diff options
| author | Ben Fuhrmannek | 2021-08-02 10:42:12 +0200 |
|---|---|---|
| committer | Ben Fuhrmannek | 2021-08-02 10:42:12 +0200 |
| commit | 4cda0120313dfd5d71236f6faf87416e93f5f89c (patch) | |
| tree | 0c2c6d15e8ac5287fb3304f96de719547d9e847a | |
| parent | 6c132e6a1d8d339a20282afb5a4af52eb6bce9db (diff) | |
| parent | e62f226c3ed885808c832040872fc2d73ca46dac (diff) | |
Merge branch 'master' of https://github.com/jvoisin/snuffleupagus
34 files changed, 441 insertions, 149 deletions
diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml new file mode 100644 index 0000000..d83aa9f --- /dev/null +++ b/.github/workflows/coverity.yml | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | name: Coverity scan | ||
| 2 | on: | ||
| 3 | schedule: | ||
| 4 | - cron: '0 18 * * 1' # Weekly at 18:00 UTC on Mondays | ||
| 5 | |||
| 6 | jobs: | ||
| 7 | latest: | ||
| 8 | runs-on: ubuntu-latest | ||
| 9 | container: debian:stable | ||
| 10 | steps: | ||
| 11 | - name: Checkout code | ||
| 12 | uses: actions/checkout@v2 | ||
| 13 | - name: Install dependencies | ||
| 14 | run: | | ||
| 15 | apt update | ||
| 16 | DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends php-dev curl ca-certificates make gcc | ||
| 17 | - name: Remove php8 tests on php7 | ||
| 18 | run: rm -rf src/tests/*php8*/ | ||
| 19 | - name: Download Coverity Build Tool | ||
| 20 | run: | | ||
| 21 | curl https://scan.coverity.com/download/linux64 --form token=$TOKEN --form project=jvoisin/snuffleupagus -o cov-analysis-linux64.tar.gz | ||
| 22 | mkdir cov-analysis-linux64 | ||
| 23 | tar xzf cov-analysis-linux64.tar.gz --strip-components=1 -C cov-analysis-linux64 | ||
| 24 | env: | ||
| 25 | TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} | ||
| 26 | - name: Configure | ||
| 27 | run: cd src; phpize; ./configure --enable-snuffleupagus; cd - | ||
| 28 | - name: Build with cov-build | ||
| 29 | run: ./cov-analysis-linux64/bin/cov-build --dir cov-int make compile_debug | ||
| 30 | - name: Submit the result to Coverity Scan | ||
| 31 | run: | | ||
| 32 | tar czf snuffleupagus.tgz cov-int | ||
| 33 | curl \ | ||
| 34 | --form project=jvoisin/snuffleupagus \ | ||
| 35 | --form token=$TOKEN \ | ||
| 36 | --form file=@snuffleupagus.tgz \ | ||
| 37 | --form version=master \ | ||
| 38 | --form email=julien.voisin+coverity@dustri.org \ | ||
| 39 | --form description=master \ | ||
| 40 | https://scan.coverity.com/builds?project=jvoisin/snuffleupagus | ||
| 41 | env: | ||
| 42 | TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} | ||
| 43 | |||
diff --git a/.github/workflows/distributions_php8.yml b/.github/workflows/distributions_php8.yml new file mode 100644 index 0000000..f055499 --- /dev/null +++ b/.github/workflows/distributions_php8.yml | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | name: CI for linux distributions, on php8 | ||
| 2 | on: ['pull_request', 'push'] | ||
| 3 | |||
| 4 | jobs: | ||
| 5 | alpine: | ||
| 6 | runs-on: ubuntu-latest | ||
| 7 | container: alpine:edge | ||
| 8 | steps: | ||
| 9 | - name: Checkout code | ||
| 10 | uses: actions/checkout@v2 | ||
| 11 | - name: Remove php7 tests for php8 | ||
| 12 | run: rm -rf src/tests/*php7*/ | ||
| 13 | - name: Remove tests failing on alpine for wathever reason | ||
| 14 | run: rm -rf src/tests/*session*/ src/tests/broken_configuration/ src/tests/*cookie* src/tests/upload_validation/ | ||
| 15 | - name: Install dependencies | ||
| 16 | run: apk add php8-dev php8-cgi php8-simplexml php8-xml pcre-dev build-base php8-pear php8-openssl | ||
| 17 | - name: Install pecl | ||
| 18 | continue-on-error: true | ||
| 19 | run: pecl install vld-beta | ||
| 20 | - name: Link phpize | ||
| 21 | run: ln -s /usr/bin/phpize8 /usr/bin/phpize | ||
| 22 | - name: Link php-config | ||
| 23 | run: ln -s /usr/bin/php-config8 /usr/bin/php-config | ||
| 24 | - name: Build and run the testsuite | ||
| 25 | continue-on-error: true | ||
| 26 | run: make tests | ||
| 27 | - name: Show logs in case of failure | ||
| 28 | if: ${{ failure() }} | ||
| 29 | continue-on-error: true | ||
| 30 | run: | | ||
| 31 | grep -r . ./src/tests/*/*.out | ||
| 32 | grep -r . ./src/tests/*/*.diff | ||
diff --git a/config/default.rules b/config/default.rules index 05dd91d..ea65e01 100644 --- a/config/default.rules +++ b/config/default.rules | |||
| @@ -33,8 +33,9 @@ sp.disable_xxe.enable(); | |||
| 33 | # https://snuffleupagus.readthedocs.io/features.html#protection-against-cross-site-request-forgery | 33 | # https://snuffleupagus.readthedocs.io/features.html#protection-against-cross-site-request-forgery |
| 34 | sp.cookie.name("PHPSESSID").samesite("lax"); | 34 | sp.cookie.name("PHPSESSID").samesite("lax"); |
| 35 | 35 | ||
| 36 | # Harden the `chmod` function | 36 | # Harden the `chmod` function (0777 (oct = 511, 0666 = 438) |
| 37 | sp.disable_function.function("chmod").param("mode").value_r("^[0-9]{2}[67]$").drop(); | 37 | sp.disable_function.function("chmod").param("mode").value("438").drop(); |
| 38 | sp.disable_function.function("chmod").param("mode").value("511").drop(); | ||
| 38 | 39 | ||
| 39 | # Prevent various `mail`-related vulnerabilities | 40 | # Prevent various `mail`-related vulnerabilities |
| 40 | sp.disable_function.function("mail").param("additional_parameters").value_r("\\-").drop(); | 41 | sp.disable_function.function("mail").param("additional_parameters").value_r("\\-").drop(); |
| @@ -96,34 +97,7 @@ sp.disable_function.function("is_callable").param("var").value("shell_exec").dro | |||
| 96 | sp.disable_function.function("is_callable").param("var").value("proc_open").drop(); | 97 | sp.disable_function.function("is_callable").param("var").value("proc_open").drop(); |
| 97 | sp.disable_function.function("is_callable").param("var").value("passthru").drop(); | 98 | sp.disable_function.function("is_callable").param("var").value("passthru").drop(); |
| 98 | 99 | ||
| 99 | # Commenting sqli related stuff to improve performance. | 100 | # Ghetto error-based sqli detection |
| 100 | # TODO figure out why these functions can't be hooked at startup | ||
| 101 | # Ghetto sqli hardening | ||
| 102 | # sp.disable_function.function("mysql_query").param("query").value_r("/\\*").drop(); | ||
| 103 | # sp.disable_function.function("mysql_query").param("query").value_r("--").drop(); | ||
| 104 | # sp.disable_function.function("mysql_query").param("query").value_r("#").drop(); | ||
| 105 | # sp.disable_function.function("mysql_query").param("query").value_r(";.*;").drop(); | ||
| 106 | # sp.disable_function.function("mysql_query").param("query").value_r("benchmark").drop(); | ||
| 107 | # sp.disable_function.function("mysql_query").param("query").value_r("sleep").drop(); | ||
| 108 | # sp.disable_function.function("mysql_query").param("query").value_r("information_schema").drop(); | ||
| 109 | |||
| 110 | # sp.disable_function.function("mysqli_query").param("query").value_r("/\\*").drop(); | ||
| 111 | # sp.disable_function.function("mysqli_query").param("query").value_r("--").drop(); | ||
| 112 | # sp.disable_function.function("mysqli_query").param("query").value_r("#").drop(); | ||
| 113 | # sp.disable_function.function("mysqli_query").param("query").value_r(";.*;").drop(); | ||
| 114 | # sp.disable_function.function("mysqli_query").param("query").value_r("benchmark").drop(); | ||
| 115 | # sp.disable_function.function("mysqli_query").param("query").value_r("sleep").drop(); | ||
| 116 | # sp.disable_function.function("mysqli_query").param("query").value_r("information_schema").drop(); | ||
| 117 | |||
| 118 | # sp.disable_function.function("PDO::query").param("query").value_r("/\\*").drop(); | ||
| 119 | # sp.disable_function.function("PDO::query").param("query").value_r("--").drop(); | ||
| 120 | # sp.disable_function.function("PDO::query").param("query").value_r("#").drop(); | ||
| 121 | # sp.disable_function.function("PDO::query").param("query").value_r(";.*;").drop(); | ||
| 122 | # sp.disable_function.function("PDO::query").param("query").value_r("benchmark\\s*\\(").drop(); | ||
| 123 | # sp.disable_function.function("PDO::query").param("query").value_r("sleep\\s*\\(").drop(); | ||
| 124 | # sp.disable_function.function("PDO::query").param("query").value_r("information_schema").drop(); | ||
| 125 | |||
| 126 | # Ghetto sqli detection | ||
| 127 | # sp.disable_function.function("mysql_query").ret("FALSE").drop(); | 101 | # sp.disable_function.function("mysql_query").ret("FALSE").drop(); |
| 128 | # sp.disable_function.function("mysqli_query").ret("FALSE").drop(); | 102 | # sp.disable_function.function("mysqli_query").ret("FALSE").drop(); |
| 129 | # sp.disable_function.function("PDO::query").ret("FALSE").drop(); | 103 | # sp.disable_function.function("PDO::query").ret("FALSE").drop(); |
diff --git a/config/default_php8.rules b/config/default_php8.rules new file mode 100644 index 0000000..c024176 --- /dev/null +++ b/config/default_php8.rules | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | # This is the default configuration file for Snuffleupagus (https://snuffleupagus.rtfd.io), | ||
| 2 | # for php8. | ||
| 3 | # It contains "reasonable" defaults that won't break your websites, | ||
| 4 | # and a lot of commented directives that you can enable if you want to | ||
| 5 | # have a better protection. | ||
| 6 | |||
| 7 | # Harden the PRNG | ||
| 8 | sp.harden_random.enable(); | ||
| 9 | |||
| 10 | # Disabled XXE | ||
| 11 | sp.disable_xxe.enable(); | ||
| 12 | |||
| 13 | # Global configuration variables | ||
| 14 | # sp.global.secret_key("YOU _DO_ NEED TO CHANGE THIS WITH SOME RANDOM CHARACTERS."); | ||
| 15 | |||
| 16 | # Globally activate strict mode | ||
| 17 | # https://secure.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration.strict | ||
| 18 | # sp.global_strict.enable(); | ||
| 19 | |||
| 20 | # Prevent unserialize-related exploits | ||
| 21 | # sp.unserialize_hmac.enable(); | ||
| 22 | |||
| 23 | # Only allow execution of read-only files. This is a low-hanging fruit that you should enable. | ||
| 24 | # sp.readonly_exec.enable(); | ||
| 25 | |||
| 26 | # Php has a lot of wrappers, most of them aren't usually useful, you should | ||
| 27 | # only enable the ones you're using. | ||
| 28 | # sp.wrappers_whitelist.list("file,php,phar"); | ||
| 29 | |||
| 30 | # Prevent sloppy comparisons. | ||
| 31 | # sp.sloppy_comparison.enable(); | ||
| 32 | |||
| 33 | # use SameSite on session cookie | ||
| 34 | # https://snuffleupagus.readthedocs.io/features.html#protection-against-cross-site-request-forgery | ||
| 35 | sp.cookie.name("PHPSESSID").samesite("lax"); | ||
| 36 | |||
| 37 | # Harden the `chmod` function (0777 (oct = 511, 0666 = 438) | ||
| 38 | sp.disable_function.function("chmod").param("permissions").value("438").drop(); | ||
| 39 | sp.disable_function.function("chmod").param("permissions").value("511").drop(); | ||
| 40 | |||
| 41 | # Prevent various `mail`-related vulnerabilities | ||
| 42 | sp.disable_function.function("mail").param("additional_parameters").value_r("\\-").drop(); | ||
| 43 | |||
| 44 | # Since it's now burned, me might as well mitigate it publicly | ||
| 45 | sp.disable_function.function("putenv").param("assignment").value_r("LD_").drop() | ||
| 46 | |||
| 47 | # This one was burned in Nov 2019 - https://gist.github.com/LoadLow/90b60bd5535d6c3927bb24d5f9955b80 | ||
| 48 | sp.disable_function.function("putenv").param("assignment").value_r("GCONV_").drop() | ||
| 49 | |||
| 50 | # Since people are stupid enough to use `extract` on things like $_GET or $_POST, we might as well mitigate this vector | ||
| 51 | sp.disable_function.function("extract").param("array").value_r("^_").drop() | ||
| 52 | sp.disable_function.function("extract").param("flags").value("0").drop() | ||
| 53 | |||
| 54 | # This is also burned: | ||
| 55 | # ini_set('open_basedir','..');chdir('..');…;chdir('..');ini_set('open_basedir','/');echo(file_get_contents('/etc/passwd')); | ||
| 56 | # Since we have no way of matching on two parameters at the same time, we're | ||
| 57 | # blocking calls to open_basedir altogether: nobody is using it via ini_set anyway. | ||
| 58 | # Moreover, there are non-public bypasses that are also using this vector ;) | ||
| 59 | sp.disable_function.function("ini_set").param("option").value_r("open_basedir").drop() | ||
| 60 | |||
| 61 | ##Prevent various `include`-related vulnerabilities | ||
| 62 | sp.disable_function.function("require_once").value_r("\.(inc|phtml|php)$").allow(); | ||
| 63 | sp.disable_function.function("include_once").value_r("\.(inc|phtml|php)$").allow(); | ||
| 64 | sp.disable_function.function("require").value_r("\.(inc|phtml|php)$").allow(); | ||
| 65 | sp.disable_function.function("include").value_r("\.(inc|phtml|php)$").allow(); | ||
| 66 | sp.disable_function.function("require_once").drop() | ||
| 67 | sp.disable_function.function("include_once").drop() | ||
| 68 | sp.disable_function.function("require").drop() | ||
| 69 | sp.disable_function.function("include").drop() | ||
| 70 | |||
| 71 | # Prevent `system`-related injections | ||
| 72 | sp.disable_function.function("system").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); | ||
| 73 | sp.disable_function.function("shell_exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); | ||
| 74 | sp.disable_function.function("exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); | ||
| 75 | sp.disable_function.function("proc_open").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); | ||
| 76 | |||
| 77 | # Prevent runtime modification of interesting things | ||
| 78 | sp.disable_function.function("ini_set").param("option").value("assert.active").drop(); | ||
| 79 | sp.disable_function.function("ini_set").param("option").value("zend.assertions").drop(); | ||
| 80 | sp.disable_function.function("ini_set").param("option").value("memory_limit").drop(); | ||
| 81 | sp.disable_function.function("ini_set").param("option").value("include_path").drop(); | ||
| 82 | sp.disable_function.function("ini_set").param("option").value("open_basedir").drop(); | ||
| 83 | |||
| 84 | # Detect some backdoors via environment recon | ||
| 85 | sp.disable_function.function("ini_get").param("option").value("allow_url_fopen").drop(); | ||
| 86 | sp.disable_function.function("ini_get").param("option").value("open_basedir").drop(); | ||
| 87 | sp.disable_function.function("ini_get").param("option").value_r("suhosin").drop(); | ||
| 88 | sp.disable_function.function("function_exists").param("function").value("eval").drop(); | ||
| 89 | sp.disable_function.function("function_exists").param("function").value("exec").drop(); | ||
| 90 | sp.disable_function.function("function_exists").param("function").value("system").drop(); | ||
| 91 | sp.disable_function.function("function_exists").param("function").value("shell_exec").drop(); | ||
| 92 | sp.disable_function.function("function_exists").param("function").value("proc_open").drop(); | ||
| 93 | sp.disable_function.function("function_exists").param("function").value("passthru").drop(); | ||
| 94 | sp.disable_function.function("is_callable").param("value").value("eval").drop(); | ||
| 95 | sp.disable_function.function("is_callable").param("value").value("exec").drop(); | ||
| 96 | sp.disable_function.function("is_callable").param("value").value("system").drop(); | ||
| 97 | sp.disable_function.function("is_callable").param("value").value("shell_exec").drop(); | ||
| 98 | sp.disable_function.function("is_callable").param("value").value("proc_open").drop(); | ||
| 99 | sp.disable_function.function("is_callable").param("value").value("passthru").drop(); | ||
| 100 | |||
| 101 | # Ghetto error-based sqli detection | ||
| 102 | # sp.disable_function.function("mysql_query").ret("FALSE").drop(); | ||
| 103 | # sp.disable_function.function("mysqli_query").ret("FALSE").drop(); | ||
| 104 | # sp.disable_function.function("PDO::query").ret("FALSE").drop(); | ||
| 105 | |||
| 106 | # Ensure that certificates are properly verified | ||
| 107 | sp.disable_function.function("curl_setopt").param("value").value("1").allow(); | ||
| 108 | sp.disable_function.function("curl_setopt").param("value").value("2").allow(); | ||
| 109 | # `81` is SSL_VERIFYHOST and `64` SSL_VERIFYPEER | ||
| 110 | sp.disable_function.function("curl_setopt").param("option").value("64").drop().alias("Please don't turn CURLOPT_SSL_VERIFYCLIENT off."); | ||
| 111 | sp.disable_function.function("curl_setopt").param("option").value("81").drop().alias("Please don't turn CURLOPT_SSL_VERIFYHOST off."); | ||
| 112 | |||
| 113 | # File upload | ||
| 114 | sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ph").drop(); | ||
| 115 | sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ht").drop(); | ||
| 116 | |||
| 117 | # Logging lockdown | ||
| 118 | sp.disable_function.function("ini_set").param("option").value_r("error_log").drop() | ||
| 119 | sp.disable_function.function("ini_set").param("option").value_r("error_reporting").drop() | ||
| 120 | sp.disable_function.function("ini_set").param("option").value_r("display_errors").drop() | ||
diff --git a/debian/control b/debian/control index 6e48b93..9e313b6 100644 --- a/debian/control +++ b/debian/control | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | Source: snuffleupagus | 1 | Source: snuffleupagus |
| 2 | Priority: optional | 2 | Priority: optional |
| 3 | Maintainer: Julien (jvoisin) Voisin <julien.voisin+snuffleupagus@dustri.org> | 3 | Maintainer: Julien (jvoisin) Voisin <julien.voisin+snuffleupagus@dustri.org> |
| 4 | Build-Depends: debhelper (>= 9), php-curl, php-xml, php7.0-dev | php7.1-dev | php7.2-dev | php7.3-dev | php7.4-dev | 4 | Build-Depends: debhelper (>= 9), php-curl, php-xml, php7.0-dev | php7.1-dev | php7.2-dev | php7.3-dev | php7.4-dev | php8.0-dev |
| 5 | Standards-Version: 4.1.3 | 5 | Standards-Version: 4.1.3 |
| 6 | Homepage: https://github.com/jvoisin/snuffleupagus | 6 | Homepage: https://github.com/jvoisin/snuffleupagus |
| 7 | Section: php | 7 | Section: php |
diff --git a/doc/source/config.rst b/doc/source/config.rst index 258b1ab..84e3fa9 100644 --- a/doc/source/config.rst +++ b/doc/source/config.rst | |||
| @@ -164,6 +164,12 @@ It can either be ``enabled`` or ``disabled`` and can be used in ``simulation`` m | |||
| 164 | sp.unserialize_hmac.enable(); | 164 | sp.unserialize_hmac.enable(); |
| 165 | sp.unserialize_hmac.disable(); | 165 | sp.unserialize_hmac.disable(); |
| 166 | 166 | ||
| 167 | |||
| 168 | .. warning:: | ||
| 169 | |||
| 170 | This feature breaks web applications doing checks on the serialized | ||
| 171 | representation of data on their own, like `WordPress <https://wordpress.com/>`__. | ||
| 172 | |||
| 167 | .. _config_cookie-encryption: | 173 | .. _config_cookie-encryption: |
| 168 | 174 | ||
| 169 | Cookies-related mitigations | 175 | Cookies-related mitigations |
diff --git a/doc/source/features.rst b/doc/source/features.rst index 2eebc88..25fd62d 100644 --- a/doc/source/features.rst +++ b/doc/source/features.rst | |||
| @@ -480,15 +480,9 @@ to see that people are disabling it on production too. | |||
| 480 | We're detecting/preventing this by not allowing the ``CURLOPT_SSL_VERIFYPEER`` and | 480 | We're detecting/preventing this by not allowing the ``CURLOPT_SSL_VERIFYPEER`` and |
| 481 | ``CURLOPT_SSL_VERIFYHOST`` options from being set to ``0``. | 481 | ``CURLOPT_SSL_VERIFYHOST`` options from being set to ``0``. |
| 482 | 482 | ||
| 483 | *Cheap* SQL injections detection | 483 | *Cheap* error-based SQL injections detection |
| 484 | """""""""""""""""""""""""""""""" | 484 | """""""""""""""""""""""""""""""""""""""""""" |
| 485 | 485 | ||
| 486 | In some SQL injections, attackers might need to use comments, a feature that is | 486 | If a function performing a SQL query returns ``FALSE`` |
| 487 | often not used in production system, so it might be a good idea to filter | ||
| 488 | queries that contains some. The same filtering idea can be used against | ||
| 489 | SQL functions that are frequently used in SQL injections, like ``sleep``, ``benchmark`` | ||
| 490 | or strings like ``version_info``. | ||
| 491 | |||
| 492 | On the topic of SQL injections, if a function performing a query returns ``FALSE`` | ||
| 493 | (indicating an error), it might be useful to dump the request for further analysis. | 487 | (indicating an error), it might be useful to dump the request for further analysis. |
| 494 | 488 | ||
diff --git a/doc/source/papers.rst b/doc/source/papers.rst index 3cdb909..35905dd 100644 --- a/doc/source/papers.rst +++ b/doc/source/papers.rst | |||
| @@ -101,6 +101,7 @@ Articles | |||
| 101 | """" | 101 | """" |
| 102 | 102 | ||
| 103 | - `Sortie de Snuffleupagus 0.7.0 - Los Elefantes <https://linuxfr.org/news/sortie-de-snuffleupagus-0-7-0-los-elefantes>`__ (fr) - linuxfr | 103 | - `Sortie de Snuffleupagus 0.7.0 - Los Elefantes <https://linuxfr.org/news/sortie-de-snuffleupagus-0-7-0-los-elefantes>`__ (fr) - linuxfr |
| 104 | - `Virtual patching CVE-2021-29447 with Snuffleupagus <https://dustri.org/b/virtual-patching-cve-2021-29447-with-snuffleupagus.html>`__ - dustri.org | ||
| 104 | 105 | ||
| 105 | 106 | ||
| 106 | Papers | 107 | Papers |
diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h index 248045c..5b2b414 100644 --- a/src/php_snuffleupagus.h +++ b/src/php_snuffleupagus.h | |||
| @@ -56,7 +56,7 @@ typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS); | |||
| 56 | #define TSRMLS_FETCH() | 56 | #define TSRMLS_FETCH() |
| 57 | #define TSRMLS_C | 57 | #define TSRMLS_C |
| 58 | #else | 58 | #else |
| 59 | #if ( !HAVE_PCRE && !HAVE_BUNDLED_PCRE ) | 59 | #if (!HAVE_PCRE && !HAVE_BUNDLED_PCRE) |
| 60 | #error Snuffleupagus requires PHP7+ with PCRE support | 60 | #error Snuffleupagus requires PHP7+ with PCRE support |
| 61 | #endif | 61 | #endif |
| 62 | #endif | 62 | #endif |
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index 9a5ac90..7bf3649 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c | |||
| @@ -21,7 +21,7 @@ ZEND_DLEXPORT int sp_zend_startup(zend_extension *extension) { | |||
| 21 | } | 21 | } |
| 22 | // LCOV_EXCL_END | 22 | // LCOV_EXCL_END |
| 23 | 23 | ||
| 24 | static inline void sp_op_array_handler(zend_op_array *op) { | 24 | static inline void sp_op_array_handler(zend_op_array *const op) { |
| 25 | // We need a filename, and strict mode not already enabled on this op | 25 | // We need a filename, and strict mode not already enabled on this op |
| 26 | if (NULL == op->filename || op->fn_flags & ZEND_ACC_STRICT_TYPES) { | 26 | if (NULL == op->filename || op->fn_flags & ZEND_ACC_STRICT_TYPES) { |
| 27 | return; | 27 | return; |
| @@ -47,8 +47,7 @@ static PHP_INI_MH(StrictMode) { | |||
| 47 | PHP_INI_BEGIN() | 47 | PHP_INI_BEGIN() |
| 48 | PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, | 48 | PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, |
| 49 | OnUpdateConfiguration) | 49 | OnUpdateConfiguration) |
| 50 | PHP_INI_ENTRY("sp.allow_broken_configuration", "0", PHP_INI_SYSTEM, | 50 | PHP_INI_ENTRY("sp.allow_broken_configuration", "0", PHP_INI_SYSTEM, StrictMode) |
| 51 | StrictMode) | ||
| 52 | PHP_INI_END() | 51 | PHP_INI_END() |
| 53 | 52 | ||
| 54 | ZEND_DLEXPORT zend_extension zend_extension_entry = { | 53 | ZEND_DLEXPORT zend_extension zend_extension_entry = { |
| @@ -59,24 +58,24 @@ ZEND_DLEXPORT zend_extension zend_extension_entry = { | |||
| 59 | PHP_SNUFFLEUPAGUS_COPYRIGHT, | 58 | PHP_SNUFFLEUPAGUS_COPYRIGHT, |
| 60 | sp_zend_startup, | 59 | sp_zend_startup, |
| 61 | NULL, | 60 | NULL, |
| 62 | NULL, /* activate_func_t */ | 61 | NULL, /* activate_func_t */ |
| 63 | NULL, /* deactivate_func_t */ | 62 | NULL, /* deactivate_func_t */ |
| 64 | NULL, /* message_handler_func_t */ | 63 | NULL, /* message_handler_func_t */ |
| 65 | sp_op_array_handler, /* op_array_handler_func_t */ | 64 | sp_op_array_handler, /* op_array_handler_func_t */ |
| 66 | NULL, /* statement_handler_func_t */ | 65 | NULL, /* statement_handler_func_t */ |
| 67 | NULL, /* fcall_begin_handler_func_t */ | 66 | NULL, /* fcall_begin_handler_func_t */ |
| 68 | NULL, /* fcall_end_handler_func_t */ | 67 | NULL, /* fcall_end_handler_func_t */ |
| 69 | NULL, /* op_array_ctor_func_t */ | 68 | NULL, /* op_array_ctor_func_t */ |
| 70 | NULL, /* op_array_dtor_func_t */ | 69 | NULL, /* op_array_dtor_func_t */ |
| 71 | STANDARD_ZEND_EXTENSION_PROPERTIES}; | 70 | STANDARD_ZEND_EXTENSION_PROPERTIES}; |
| 72 | 71 | ||
| 73 | PHP_GINIT_FUNCTION(snuffleupagus) { | 72 | PHP_GINIT_FUNCTION(snuffleupagus) { |
| 74 | snuffleupagus_globals->is_config_valid = SP_CONFIG_NONE; | 73 | snuffleupagus_globals->is_config_valid = SP_CONFIG_NONE; |
| 75 | snuffleupagus_globals->in_eval = 0; | 74 | snuffleupagus_globals->in_eval = 0; |
| 76 | 75 | ||
| 77 | #define SP_INIT_HT(F) snuffleupagus_globals->F = \ | 76 | #define SP_INIT_HT(F) \ |
| 78 | pemalloc(sizeof(*(snuffleupagus_globals->F)), 1); \ | 77 | snuffleupagus_globals->F = pemalloc(sizeof(*(snuffleupagus_globals->F)), 1); \ |
| 79 | zend_hash_init(snuffleupagus_globals->F, 10, NULL, NULL, 1); | 78 | zend_hash_init(snuffleupagus_globals->F, 10, NULL, NULL, 1); |
| 80 | SP_INIT_HT(disabled_functions_hook); | 79 | SP_INIT_HT(disabled_functions_hook); |
| 81 | SP_INIT_HT(sp_internal_functions_hook); | 80 | SP_INIT_HT(sp_internal_functions_hook); |
| 82 | SP_INIT_HT(sp_eval_blacklist_functions_hook); | 81 | SP_INIT_HT(sp_eval_blacklist_functions_hook); |
| @@ -86,8 +85,9 @@ PHP_GINIT_FUNCTION(snuffleupagus) { | |||
| 86 | SP_INIT_HT(config.config_disabled_functions_ret_hooked); | 85 | SP_INIT_HT(config.config_disabled_functions_ret_hooked); |
| 87 | #undef SP_INIT_HT | 86 | #undef SP_INIT_HT |
| 88 | 87 | ||
| 89 | #define SP_INIT(F) snuffleupagus_globals->config.F = \ | 88 | #define SP_INIT(F) \ |
| 90 | pecalloc(sizeof(*(snuffleupagus_globals->config.F)), 1, 1); | 89 | snuffleupagus_globals->config.F = \ |
| 90 | pecalloc(sizeof(*(snuffleupagus_globals->config.F)), 1, 1); | ||
| 91 | SP_INIT(config_unserialize); | 91 | SP_INIT(config_unserialize); |
| 92 | SP_INIT(config_random); | 92 | SP_INIT(config_random); |
| 93 | SP_INIT(config_sloppy); | 93 | SP_INIT(config_sloppy); |
| @@ -121,23 +121,22 @@ PHP_MINIT_FUNCTION(snuffleupagus) { | |||
| 121 | return SUCCESS; | 121 | return SUCCESS; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | static void free_disabled_functions_hashtable(HashTable *ht) { | 124 | static void free_disabled_functions_hashtable(HashTable *const ht) { |
| 125 | void *ptr = NULL; | 125 | void *ptr = NULL; |
| 126 | ZEND_HASH_FOREACH_PTR(ht, ptr) { sp_list_free(ptr); } | 126 | ZEND_HASH_FOREACH_PTR(ht, ptr) { sp_list_free(ptr); } |
| 127 | ZEND_HASH_FOREACH_END(); | 127 | ZEND_HASH_FOREACH_END(); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { | 130 | PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { |
| 131 | |||
| 132 | #define FREE_HT(F) \ | 131 | #define FREE_HT(F) \ |
| 133 | zend_hash_destroy(SNUFFLEUPAGUS_G(F)); \ | 132 | zend_hash_destroy(SNUFFLEUPAGUS_G(F)); \ |
| 134 | pefree(SNUFFLEUPAGUS_G(F), 1); | 133 | pefree(SNUFFLEUPAGUS_G(F), 1); |
| 135 | FREE_HT(disabled_functions_hook); | 134 | FREE_HT(disabled_functions_hook); |
| 136 | FREE_HT(sp_eval_blacklist_functions_hook); | 135 | FREE_HT(sp_eval_blacklist_functions_hook); |
| 137 | 136 | ||
| 138 | #define FREE_HT_LIST(F) \ | 137 | #define FREE_HT_LIST(F) \ |
| 139 | free_disabled_functions_hashtable(SNUFFLEUPAGUS_G(config).F); \ | 138 | free_disabled_functions_hashtable(SNUFFLEUPAGUS_G(config).F); \ |
| 140 | FREE_HT(config.F); | 139 | FREE_HT(config.F); |
| 141 | FREE_HT_LIST(config_disabled_functions); | 140 | FREE_HT_LIST(config_disabled_functions); |
| 142 | FREE_HT_LIST(config_disabled_functions_hooked); | 141 | FREE_HT_LIST(config_disabled_functions_hooked); |
| 143 | FREE_HT_LIST(config_disabled_functions_ret); | 142 | FREE_HT_LIST(config_disabled_functions_ret); |
| @@ -145,18 +144,21 @@ PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { | |||
| 145 | #undef FREE_HT_LIST | 144 | #undef FREE_HT_LIST |
| 146 | #undef FREE_HT | 145 | #undef FREE_HT |
| 147 | 146 | ||
| 148 | #define FREE_LST_DISABLE(L) \ | 147 | #define FREE_LST_DISABLE(L) \ |
| 149 | do { \ | 148 | do { \ |
| 150 | sp_list_node *_n = SNUFFLEUPAGUS_G(config).L; \ | 149 | sp_list_node *_n = SNUFFLEUPAGUS_G(config).L; \ |
| 151 | sp_disabled_function_list_free(_n); \ | 150 | sp_disabled_function_list_free(_n); \ |
| 152 | sp_list_free(_n); \ | 151 | sp_list_free(_n); \ |
| 153 | } while (0) | 152 | } while (0) |
| 154 | FREE_LST_DISABLE(config_disabled_functions_reg->disabled_functions); | 153 | FREE_LST_DISABLE(config_disabled_functions_reg->disabled_functions); |
| 155 | FREE_LST_DISABLE(config_disabled_functions_reg_ret->disabled_functions); | 154 | FREE_LST_DISABLE(config_disabled_functions_reg_ret->disabled_functions); |
| 156 | #undef FREE_LST_DISABLE | 155 | #undef FREE_LST_DISABLE |
| 157 | 156 | ||
| 157 | sp_list_node *_n = SNUFFLEUPAGUS_G(config).config_cookie->cookies; | ||
| 158 | sp_cookie_list_free(_n); | ||
| 159 | sp_list_free(_n); | ||
| 160 | |||
| 158 | #define FREE_LST(L) sp_list_free(SNUFFLEUPAGUS_G(config).L); | 161 | #define FREE_LST(L) sp_list_free(SNUFFLEUPAGUS_G(config).L); |
| 159 | FREE_LST(config_cookie->cookies); | ||
| 160 | FREE_LST(config_eval->blacklist); | 162 | FREE_LST(config_eval->blacklist); |
| 161 | FREE_LST(config_eval->whitelist); | 163 | FREE_LST(config_eval->whitelist); |
| 162 | FREE_LST(config_wrapper->whitelist); | 164 | FREE_LST(config_wrapper->whitelist); |
| @@ -184,24 +186,26 @@ PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { | |||
| 184 | } | 186 | } |
| 185 | 187 | ||
| 186 | PHP_RINIT_FUNCTION(snuffleupagus) { | 188 | PHP_RINIT_FUNCTION(snuffleupagus) { |
| 187 | const sp_config_wrapper* config_wrapper = | 189 | const sp_config_wrapper *const config_wrapper = |
| 188 | SNUFFLEUPAGUS_G(config).config_wrapper; | 190 | SNUFFLEUPAGUS_G(config).config_wrapper; |
| 189 | #if defined(COMPILE_DL_SNUFFLEUPAGUS) && defined(ZTS) | 191 | #if defined(COMPILE_DL_SNUFFLEUPAGUS) && defined(ZTS) |
| 190 | ZEND_TSRMLS_CACHE_UPDATE(); | 192 | ZEND_TSRMLS_CACHE_UPDATE(); |
| 191 | #endif | 193 | #endif |
| 192 | 194 | ||
| 193 | if (!SNUFFLEUPAGUS_G(allow_broken_configuration)) { | 195 | if (!SNUFFLEUPAGUS_G(allow_broken_configuration)) { |
| 194 | if (SNUFFLEUPAGUS_G(is_config_valid) == SP_CONFIG_INVALID ) { | 196 | if (SNUFFLEUPAGUS_G(is_config_valid) == SP_CONFIG_INVALID) { |
| 195 | sp_log_err("config", "Invalid configuration file"); | 197 | sp_log_err("config", "Invalid configuration file"); |
| 196 | } else if (SNUFFLEUPAGUS_G(is_config_valid) == SP_CONFIG_NONE) { | 198 | } else if (SNUFFLEUPAGUS_G(is_config_valid) == SP_CONFIG_NONE) { |
| 197 | sp_log_warn("config", "No configuration specificed via sp.configuration_file"); | 199 | sp_log_warn("config", |
| 200 | "No configuration specificed via sp.configuration_file"); | ||
| 198 | } | 201 | } |
| 199 | } | 202 | } |
| 200 | 203 | ||
| 201 | // We need to disable wrappers loaded by extensions loaded after SNUFFLEUPAGUS. | 204 | // We need to disable wrappers loaded by extensions loaded after |
| 205 | // SNUFFLEUPAGUS. | ||
| 202 | if (config_wrapper->enabled && | 206 | if (config_wrapper->enabled && |
| 203 | zend_hash_num_elements(php_stream_get_url_stream_wrappers_hash()) != | 207 | zend_hash_num_elements(php_stream_get_url_stream_wrappers_hash()) != |
| 204 | config_wrapper->num_wrapper) { | 208 | config_wrapper->num_wrapper) { |
| 205 | sp_disable_wrapper(); | 209 | sp_disable_wrapper(); |
| 206 | } | 210 | } |
| 207 | 211 | ||
| @@ -218,7 +222,7 @@ PHP_RSHUTDOWN_FUNCTION(snuffleupagus) { return SUCCESS; } | |||
| 218 | 222 | ||
| 219 | PHP_MINFO_FUNCTION(snuffleupagus) { | 223 | PHP_MINFO_FUNCTION(snuffleupagus) { |
| 220 | const char *valid_config; | 224 | const char *valid_config; |
| 221 | switch(SNUFFLEUPAGUS_G(is_config_valid)) { | 225 | switch (SNUFFLEUPAGUS_G(is_config_valid)) { |
| 222 | case SP_CONFIG_VALID: | 226 | case SP_CONFIG_VALID: |
| 223 | valid_config = "yes"; | 227 | valid_config = "yes"; |
| 224 | break; | 228 | break; |
| @@ -230,10 +234,11 @@ PHP_MINFO_FUNCTION(snuffleupagus) { | |||
| 230 | valid_config = "no"; | 234 | valid_config = "no"; |
| 231 | } | 235 | } |
| 232 | php_info_print_table_start(); | 236 | php_info_print_table_start(); |
| 233 | php_info_print_table_row(2, "snuffleupagus support", | 237 | php_info_print_table_row( |
| 234 | SNUFFLEUPAGUS_G(is_config_valid)?"enabled":"disabled"); | 238 | 2, "snuffleupagus support", |
| 239 | SNUFFLEUPAGUS_G(is_config_valid) ? "enabled" : "disabled"); | ||
| 235 | php_info_print_table_row(2, "Version", PHP_SNUFFLEUPAGUS_VERSION); | 240 | php_info_print_table_row(2, "Version", PHP_SNUFFLEUPAGUS_VERSION); |
| 236 | php_info_print_table_row( 2, "Valid config", valid_config); | 241 | php_info_print_table_row(2, "Valid config", valid_config); |
| 237 | php_info_print_table_end(); | 242 | php_info_print_table_end(); |
| 238 | DISPLAY_INI_ENTRIES(); | 243 | DISPLAY_INI_ENTRIES(); |
| 239 | } | 244 | } |
| @@ -245,14 +250,15 @@ static PHP_INI_MH(OnUpdateConfiguration) { | |||
| 245 | return FAILURE; | 250 | return FAILURE; |
| 246 | } | 251 | } |
| 247 | 252 | ||
| 248 | glob_t globbuf; | 253 | char *str = new_value->val; |
| 249 | char *config_file; | ||
| 250 | char *rest = new_value->val; | ||
| 251 | 254 | ||
| 252 | while ((config_file = strtok_r(rest, ",", &rest))) { | 255 | while (1) { |
| 253 | int ret = glob(config_file, GLOB_NOCHECK, NULL, &globbuf); | 256 | // We don't care about overwriting new_value->val |
| 257 | const char *config_file = strsep(&str, ","); | ||
| 258 | if (config_file == NULL) break; | ||
| 254 | 259 | ||
| 255 | if (ret != 0) { | 260 | glob_t globbuf; |
| 261 | if (0 != glob(config_file, GLOB_NOCHECK, NULL, &globbuf)) { | ||
| 256 | SNUFFLEUPAGUS_G(is_config_valid) = SP_CONFIG_INVALID; | 262 | SNUFFLEUPAGUS_G(is_config_valid) = SP_CONFIG_INVALID; |
| 257 | globfree(&globbuf); | 263 | globfree(&globbuf); |
| 258 | return FAILURE; | 264 | return FAILURE; |
| @@ -315,11 +321,12 @@ static PHP_INI_MH(OnUpdateConfiguration) { | |||
| 315 | 321 | ||
| 316 | // If `zend_write_default` is not NULL it is already hooked. | 322 | // If `zend_write_default` is not NULL it is already hooked. |
| 317 | if ((zend_hash_str_find( | 323 | if ((zend_hash_str_find( |
| 318 | SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked, "echo", | 324 | SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked, "echo", |
| 319 | sizeof("echo") - 1) || | 325 | sizeof("echo") - 1) || |
| 320 | zend_hash_str_find( | 326 | zend_hash_str_find( |
| 321 | SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked, "echo", | 327 | SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked, "echo", |
| 322 | sizeof("echo") - 1)) && NULL == zend_write_default) { | 328 | sizeof("echo") - 1)) && |
| 329 | NULL == zend_write_default && zend_write != hook_echo) { | ||
| 323 | zend_write_default = zend_write; | 330 | zend_write_default = zend_write; |
| 324 | zend_write = hook_echo; | 331 | zend_write = hook_echo; |
| 325 | } | 332 | } |
diff --git a/src/sp_config.c b/src/sp_config.c index 69730e3..c12b435 100644 --- a/src/sp_config.c +++ b/src/sp_config.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | size_t sp_line_no; | 7 | size_t sp_line_no; |
| 8 | 8 | ||
| 9 | sp_config_tokens const sp_func[] = { | 9 | static sp_config_tokens const sp_func[] = { |
| 10 | {.func = parse_unserialize, .token = SP_TOKEN_UNSERIALIZE_HMAC}, | 10 | {.func = parse_unserialize, .token = SP_TOKEN_UNSERIALIZE_HMAC}, |
| 11 | {.func = parse_random, .token = SP_TOKEN_HARDEN_RANDOM}, | 11 | {.func = parse_random, .token = SP_TOKEN_HARDEN_RANDOM}, |
| 12 | {.func = parse_log_media, .token = SP_TOKEN_LOG_MEDIA}, | 12 | {.func = parse_log_media, .token = SP_TOKEN_LOG_MEDIA}, |
| @@ -73,7 +73,11 @@ int parse_list(char *restrict line, char *restrict keyword, void *list_ptr) { | |||
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | tmp = ZSTR_VAL(value); | 75 | tmp = ZSTR_VAL(value); |
| 76 | while ((token = strtok_r(tmp, ",", &tmp))) { | 76 | while (1) { |
| 77 | token = strsep(&tmp, ","); | ||
| 78 | if (token == NULL) { | ||
| 79 | break; | ||
| 80 | } | ||
| 77 | *list = sp_list_insert(*list, zend_string_init(token, strlen(token), 1)); | 81 | *list = sp_list_insert(*list, zend_string_init(token, strlen(token), 1)); |
| 78 | } | 82 | } |
| 79 | 83 | ||
| @@ -216,11 +220,32 @@ void sp_disabled_function_list_free(sp_list_node *list) { | |||
| 216 | sp_list_node *cursor = list; | 220 | sp_list_node *cursor = list; |
| 217 | while (cursor) { | 221 | while (cursor) { |
| 218 | sp_disabled_function *df = cursor->data; | 222 | sp_disabled_function *df = cursor->data; |
| 219 | if (df && df->functions_list) sp_list_free(df->functions_list); | ||
| 220 | if (df) { | 223 | if (df) { |
| 224 | sp_list_free(df->functions_list); | ||
| 225 | sp_list_free(df->param_array_keys); | ||
| 226 | sp_list_free(df->var_array_keys); | ||
| 227 | |||
| 228 | sp_pcre_free(df->r_filename); | ||
| 229 | sp_pcre_free(df->r_function); | ||
| 230 | sp_pcre_free(df->r_param); | ||
| 231 | sp_pcre_free(df->r_ret); | ||
| 232 | sp_pcre_free(df->r_value); | ||
| 233 | sp_pcre_free(df->r_key); | ||
| 234 | |||
| 221 | sp_tree_free(df->param); | 235 | sp_tree_free(df->param); |
| 222 | sp_tree_free(df->var); | 236 | sp_tree_free(df->var); |
| 223 | } | 237 | } |
| 224 | cursor = cursor->next; | 238 | cursor = cursor->next; |
| 225 | } | 239 | } |
| 226 | } | 240 | } |
| 241 | |||
| 242 | void sp_cookie_list_free(sp_list_node *list) { | ||
| 243 | sp_list_node *cursor = list; | ||
| 244 | while (cursor) { | ||
| 245 | sp_cookie *c = cursor->data; | ||
| 246 | if (c) { | ||
| 247 | sp_pcre_free(c->name_r); | ||
| 248 | } | ||
| 249 | cursor = cursor->next; | ||
| 250 | } | ||
| 251 | } | ||
diff --git a/src/sp_config.h b/src/sp_config.h index b06e8be..e7b1473 100644 --- a/src/sp_config.h +++ b/src/sp_config.h | |||
| @@ -282,5 +282,6 @@ int parse_list(char *restrict, char *restrict, void *); | |||
| 282 | 282 | ||
| 283 | // cleanup | 283 | // cleanup |
| 284 | void sp_disabled_function_list_free(sp_list_node *); | 284 | void sp_disabled_function_list_free(sp_list_node *); |
| 285 | void sp_cookie_list_free(sp_list_node *); | ||
| 285 | 286 | ||
| 286 | #endif /* SP_CONFIG_H */ | 287 | #endif /* SP_CONFIG_H */ |
diff --git a/src/sp_disable_xxe.c b/src/sp_disable_xxe.c index 113d84b..f9712b5 100644 --- a/src/sp_disable_xxe.c +++ b/src/sp_disable_xxe.c | |||
| @@ -1,26 +1,41 @@ | |||
| 1 | #include "php_snuffleupagus.h" | 1 | #include "php_snuffleupagus.h" |
| 2 | 2 | ||
| 3 | PHP_FUNCTION(sp_libxml_disable_entity_loader) { RETURN_TRUE; } | 3 | PHP_FUNCTION(sp_libxml_disable_entity_loader) { |
| 4 | sp_log_warn("xxe", | ||
| 5 | "A call to libxml_disable_entity_loader was tried and nopped"); | ||
| 6 | RETURN_TRUE; | ||
| 7 | } | ||
| 8 | |||
| 9 | PHP_FUNCTION(sp_libxml_set_external_entity_loader) { | ||
| 10 | sp_log_warn( | ||
| 11 | "xxe", | ||
| 12 | "A call to libxml_set_external_entity_loader was tried and nopped"); | ||
| 13 | RETURN_TRUE; | ||
| 14 | } | ||
| 4 | 15 | ||
| 5 | int hook_libxml_disable_entity_loader() { | 16 | int hook_libxml_disable_entity_loader() { |
| 6 | TSRMLS_FETCH(); | 17 | TSRMLS_FETCH(); |
| 7 | 18 | ||
| 8 | // External entities are disabled by default in PHP8+ | ||
| 9 | #if PHP_VERSION_ID < 80000 | ||
| 10 | /* Call the php function here instead of re-implementing it is a bit | ||
| 11 | * ugly, but we do not want to introduce compile-time dependencies against | ||
| 12 | * libxml. */ | ||
| 13 | zval func_name; | 19 | zval func_name; |
| 14 | zval hmac; | 20 | zval retval; |
| 15 | zval params[1]; | 21 | zval params[1]; |
| 16 | 22 | ||
| 23 | #if PHP_VERSION_ID < 80000 | ||
| 24 | // This function is deprecated in PHP8, but better safe than sorry for php7. | ||
| 17 | ZVAL_STRING(&func_name, "libxml_disable_entity_loader"); | 25 | ZVAL_STRING(&func_name, "libxml_disable_entity_loader"); |
| 18 | ZVAL_STRING(¶ms[0], "true"); | 26 | ZVAL_STRING(¶ms[0], "true"); |
| 19 | call_user_function(CG(function_table), NULL, &func_name, &hmac, 1, params); | 27 | call_user_function(CG(function_table), NULL, &func_name, &retval, 1, params); |
| 20 | #endif | 28 | #endif |
| 21 | 29 | ||
| 30 | // This is now the recommended way to disable external entities | ||
| 31 | ZVAL_STRING(&func_name, "libxml_set_external_entity_loader"); | ||
| 32 | ZVAL_NULL(¶ms[0]); | ||
| 33 | call_user_function(CG(function_table), NULL, &func_name, &retval, 1, params); | ||
| 34 | |||
| 22 | HOOK_FUNCTION("libxml_disable_entity_loader", sp_internal_functions_hook, | 35 | HOOK_FUNCTION("libxml_disable_entity_loader", sp_internal_functions_hook, |
| 23 | PHP_FN(sp_libxml_disable_entity_loader)); | 36 | PHP_FN(sp_libxml_disable_entity_loader)); |
| 37 | HOOK_FUNCTION("libxml_set_external_entity_loader", sp_internal_functions_hook, | ||
| 38 | PHP_FN(sp_libxml_set_external_entity_loader)); | ||
| 24 | 39 | ||
| 25 | return SUCCESS; | 40 | return SUCCESS; |
| 26 | } | 41 | } |
diff --git a/src/sp_execute.c b/src/sp_execute.c index de83a2a..7d078b0 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c | |||
| @@ -274,17 +274,23 @@ int hook_execute(void) { | |||
| 274 | TSRMLS_FETCH(); | 274 | TSRMLS_FETCH(); |
| 275 | 275 | ||
| 276 | if (NULL == orig_execute_ex && NULL == orig_zend_stream_open) { | 276 | if (NULL == orig_execute_ex && NULL == orig_zend_stream_open) { |
| 277 | /* zend_execute_ex is used for "user" function calls */ | 277 | if (zend_execute_ex != sp_execute_ex) { |
| 278 | orig_execute_ex = zend_execute_ex; | 278 | /* zend_execute_ex is used for "user" function calls */ |
| 279 | zend_execute_ex = sp_execute_ex; | 279 | orig_execute_ex = zend_execute_ex; |
| 280 | zend_execute_ex = sp_execute_ex; | ||
| 281 | } | ||
| 280 | 282 | ||
| 281 | /* zend_execute_internal is used for "builtin" functions calls */ | 283 | if (zend_execute_internal != sp_zend_execute_internal) { |
| 282 | orig_zend_execute_internal = zend_execute_internal; | 284 | /* zend_execute_internal is used for "builtin" functions calls */ |
| 283 | zend_execute_internal = sp_zend_execute_internal; | 285 | orig_zend_execute_internal = zend_execute_internal; |
| 286 | zend_execute_internal = sp_zend_execute_internal; | ||
| 287 | } | ||
| 284 | 288 | ||
| 285 | /* zend_stream_open_function is used for include-related stuff */ | 289 | if (zend_stream_open_function != sp_stream_open) { |
| 286 | orig_zend_stream_open = zend_stream_open_function; | 290 | /* zend_stream_open_function is used for include-related stuff */ |
| 287 | zend_stream_open_function = sp_stream_open; | 291 | orig_zend_stream_open = zend_stream_open_function; |
| 292 | zend_stream_open_function = sp_stream_open; | ||
| 293 | } | ||
| 288 | } | 294 | } |
| 289 | 295 | ||
| 290 | return SUCCESS; | 296 | return SUCCESS; |
diff --git a/src/sp_pcre_compat.c b/src/sp_pcre_compat.c index 509a8ea..3bd00ca 100644 --- a/src/sp_pcre_compat.c +++ b/src/sp_pcre_compat.c | |||
| @@ -1,5 +1,12 @@ | |||
| 1 | #include "php_snuffleupagus.h" | 1 | #include "php_snuffleupagus.h" |
| 2 | 2 | ||
| 3 | inline void sp_pcre_free(sp_pcre* regexp) { | ||
| 4 | #ifdef SP_HAS_PCRE2 | ||
| 5 | pcre2_code_free(regexp); | ||
| 6 | #endif | ||
| 7 | regexp = NULL; | ||
| 8 | } | ||
| 9 | |||
| 3 | sp_pcre* sp_pcre_compile(const char* const pattern) { | 10 | sp_pcre* sp_pcre_compile(const char* const pattern) { |
| 4 | assert(NULL != pattern); | 11 | assert(NULL != pattern); |
| 5 | 12 | ||
| @@ -34,7 +41,11 @@ bool ZEND_HOT sp_is_regexp_matching_len(const sp_pcre* regexp, const char* str, | |||
| 34 | #ifdef SP_HAS_PCRE2 | 41 | #ifdef SP_HAS_PCRE2 |
| 35 | pcre2_match_data* match_data = | 42 | pcre2_match_data* match_data = |
| 36 | pcre2_match_data_create_from_pattern(regexp, NULL); | 43 | pcre2_match_data_create_from_pattern(regexp, NULL); |
| 44 | if (NULL == match_data) { | ||
| 45 | sp_log_err("regexp", "Unable to get memory for a regxp."); | ||
| 46 | } | ||
| 37 | ret = pcre2_match(regexp, (PCRE2_SPTR)str, len, 0, 0, match_data, NULL); | 47 | ret = pcre2_match(regexp, (PCRE2_SPTR)str, len, 0, 0, match_data, NULL); |
| 48 | pcre2_match_data_free(match_data); | ||
| 38 | #else | 49 | #else |
| 39 | int vec[30]; | 50 | int vec[30]; |
| 40 | ret = pcre_exec(regexp, NULL, str, len, 0, 0, vec, sizeof(vec) / sizeof(int)); | 51 | ret = pcre_exec(regexp, NULL, str, len, 0, 0, vec, sizeof(vec) / sizeof(int)); |
diff --git a/src/sp_pcre_compat.h b/src/sp_pcre_compat.h index 14c33b2..725004d 100644 --- a/src/sp_pcre_compat.h +++ b/src/sp_pcre_compat.h | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #endif | 17 | #endif |
| 18 | 18 | ||
| 19 | sp_pcre* sp_pcre_compile(const char* str); | 19 | sp_pcre* sp_pcre_compile(const char* str); |
| 20 | void sp_pcre_free(sp_pcre* regexp); | ||
| 20 | #define sp_is_regexp_matching_zend(regexp, zstr) \ | 21 | #define sp_is_regexp_matching_zend(regexp, zstr) \ |
| 21 | sp_is_regexp_matching_len(regexp, ZSTR_VAL(zstr), ZSTR_LEN(zstr)) | 22 | sp_is_regexp_matching_len(regexp, ZSTR_VAL(zstr), ZSTR_LEN(zstr)) |
| 22 | #define sp_is_regexp_matching(regexp, str) \ | 23 | #define sp_is_regexp_matching(regexp, str) \ |
diff --git a/src/sp_sloppy.c b/src/sp_sloppy.c index f9ed718..ff2d644 100644 --- a/src/sp_sloppy.c +++ b/src/sp_sloppy.c | |||
| @@ -99,12 +99,13 @@ PHP_FUNCTION(sp_array_keys) { | |||
| 99 | void hook_sloppy() { | 99 | void hook_sloppy() { |
| 100 | TSRMLS_FETCH(); | 100 | TSRMLS_FETCH(); |
| 101 | 101 | ||
| 102 | if (NULL == orig_zend_compile_file) { | 102 | if (NULL == orig_zend_compile_file && zend_compile_file != sp_compile_file) { |
| 103 | orig_zend_compile_file = zend_compile_file; | 103 | orig_zend_compile_file = zend_compile_file; |
| 104 | zend_compile_file = sp_compile_file; | 104 | zend_compile_file = sp_compile_file; |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | if (NULL == orig_zend_compile_string) { | 107 | if (NULL == orig_zend_compile_string && |
| 108 | zend_compile_string != sp_compile_string) { | ||
| 108 | orig_zend_compile_string = zend_compile_string; | 109 | orig_zend_compile_string = zend_compile_string; |
| 109 | zend_compile_string = sp_compile_string; | 110 | zend_compile_string = sp_compile_string; |
| 110 | } | 111 | } |
diff --git a/src/sp_upload_validation.c b/src/sp_upload_validation.c index f3ae311..cebab3e 100644 --- a/src/sp_upload_validation.c +++ b/src/sp_upload_validation.c | |||
| @@ -103,6 +103,10 @@ int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra) { | |||
| 103 | #endif | 103 | #endif |
| 104 | 104 | ||
| 105 | void hook_upload() { | 105 | void hook_upload() { |
| 106 | if (php_rfc1867_callback == sp_rfc1867_callback) { | ||
| 107 | return; | ||
| 108 | } | ||
| 109 | |||
| 106 | if (NULL == sp_rfc1867_orig_callback) { | 110 | if (NULL == sp_rfc1867_orig_callback) { |
| 107 | sp_rfc1867_orig_callback = php_rfc1867_callback; | 111 | sp_rfc1867_orig_callback = php_rfc1867_callback; |
| 108 | php_rfc1867_callback = sp_rfc1867_callback; | 112 | php_rfc1867_callback = sp_rfc1867_callback; |
diff --git a/src/sp_utils.c b/src/sp_utils.c index 73c0546..5f25920 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c | |||
| @@ -19,24 +19,6 @@ const char* get_ipaddr() { | |||
| 19 | return fwd_ip; | 19 | return fwd_ip; |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | /* Some hosters (like heroku, see | ||
| 23 | * https://github.com/jvoisin/snuffleupagus/issues/336) are clearing the | ||
| 24 | * environment variables, so we don't have access to them, hence why we're | ||
| 25 | * resorting to $_SERVER['REMOTE_ADDR']. | ||
| 26 | */ | ||
| 27 | if (!Z_ISUNDEF(PG(http_globals)[TRACK_VARS_SERVER])) { | ||
| 28 | const zval* const globals_client_ip = | ||
| 29 | zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), | ||
| 30 | "REMOTE_ADDR", sizeof("REMOTE_ADDR") - 1); | ||
| 31 | if (globals_client_ip) { | ||
| 32 | if (Z_TYPE_P(globals_client_ip) == IS_STRING) { | ||
| 33 | if (Z_STRLEN_P(globals_client_ip) != 0) { | ||
| 34 | return estrdup(Z_STRVAL_P(globals_client_ip)); | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | return default_ipaddr; | 22 | return default_ipaddr; |
| 41 | } | 23 | } |
| 42 | 24 | ||
diff --git a/src/sp_var_parser.c b/src/sp_var_parser.c index b066b84..bb5a5c0 100644 --- a/src/sp_var_parser.c +++ b/src/sp_var_parser.c | |||
| @@ -20,7 +20,7 @@ static sp_list_node *parse_str_tokens(const char *str, | |||
| 20 | return tokens_list; | 20 | return tokens_list; |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | static bool is_var_name_valid(const char *name) { | 23 | static bool is_var_name_valid(const char *const name) { |
| 24 | static sp_pcre *regexp_const = NULL; | 24 | static sp_pcre *regexp_const = NULL; |
| 25 | static sp_pcre *regexp_var = NULL; | 25 | static sp_pcre *regexp_var = NULL; |
| 26 | 26 | ||
diff --git a/src/sp_var_value.c b/src/sp_var_value.c index b9ac357..fe37f99 100644 --- a/src/sp_var_value.c +++ b/src/sp_var_value.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include "php_snuffleupagus.h" | 1 | #include "php_snuffleupagus.h" |
| 2 | 2 | ||
| 3 | static zval *get_param_var(zend_execute_data *ed, const char *var_name) { | 3 | static zval *get_param_var(const zend_execute_data *const ed, |
| 4 | const char *const var_name, bool print) { | ||
| 4 | unsigned int nb_param = ed->func->common.num_args; | 5 | unsigned int nb_param = ed->func->common.num_args; |
| 5 | 6 | ||
| 6 | for (unsigned int i = 0; i < nb_param; i++) { | 7 | for (unsigned int i = 0; i < nb_param; i++) { |
| @@ -13,11 +14,14 @@ static zval *get_param_var(zend_execute_data *ed, const char *var_name) { | |||
| 13 | if (0 == strcmp(arg_name, var_name)) { | 14 | if (0 == strcmp(arg_name, var_name)) { |
| 14 | return ZEND_CALL_VAR_NUM(ed, i); | 15 | return ZEND_CALL_VAR_NUM(ed, i); |
| 15 | } | 16 | } |
| 17 | if (print == true) { | ||
| 18 | sp_log_warn("config", " - %d parameter's name: '%s'", i, arg_name); | ||
| 19 | } | ||
| 16 | } | 20 | } |
| 17 | return NULL; | 21 | return NULL; |
| 18 | } | 22 | } |
| 19 | 23 | ||
| 20 | static zval *get_local_var(zend_execute_data *ed, const char *var_name) { | 24 | static zval *get_local_var(zend_execute_data *ed, const char *const var_name) { |
| 21 | zend_execute_data *orig_execute_data = ed; | 25 | zend_execute_data *orig_execute_data = ed; |
| 22 | zend_execute_data *current = ed; | 26 | zend_execute_data *current = ed; |
| 23 | 27 | ||
| @@ -48,7 +52,7 @@ static zval *get_local_var(zend_execute_data *ed, const char *var_name) { | |||
| 48 | return NULL; | 52 | return NULL; |
| 49 | } | 53 | } |
| 50 | 54 | ||
| 51 | static zval *get_constant(const char *value) { | 55 | static zval *get_constant(const char *const value) { |
| 52 | zend_string *name = zend_string_init(value, strlen(value), 0); | 56 | zend_string *name = zend_string_init(value, strlen(value), 0); |
| 53 | zval *zvalue = zend_get_constant_ex(name, NULL, ZEND_FETCH_CLASS_SILENT); | 57 | zval *zvalue = zend_get_constant_ex(name, NULL, ZEND_FETCH_CLASS_SILENT); |
| 54 | zend_string_release(name); | 58 | zend_string_release(name); |
| @@ -68,7 +72,7 @@ static zval *get_var_value(zend_execute_data *ed, const char *var_name, | |||
| 68 | } | 72 | } |
| 69 | 73 | ||
| 70 | if (is_param) { | 74 | if (is_param) { |
| 71 | zval *zvalue = get_param_var(ed, var_name); | 75 | zval *zvalue = get_param_var(ed, var_name, false); |
| 72 | if (!zvalue) { | 76 | if (!zvalue) { |
| 73 | char *complete_function_path = get_complete_function_path(ed); | 77 | char *complete_function_path = get_complete_function_path(ed); |
| 74 | sp_log_warn("config", | 78 | sp_log_warn("config", |
| @@ -76,6 +80,7 @@ static zval *get_var_value(zend_execute_data *ed, const char *var_name, | |||
| 76 | "'%s' of the function '%s', but the parameter does " | 80 | "'%s' of the function '%s', but the parameter does " |
| 77 | "not exists.", | 81 | "not exists.", |
| 78 | var_name, complete_function_path); | 82 | var_name, complete_function_path); |
| 83 | get_param_var(ed, var_name, true); | ||
| 79 | efree(complete_function_path); | 84 | efree(complete_function_path); |
| 80 | return NULL; | 85 | return NULL; |
| 81 | } | 86 | } |
| @@ -85,8 +90,8 @@ static zval *get_var_value(zend_execute_data *ed, const char *var_name, | |||
| 85 | } | 90 | } |
| 86 | } | 91 | } |
| 87 | 92 | ||
| 88 | static void *get_entry_hashtable(const HashTable *ht, const char *entry, | 93 | static void *get_entry_hashtable(const HashTable *const ht, |
| 89 | size_t entry_len) { | 94 | const char *const entry, size_t entry_len) { |
| 90 | zval *zvalue = zend_hash_str_find(ht, entry, entry_len); | 95 | zval *zvalue = zend_hash_str_find(ht, entry, entry_len); |
| 91 | 96 | ||
| 92 | if (!zvalue) { | 97 | if (!zvalue) { |
| @@ -104,8 +109,8 @@ static void *get_entry_hashtable(const HashTable *ht, const char *entry, | |||
| 104 | return zvalue; | 109 | return zvalue; |
| 105 | } | 110 | } |
| 106 | 111 | ||
| 107 | static zval *get_array_value(zend_execute_data *ed, zval *zvalue, | 112 | static zval *get_array_value(zend_execute_data *ed, const zval *const zvalue, |
| 108 | const sp_tree *tree) { | 113 | const sp_tree *const tree) { |
| 109 | zval *idx_value = sp_get_var_value(ed, tree->idx, false); | 114 | zval *idx_value = sp_get_var_value(ed, tree->idx, false); |
| 110 | 115 | ||
| 111 | if (!zvalue || !idx_value) { | 116 | if (!zvalue || !idx_value) { |
| @@ -113,7 +118,7 @@ static zval *get_array_value(zend_execute_data *ed, zval *zvalue, | |||
| 113 | } | 118 | } |
| 114 | 119 | ||
| 115 | if (Z_TYPE_P(zvalue) == IS_ARRAY) { | 120 | if (Z_TYPE_P(zvalue) == IS_ARRAY) { |
| 116 | const zend_string *idx = sp_zval_to_zend_string(idx_value); | 121 | const zend_string *const idx = sp_zval_to_zend_string(idx_value); |
| 117 | return get_entry_hashtable(Z_ARRVAL_P(zvalue), ZSTR_VAL(idx), | 122 | return get_entry_hashtable(Z_ARRVAL_P(zvalue), ZSTR_VAL(idx), |
| 118 | ZSTR_LEN(idx)); | 123 | ZSTR_LEN(idx)); |
| 119 | } | 124 | } |
| @@ -123,10 +128,10 @@ static zval *get_array_value(zend_execute_data *ed, zval *zvalue, | |||
| 123 | 128 | ||
| 124 | static zval *get_object_property(zend_execute_data *ed, zval *object, | 129 | static zval *get_object_property(zend_execute_data *ed, zval *object, |
| 125 | const char *property, bool is_param) { | 130 | const char *property, bool is_param) { |
| 126 | char *class_name = object->value.obj->ce->name->val; | 131 | const char *const class_name = object->value.obj->ce->name->val; |
| 127 | HashTable *array = Z_OBJPROP_P(object); | 132 | HashTable *array = Z_OBJPROP_P(object); |
| 128 | zval *zvalue = NULL; | 133 | zval *zvalue = NULL; |
| 129 | zval *property_val = get_var_value(ed, property, is_param); | 134 | const zval *property_val = get_var_value(ed, property, is_param); |
| 130 | size_t len; | 135 | size_t len; |
| 131 | 136 | ||
| 132 | if (property_val) { | 137 | if (property_val) { |
| @@ -156,7 +161,7 @@ static zval *get_object_property(zend_execute_data *ed, zval *object, | |||
| 156 | return zvalue; | 161 | return zvalue; |
| 157 | } | 162 | } |
| 158 | 163 | ||
| 159 | static zend_class_entry *get_class(const char *value) { | 164 | static zend_class_entry *get_class(const char *const value) { |
| 160 | zend_string *name = zend_string_init(value, strlen(value), 0); | 165 | zend_string *name = zend_string_init(value, strlen(value), 0); |
| 161 | zend_class_entry *ce = zend_lookup_class(name); | 166 | zend_class_entry *ce = zend_lookup_class(name); |
| 162 | zend_string_release(name); | 167 | zend_string_release(name); |
| @@ -165,7 +170,7 @@ static zend_class_entry *get_class(const char *value) { | |||
| 165 | 170 | ||
| 166 | static zval *get_unknown_type(const char *restrict value, zval *zvalue, | 171 | static zval *get_unknown_type(const char *restrict value, zval *zvalue, |
| 167 | zend_class_entry *ce, zend_execute_data *ed, | 172 | zend_class_entry *ce, zend_execute_data *ed, |
| 168 | const sp_tree *tree, bool is_param) { | 173 | const sp_tree *const tree, bool is_param) { |
| 169 | if (ce) { | 174 | if (ce) { |
| 170 | zvalue = get_entry_hashtable(&ce->constants_table, value, strlen(value)); | 175 | zvalue = get_entry_hashtable(&ce->constants_table, value, strlen(value)); |
| 171 | ce = NULL; | 176 | ce = NULL; |
diff --git a/src/sp_wrapper.c b/src/sp_wrapper.c index 277f23a..7610114 100644 --- a/src/sp_wrapper.c +++ b/src/sp_wrapper.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | #include "php_snuffleupagus.h" | 1 | #include "php_snuffleupagus.h" |
| 2 | 2 | ||
| 3 | static bool wrapper_is_whitelisted(const zend_string *zs) { | 3 | static bool wrapper_is_whitelisted(const zend_string *const zs) { |
| 4 | const sp_list_node *list = SNUFFLEUPAGUS_G(config).config_wrapper->whitelist; | 4 | const sp_list_node *list = SNUFFLEUPAGUS_G(config).config_wrapper->whitelist; |
| 5 | 5 | ||
| 6 | if (!zs) { | 6 | if (!zs) { |
| @@ -18,7 +18,7 @@ static bool wrapper_is_whitelisted(const zend_string *zs) { | |||
| 18 | 18 | ||
| 19 | void sp_disable_wrapper() { | 19 | void sp_disable_wrapper() { |
| 20 | HashTable *orig = php_stream_get_url_stream_wrappers_hash(); | 20 | HashTable *orig = php_stream_get_url_stream_wrappers_hash(); |
| 21 | HashTable *orig_complete = pemalloc(sizeof(*orig_complete), 1); | 21 | HashTable *orig_complete = pemalloc(sizeof(HashTable), 1); |
| 22 | zval *zv; | 22 | zval *zv; |
| 23 | zend_string *zs; | 23 | zend_string *zs; |
| 24 | 24 | ||
diff --git a/src/tests/broken_configuration/broken_conf_config_invalid_param.phpt b/src/tests/broken_configuration/broken_conf_config_invalid_param.phpt index ac85dea..45ccf24 100644 --- a/src/tests/broken_configuration/broken_conf_config_invalid_param.phpt +++ b/src/tests/broken_configuration/broken_conf_config_invalid_param.phpt | |||
| @@ -13,4 +13,10 @@ function foo($blah, $x = null, $y = null) { | |||
| 13 | foo("qwe"); | 13 | foo("qwe"); |
| 14 | --EXPECTF-- | 14 | --EXPECTF-- |
| 15 | Warning: [snuffleupagus][0.0.0.0][config][log] It seems that you are filtering on a parameter 'qwe' of the function 'foo', but the parameter does not exists. in %s/tests/broken_configuration/broken_conf_config_invalid_param.php on line %d | 15 | Warning: [snuffleupagus][0.0.0.0][config][log] It seems that you are filtering on a parameter 'qwe' of the function 'foo', but the parameter does not exists. in %s/tests/broken_configuration/broken_conf_config_invalid_param.php on line %d |
| 16 | |||
| 17 | Warning: [snuffleupagus][0.0.0.0][config][log] - 0 parameter's name: 'blah' in %s/tests/broken_configuration/broken_conf_config_invalid_param.php on line %d | ||
| 18 | |||
| 19 | Warning: [snuffleupagus][0.0.0.0][config][log] - 1 parameter's name: 'x' in %s/tests/broken_configuration/broken_conf_config_invalid_param.php on line %d | ||
| 20 | |||
| 21 | Warning: [snuffleupagus][0.0.0.0][config][log] - 2 parameter's name: 'y' in %s/tests/broken_configuration/broken_conf_config_invalid_param.php on line %d | ||
| 16 | ok | 22 | ok |
diff --git a/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_encryption_key.phpt b/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_encryption_key.phpt index 046dc7d..62ee41e 100644 --- a/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_encryption_key.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_encryption_key.phpt | |||
| @@ -6,6 +6,7 @@ Broken configuration - encrypted session without encryption key | |||
| 6 | --INI-- | 6 | --INI-- |
| 7 | sp.configuration_file={PWD}/config/broken_conf_session_encryption_without_encryption_key.ini | 7 | sp.configuration_file={PWD}/config/broken_conf_session_encryption_without_encryption_key.ini |
| 8 | --FILE-- | 8 | --FILE-- |
| 9 | --XFAIL-- | ||
| 9 | --EXPECT-- | 10 | --EXPECT-- |
| 10 | 11 | ||
| 11 | Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the session cookie encryption feature on line 2 without having set the `.secret_key` option in`sp.global`: please set it first in Unknown on line 0 | 12 | Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the session cookie encryption feature on line 2 without having set the `.secret_key` option in`sp.global`: please set it first in Unknown on line 0 |
diff --git a/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_env_var.phpt b/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_env_var.phpt index bb0f212..5acc1cd 100644 --- a/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_env_var.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_session_encryption_without_env_var.phpt | |||
| @@ -6,6 +6,7 @@ Broken configuration - encrypted session without env var | |||
| 6 | --INI-- | 6 | --INI-- |
| 7 | sp.configuration_file={PWD}/config/broken_conf_session_encryption_without_env_var.ini | 7 | sp.configuration_file={PWD}/config/broken_conf_session_encryption_without_env_var.ini |
| 8 | --FILE-- | 8 | --FILE-- |
| 9 | --XFAIL-- | ||
| 9 | --EXPECT-- | 10 | --EXPECT-- |
| 10 | 11 | ||
| 11 | Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the session cookie encryption feature on line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0 | 12 | Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the session cookie encryption feature on line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0 |
diff --git a/src/tests/deny_writable/deny_writable_execution_simulation.phpt b/src/tests/deny_writable/deny_writable_execution_simulation.phpt index 30f8cb1..d4b8efc 100644 --- a/src/tests/deny_writable/deny_writable_execution_simulation.phpt +++ b/src/tests/deny_writable/deny_writable_execution_simulation.phpt | |||
| @@ -3,7 +3,7 @@ Readonly execution attempt (simulation mode) | |||
| 3 | --SKIPIF-- | 3 | --SKIPIF-- |
| 4 | <?php if (PHP_VERSION_ID >= 80000) print "skip"; ?> | 4 | <?php if (PHP_VERSION_ID >= 80000) print "skip"; ?> |
| 5 | <?php | 5 | <?php |
| 6 | if (!extension_loaded("snuffleupagus")) { print "skip" }; | 6 | if (!extension_loaded("snuffleupagus")) { print "skip"; }; |
| 7 | 7 | ||
| 8 | // root has write privileges on any file | 8 | // root has write privileges on any file |
| 9 | if (TRUE == function_exists("posix_getuid")) { | 9 | if (TRUE == function_exists("posix_getuid")) { |
diff --git a/src/tests/disable_function/config/disabled_functions.ini b/src/tests/disable_function/config/disabled_functions.ini index df7013f..0758c98 100644 --- a/src/tests/disable_function/config/disabled_functions.ini +++ b/src/tests/disable_function/config/disabled_functions.ini | |||
| @@ -7,3 +7,4 @@ sp.disable_function.function_r("^var_dump$").drop(); | |||
| 7 | sp.disable_function.function("sprintf").filename("/wrong file name").drop(); | 7 | sp.disable_function.function("sprintf").filename("/wrong file name").drop(); |
| 8 | sp.disable_function.function("sprintf").filename("/wrong file name").drop(); | 8 | sp.disable_function.function("sprintf").filename("/wrong file name").drop(); |
| 9 | sp.disable_function.function("eval").drop(); | 9 | sp.disable_function.function("eval").drop(); |
| 10 | sp.disable_function.function("shell_exec").param("foo").value("bar").drop(); | ||
diff --git a/src/tests/disable_function/config/disabled_functions_chmod.ini b/src/tests/disable_function/config/disabled_functions_chmod.ini new file mode 100644 index 0000000..e601900 --- /dev/null +++ b/src/tests/disable_function/config/disabled_functions_chmod.ini | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | # PHP7 and below | ||
| 2 | sp.disable_function.function("chmod").param("mode").value("511").drop(); | ||
| 3 | # PHP8 | ||
| 4 | sp.disable_function.function("chmod").param("permissions").value("511").drop(); | ||
diff --git a/src/tests/disable_function/disabled_functions_chmod.phpt b/src/tests/disable_function/disabled_functions_chmod.phpt new file mode 100644 index 0000000..28f948d --- /dev/null +++ b/src/tests/disable_function/disabled_functions_chmod.phpt | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | --TEST-- | ||
| 2 | Disable functions - chmod | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> | ||
| 5 | <?php if (PHP_VERSION_ID >= 80000) print "skip"; ?> | ||
| 6 | --INI-- | ||
| 7 | sp.configuration_file={PWD}/config/disabled_functions_chmod.ini | ||
| 8 | --FILE-- | ||
| 9 | <?php | ||
| 10 | chmod( 'foo', 0777 ); | ||
| 11 | ?> | ||
| 12 | --XFAIL-- | ||
| 13 | --EXPECTF-- | ||
| 14 | Fatal error: [snuffleupagus][0.0.0.0][disabled_function][drop] Aborted execution on call of the function 'chmod', because its argument '$mode' content (511) matched a rule in %a/disabled_function_chmod.php on line %d | ||
diff --git a/src/tests/disable_function/disabled_functions_chmod_php8.phpt b/src/tests/disable_function/disabled_functions_chmod_php8.phpt new file mode 100644 index 0000000..71bb034 --- /dev/null +++ b/src/tests/disable_function/disabled_functions_chmod_php8.phpt | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | --TEST-- | ||
| 2 | Disable functions - chmod, in php8 | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> | ||
| 5 | <?php if (PHP_VERSION_ID < 80000) print "skip"; ?> | ||
| 6 | --INI-- | ||
| 7 | sp.configuration_file={PWD}/config/disabled_functions_chmod.ini | ||
| 8 | --FILE-- | ||
| 9 | <?php | ||
| 10 | chmod( 'foo', 0777 ); | ||
| 11 | ?> | ||
| 12 | --XFAIL-- | ||
| 13 | --EXPECTF-- | ||
| 14 | Fatal error: [snuffleupagus][0.0.0.0][disabled_function][drop] Aborted execution on call of the function 'chmod', because its argument '$permissions' content (511) matched a rule in %a/disabled_function_chmod_php8.php on line %d | ||
diff --git a/src/tests/disable_function/disabled_functions_shell_exec_wrong.phpt b/src/tests/disable_function/disabled_functions_shell_exec_wrong.phpt new file mode 100644 index 0000000..fe8e73a --- /dev/null +++ b/src/tests/disable_function/disabled_functions_shell_exec_wrong.phpt | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | --TEST-- | ||
| 2 | Disable functions - shell_exec, with a non-existing command | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/disabled_functions.ini | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | $gs = exec( 'foo' ); | ||
| 10 | echo "YES"; | ||
| 11 | ?> | ||
| 12 | --EXPECTF-- | ||
| 13 | %snot found | ||
| 14 | YES | ||
diff --git a/src/tests/session_encryption/crypt_session_corrupted_session.phpt b/src/tests/session_encryption/crypt_session_corrupted_session.phpt index a89faf4..a97dbca 100644 --- a/src/tests/session_encryption/crypt_session_corrupted_session.phpt +++ b/src/tests/session_encryption/crypt_session_corrupted_session.phpt | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | Set a custom session handler | 2 | Set a custom session handler |
| 3 | --SKIPIF-- | 3 | --SKIPIF-- |
| 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> | 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> |
| 5 | <?php if (PHP_VERSION_ID >= 80000) print "skip"; ?> | ||
| 6 | <?php if (PHP_VERSION_ID >= 70400) print "skip"; ?> | ||
| 5 | --INI-- | 7 | --INI-- |
| 6 | sp.configuration_file={PWD}/config/config_crypt_session.ini | 8 | sp.configuration_file={PWD}/config/config_crypt_session.ini |
| 7 | session.save_path = "/tmp" | 9 | session.save_path = "/tmp" |
diff --git a/src/tests/session_encryption/crypt_session_invalid.phpt b/src/tests/session_encryption/crypt_session_invalid.phpt index 9ec7c50..967d9d1 100644 --- a/src/tests/session_encryption/crypt_session_invalid.phpt +++ b/src/tests/session_encryption/crypt_session_invalid.phpt | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | SESSION crypt and bad decrypt | 2 | SESSION crypt and bad decrypt |
| 3 | --SKIPIF-- | 3 | --SKIPIF-- |
| 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> | 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> |
| 5 | <?php if (PHP_VERSION_ID >= 80000) print "skip"; ?> | ||
| 6 | <?php if (PHP_VERSION_ID >= 70400) print "skip"; ?> | ||
| 5 | --INI-- | 7 | --INI-- |
| 6 | sp.configuration_file={PWD}/config/config_crypt_session.ini | 8 | sp.configuration_file={PWD}/config/config_crypt_session.ini |
| 7 | --ENV-- | 9 | --ENV-- |
diff --git a/src/tests/xxe/disable_xxe_dom_disabled.phpt b/src/tests/xxe/disable_xxe_dom_disabled.phpt index 493f5a3..a49e094 100644 --- a/src/tests/xxe/disable_xxe_dom_disabled.phpt +++ b/src/tests/xxe/disable_xxe_dom_disabled.phpt | |||
| @@ -44,8 +44,13 @@ printf("without xxe: %s", $dom->getElementsByTagName('testing')->item(0)->nodeVa | |||
| 44 | 44 | ||
| 45 | ?> | 45 | ?> |
| 46 | --EXPECTF-- | 46 | --EXPECTF-- |
| 47 | Warning: [snuffleupagus][0.0.0.0][xxe][log] A call to libxml_disable_entity_loader was tried and nopped in %s/tests/xxe/disable_xxe_dom_disabled.php on line %d | ||
| 47 | libxml_disable_entity to true: WARNING, external entity loaded! | 48 | libxml_disable_entity to true: WARNING, external entity loaded! |
| 49 | |||
| 50 | Warning: [snuffleupagus][0.0.0.0][xxe][log] A call to libxml_disable_entity_loader was tried and nopped in %s/tests/xxe/disable_xxe_dom_disabled.php on line %d | ||
| 48 | libxml_disable_entity to false: WARNING, external entity loaded! | 51 | libxml_disable_entity to false: WARNING, external entity loaded! |
| 52 | |||
| 53 | Warning: [snuffleupagus][0.0.0.0][xxe][log] A call to libxml_disable_entity_loader was tried and nopped in %s/tests/xxe/disable_xxe_dom_disabled.php on line %d | ||
| 49 | without xxe: foo | 54 | without xxe: foo |
| 50 | --CLEAN-- | 55 | --CLEAN-- |
| 51 | <?php | 56 | <?php |
