diff options
Diffstat (limited to 'config')
| -rw-r--r-- | config/default.rules | 37 | ||||
| -rw-r--r-- | config/default_php8.rules | 19 | ||||
| -rw-r--r-- | config/detect_dangerous_extensions.rules | 12 | ||||
| -rw-r--r-- | config/ini_protection.rules | 291 | ||||
| -rw-r--r-- | config/rips.rules | 1 | ||||
| -rw-r--r-- | config/suhosin.rules | 281 | ||||
| -rw-r--r-- | config/typo3.rules | 8 |
7 files changed, 620 insertions, 29 deletions
diff --git a/config/default.rules b/config/default.rules index 74e1edb..232197a 100644 --- a/config/default.rules +++ b/config/default.rules | |||
| @@ -6,14 +6,16 @@ | |||
| 6 | # Harden the PRNG | 6 | # Harden the PRNG |
| 7 | sp.harden_random.enable(); | 7 | sp.harden_random.enable(); |
| 8 | 8 | ||
| 9 | # Disabled XXE | 9 | # Enable XXE protection |
| 10 | sp.disable_xxe.enable(); | 10 | @condition extension_loaded("xml"); |
| 11 | sp.xxe_protection.enable(); | ||
| 12 | @end_condition; | ||
| 11 | 13 | ||
| 12 | # Global configuration variables | 14 | # Global configuration variables |
| 13 | # sp.global.secret_key("YOU _DO_ NEED TO CHANGE THIS WITH SOME RANDOM CHARACTERS."); | 15 | # sp.global.secret_key("YOU _DO_ NEED TO CHANGE THIS WITH SOME RANDOM CHARACTERS."); |
| 14 | 16 | ||
| 15 | # Globally activate strict mode | 17 | # Globally activate strict mode |
| 16 | # https://secure.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration.strict | 18 | # https://www.php.net/manual/en/language.types.declarations.php#language.types.declarations.strict |
| 17 | # sp.global_strict.enable(); | 19 | # sp.global_strict.enable(); |
| 18 | 20 | ||
| 19 | # Prevent unserialize-related exploits | 21 | # Prevent unserialize-related exploits |
| @@ -22,19 +24,20 @@ sp.disable_xxe.enable(); | |||
| 22 | # Only allow execution of read-only files. This is a low-hanging fruit that you should enable. | 24 | # Only allow execution of read-only files. This is a low-hanging fruit that you should enable. |
| 23 | # sp.readonly_exec.enable(); | 25 | # sp.readonly_exec.enable(); |
| 24 | 26 | ||
| 25 | # Php has a lot of wrappers, most of them aren't usually useful, you should | 27 | # PHP has a lot of wrappers, most of them aren't usually useful, you should |
| 26 | # only enable the ones you're using. | 28 | # only enable the ones you're using. |
| 27 | # sp.wrappers_whitelist.list("file,php,phar"); | 29 | # sp.wrappers_whitelist.list("file,php,phar"); |
| 28 | 30 | ||
| 29 | # Prevent sloppy comparisons. | 31 | # Prevent sloppy comparisons. |
| 30 | # sp.sloppy_comparison.enable(); | 32 | # sp.sloppy_comparison.enable(); |
| 31 | 33 | ||
| 32 | # use SameSite on session cookie | 34 | # Use SameSite on session cookie |
| 33 | # https://snuffleupagus.readthedocs.io/features.html#protection-against-cross-site-request-forgery | 35 | # https://snuffleupagus.readthedocs.io/features.html#protection-against-cross-site-request-forgery |
| 34 | sp.cookie.name("PHPSESSID").samesite("lax"); | 36 | sp.cookie.name("PHPSESSID").samesite("lax"); |
| 35 | 37 | ||
| 36 | # Harden the `chmod` function | 38 | # Harden the `chmod` function (0777 (oct = 511, 0666 = 438) |
| 37 | sp.disable_function.function("chmod").param("mode").value_r("^[0-9]{2}[67]$").drop(); | 39 | sp.disable_function.function("chmod").param("mode").value("438").drop(); |
| 40 | sp.disable_function.function("chmod").param("mode").value("511").drop(); | ||
| 38 | 41 | ||
| 39 | # Prevent various `mail`-related vulnerabilities | 42 | # Prevent various `mail`-related vulnerabilities |
| 40 | sp.disable_function.function("mail").param("additional_parameters").value_r("\\-").drop(); | 43 | sp.disable_function.function("mail").param("additional_parameters").value_r("\\-").drop(); |
| @@ -46,8 +49,8 @@ sp.disable_function.function("putenv").param("setting").value_r("LD_").drop() | |||
| 46 | sp.disable_function.function("putenv").param("setting").value_r("GCONV_").drop() | 49 | sp.disable_function.function("putenv").param("setting").value_r("GCONV_").drop() |
| 47 | 50 | ||
| 48 | # Since people are stupid enough to use `extract` on things like $_GET or $_POST, we might as well mitigate this vector | 51 | # Since people are stupid enough to use `extract` on things like $_GET or $_POST, we might as well mitigate this vector |
| 49 | sp.disable_function.function("extract").param("var_array").value_r("^_").drop() | 52 | sp.disable_function.function("extract").pos("0").value_r("^_").drop() |
| 50 | sp.disable_function.function("extract").param("extract_type").value("0").drop() | 53 | sp.disable_function.function("extract").pos("1").value("0").drop() |
| 51 | 54 | ||
| 52 | # This is also burned: | 55 | # This is also burned: |
| 53 | # ini_set('open_basedir','..');chdir('..');…;chdir('..');ini_set('open_basedir','/');echo(file_get_contents('/etc/passwd')); | 56 | # ini_set('open_basedir','..');chdir('..');…;chdir('..');ini_set('open_basedir','/');echo(file_get_contents('/etc/passwd')); |
| @@ -56,7 +59,7 @@ sp.disable_function.function("extract").param("extract_type").value("0").drop() | |||
| 56 | # Moreover, there are non-public bypasses that are also using this vector ;) | 59 | # Moreover, there are non-public bypasses that are also using this vector ;) |
| 57 | sp.disable_function.function("ini_set").param("varname").value_r("open_basedir").drop() | 60 | sp.disable_function.function("ini_set").param("varname").value_r("open_basedir").drop() |
| 58 | 61 | ||
| 59 | ##Prevent various `include`-related vulnerabilities | 62 | # Prevent various `include`-related vulnerabilities |
| 60 | sp.disable_function.function("require_once").value_r("\.(inc|phtml|php)$").allow(); | 63 | sp.disable_function.function("require_once").value_r("\.(inc|phtml|php)$").allow(); |
| 61 | sp.disable_function.function("include_once").value_r("\.(inc|phtml|php)$").allow(); | 64 | sp.disable_function.function("include_once").value_r("\.(inc|phtml|php)$").allow(); |
| 62 | sp.disable_function.function("require").value_r("\.(inc|phtml|php)$").allow(); | 65 | sp.disable_function.function("require").value_r("\.(inc|phtml|php)$").allow(); |
| @@ -68,7 +71,7 @@ sp.disable_function.function("include").drop() | |||
| 68 | 71 | ||
| 69 | # Prevent `system`-related injections | 72 | # Prevent `system`-related injections |
| 70 | sp.disable_function.function("system").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); | 73 | sp.disable_function.function("system").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); |
| 71 | sp.disable_function.function("shell_exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); | 74 | sp.disable_function.function("shell_exec").pos("0").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); |
| 72 | sp.disable_function.function("exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); | 75 | sp.disable_function.function("exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); |
| 73 | sp.disable_function.function("proc_open").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); | 76 | sp.disable_function.function("proc_open").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop(); |
| 74 | 77 | ||
| @@ -79,7 +82,7 @@ sp.disable_function.function("ini_set").param("varname").value("memory_limit").d | |||
| 79 | sp.disable_function.function("ini_set").param("varname").value("include_path").drop(); | 82 | sp.disable_function.function("ini_set").param("varname").value("include_path").drop(); |
| 80 | sp.disable_function.function("ini_set").param("varname").value("open_basedir").drop(); | 83 | sp.disable_function.function("ini_set").param("varname").value("open_basedir").drop(); |
| 81 | 84 | ||
| 82 | # Detect some backdoors via environnement recon | 85 | # Detect some backdoors via environment recon |
| 83 | sp.disable_function.function("ini_get").param("varname").value("allow_url_fopen").drop(); | 86 | sp.disable_function.function("ini_get").param("varname").value("allow_url_fopen").drop(); |
| 84 | sp.disable_function.function("ini_get").param("varname").value("open_basedir").drop(); | 87 | sp.disable_function.function("ini_get").param("varname").value("open_basedir").drop(); |
| 85 | sp.disable_function.function("ini_get").param("varname").value_r("suhosin").drop(); | 88 | sp.disable_function.function("ini_get").param("varname").value_r("suhosin").drop(); |
| @@ -108,9 +111,13 @@ sp.disable_function.function("curl_setopt").param("value").value("2").allow(); | |||
| 108 | 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("64").drop().alias("Please don't turn CURLOPT_SSL_VERIFYCLIENT off."); |
| 109 | sp.disable_function.function("curl_setopt").param("option").value("81").drop().alias("Please don't turn CURLOPT_SSL_VERIFYHOST off."); | 112 | sp.disable_function.function("curl_setopt").param("option").value("81").drop().alias("Please don't turn CURLOPT_SSL_VERIFYHOST off."); |
| 110 | 113 | ||
| 111 | #File upload | 114 | # File upload |
| 112 | sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ph").drop(); | 115 | # On old PHP7 versions |
| 113 | sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ht").drop(); | 116 | #sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ph").drop(); |
| 117 | #sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ht").drop(); | ||
| 118 | # On PHP7.4+ | ||
| 119 | sp.disable_function.function("move_uploaded_file").param("new_path").value_r("\\.ph").drop(); | ||
| 120 | sp.disable_function.function("move_uploaded_file").param("new_path").value_r("\\.ht").drop(); | ||
| 114 | 121 | ||
| 115 | # Logging lockdown | 122 | # Logging lockdown |
| 116 | sp.disable_function.function("ini_set").param("varname").value_r("error_log").drop() | 123 | sp.disable_function.function("ini_set").param("varname").value_r("error_log").drop() |
diff --git a/config/default_php8.rules b/config/default_php8.rules index 427dcaf..6d6b88e 100644 --- a/config/default_php8.rules +++ b/config/default_php8.rules | |||
| @@ -8,13 +8,13 @@ | |||
| 8 | sp.harden_random.enable(); | 8 | sp.harden_random.enable(); |
| 9 | 9 | ||
| 10 | # Disabled XXE | 10 | # Disabled XXE |
| 11 | sp.disable_xxe.enable(); | 11 | sp.xxe_protection.enable(); |
| 12 | 12 | ||
| 13 | # Global configuration variables | 13 | # Global configuration variables |
| 14 | # sp.global.secret_key("YOU _DO_ NEED TO CHANGE THIS WITH SOME RANDOM CHARACTERS."); | 14 | # sp.global.secret_key("YOU _DO_ NEED TO CHANGE THIS WITH SOME RANDOM CHARACTERS."); |
| 15 | 15 | ||
| 16 | # Globally activate strict mode | 16 | # Globally activate strict mode |
| 17 | # https://secure.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration.strict | 17 | # https://www.php.net/manual/en/language.types.declarations.php#language.types.declarations.strict |
| 18 | # sp.global_strict.enable(); | 18 | # sp.global_strict.enable(); |
| 19 | 19 | ||
| 20 | # Prevent unserialize-related exploits | 20 | # Prevent unserialize-related exploits |
| @@ -23,19 +23,20 @@ sp.disable_xxe.enable(); | |||
| 23 | # Only allow execution of read-only files. This is a low-hanging fruit that you should enable. | 23 | # Only allow execution of read-only files. This is a low-hanging fruit that you should enable. |
| 24 | # sp.readonly_exec.enable(); | 24 | # sp.readonly_exec.enable(); |
| 25 | 25 | ||
| 26 | # Php has a lot of wrappers, most of them aren't usually useful, you should | 26 | # PHP has a lot of wrappers, most of them aren't usually useful, you should |
| 27 | # only enable the ones you're using. | 27 | # only enable the ones you're using. |
| 28 | # sp.wrappers_whitelist.list("file,php,phar"); | 28 | # sp.wrappers_whitelist.list("file,php,phar"); |
| 29 | 29 | ||
| 30 | # Prevent sloppy comparisons. | 30 | # Prevent sloppy comparisons. |
| 31 | # sp.sloppy_comparison.enable(); | 31 | # sp.sloppy_comparison.enable(); |
| 32 | 32 | ||
| 33 | # use SameSite on session cookie | 33 | # Use SameSite on session cookie |
| 34 | # https://snuffleupagus.readthedocs.io/features.html#protection-against-cross-site-request-forgery | 34 | # https://snuffleupagus.readthedocs.io/features.html#protection-against-cross-site-request-forgery |
| 35 | sp.cookie.name("PHPSESSID").samesite("lax"); | 35 | sp.cookie.name("PHPSESSID").samesite("lax"); |
| 36 | 36 | ||
| 37 | # Harden the `chmod` function | 37 | # Harden the `chmod` function (0777 (oct = 511, 0666 = 438) |
| 38 | sp.disable_function.function("chmod").param("mode").value_r("^[0-9]{2}[67]$").drop(); | 38 | sp.disable_function.function("chmod").param("permissions").value("438").drop(); |
| 39 | sp.disable_function.function("chmod").param("permissions").value("511").drop(); | ||
| 39 | 40 | ||
| 40 | # Prevent various `mail`-related vulnerabilities | 41 | # Prevent various `mail`-related vulnerabilities |
| 41 | sp.disable_function.function("mail").param("additional_parameters").value_r("\\-").drop(); | 42 | sp.disable_function.function("mail").param("additional_parameters").value_r("\\-").drop(); |
| @@ -57,7 +58,7 @@ sp.disable_function.function("extract").param("flags").value("0").drop() | |||
| 57 | # Moreover, there are non-public bypasses that are also using this vector ;) | 58 | # Moreover, there are non-public bypasses that are also using this vector ;) |
| 58 | sp.disable_function.function("ini_set").param("option").value_r("open_basedir").drop() | 59 | sp.disable_function.function("ini_set").param("option").value_r("open_basedir").drop() |
| 59 | 60 | ||
| 60 | ##Prevent various `include`-related vulnerabilities | 61 | # Prevent various `include`-related vulnerabilities |
| 61 | sp.disable_function.function("require_once").value_r("\.(inc|phtml|php)$").allow(); | 62 | sp.disable_function.function("require_once").value_r("\.(inc|phtml|php)$").allow(); |
| 62 | sp.disable_function.function("include_once").value_r("\.(inc|phtml|php)$").allow(); | 63 | sp.disable_function.function("include_once").value_r("\.(inc|phtml|php)$").allow(); |
| 63 | sp.disable_function.function("require").value_r("\.(inc|phtml|php)$").allow(); | 64 | sp.disable_function.function("require").value_r("\.(inc|phtml|php)$").allow(); |
| @@ -110,8 +111,8 @@ sp.disable_function.function("curl_setopt").param("option").value("64").drop().a | |||
| 110 | sp.disable_function.function("curl_setopt").param("option").value("81").drop().alias("Please don't turn CURLOPT_SSL_VERIFYHOST off."); | 111 | sp.disable_function.function("curl_setopt").param("option").value("81").drop().alias("Please don't turn CURLOPT_SSL_VERIFYHOST off."); |
| 111 | 112 | ||
| 112 | # File upload | 113 | # File upload |
| 113 | sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ph").drop(); | 114 | sp.disable_function.function("move_uploaded_file").param("to").value_r("\\.ph").drop(); |
| 114 | sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ht").drop(); | 115 | sp.disable_function.function("move_uploaded_file").param("to").value_r("\\.ht").drop(); |
| 115 | 116 | ||
| 116 | # Logging lockdown | 117 | # Logging lockdown |
| 117 | sp.disable_function.function("ini_set").param("option").value_r("error_log").drop() | 118 | sp.disable_function.function("ini_set").param("option").value_r("error_log").drop() |
diff --git a/config/detect_dangerous_extensions.rules b/config/detect_dangerous_extensions.rules new file mode 100644 index 0000000..8f10532 --- /dev/null +++ b/config/detect_dangerous_extensions.rules | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | ## This example rules file shows how to detect and disable certain potentially | ||
| 2 | ## dangerous or unwanted extensions. | ||
| 3 | |||
| 4 | @condition extension_loaded("runkit7"); | ||
| 5 | @error "The runkit7 extension can be used to rename classes and functions, thereby circumventing any filters set by Snuffleupagus. Please disable runkit7."; | ||
| 6 | |||
| 7 | @condition extension_loaded("FFI"); | ||
| 8 | @warning "FFI extension is loaded. Disabling via 'ffi.enable=false'"; | ||
| 9 | sp.ini_protection.enable(); | ||
| 10 | sp.ini.key("ffi.enable").set("false").ro(); | ||
| 11 | @end_condition; | ||
| 12 | |||
diff --git a/config/ini_protection.rules b/config/ini_protection.rules new file mode 100644 index 0000000..9b42a18 --- /dev/null +++ b/config/ini_protection.rules | |||
| @@ -0,0 +1,291 @@ | |||
| 1 | ## INI protection - prevent unwanted runtime ini changes made by ini_set() or other functions or by .htaccess | ||
| 2 | sp.ini_protection.enable(); | ||
| 3 | |||
| 4 | ## simulation mode: only log violations | ||
| 5 | #sp.ini_protection.simulation(); | ||
| 6 | |||
| 7 | ## drop policy: drop request on rule violation | ||
| 8 | #sp.ini_protection.policy_drop(); | ||
| 9 | |||
| 10 | ## do not log violations. | ||
| 11 | ## this setting has no effect in simulation or drop mode | ||
| 12 | #sp.ini_protection.policy_silent_fail(); | ||
| 13 | |||
| 14 | ## do not log read-only violations | ||
| 15 | ## this setting has no effect in simulation or drop mode | ||
| 16 | sp.ini_protection.policy_silent_ro(); | ||
| 17 | |||
| 18 | ## access policy can be one of | ||
| 19 | ## .policy_readonly(): All entries are read-only by default. | ||
| 20 | ## Individual entries can be set read-write using .readwrite() or .rw() | ||
| 21 | ## .policy_readwrite(): This is the default and can be omitted. | ||
| 22 | ## Individual entries can be set read-only using .readonly() or .ro() | ||
| 23 | #sp.ini_protection.policy_readonly(); | ||
| 24 | |||
| 25 | ## sp.ini entries can have the following attributes | ||
| 26 | ## .key("..."): mandatory ini name. | ||
| 27 | ## .set("..."): set the initial value. This overrides php.ini. | ||
| 28 | ## checks are not performed for this initial value. | ||
| 29 | ## .min("...") / .max("..."): value must be an integer between .min and .max. | ||
| 30 | ## shorthand notation (e.g. 1k = 1024) is allowed | ||
| 31 | ## .regexp("..."): value must match the regular expression | ||
| 32 | ## .allow_null(): allow setting a NULL-value | ||
| 33 | ## .msg("..."): message is shown in logs on rule violation instead of default message | ||
| 34 | ## .readonly() / .ro() / .readwrite() / .rw(): set entry to read-only or read-write respectively | ||
| 35 | ## If no access keyword is provided, the entry inherits the default policy set by sp.ini_protection.policy_*-rules. | ||
| 36 | ## .drop(): drop request on rule violation for this entry | ||
| 37 | ## .simulation(): only log rule violation for this entry | ||
| 38 | |||
| 39 | ## FOR PRODUCTION SYSTEMS: disable error messages and version numbers | ||
| 40 | sp.ini.key("display_errors").set("0").ro(); | ||
| 41 | sp.ini.key("display_startup_errors").set("0").ro(); | ||
| 42 | sp.ini.key("expose_php").set("0").ro(); | ||
| 43 | ## FOR DEVELOPMENT/TESTING: allow enabling error messages and version numbers | ||
| 44 | #sp.ini.key("display_errors").rw(); | ||
| 45 | #sp.ini.key("display_startup_errors").rw(); | ||
| 46 | #sp.ini.key("expose_php").rw(); | ||
| 47 | |||
| 48 | ## error logging options should not be set during runtime -> read-only. | ||
| 49 | sp.ini.key("error_log").ro(); | ||
| 50 | sp.ini.key("error_reporting").ro(); | ||
| 51 | sp.ini.key("log_errors").ro(); | ||
| 52 | @condition PHP_VERSION_ID < 80000; | ||
| 53 | sp.ini.key("log_errors_max_len").set("2048").ro(); | ||
| 54 | @end_condition; | ||
| 55 | sp.ini.key("ignore_repeated_errors").ro(); | ||
| 56 | sp.ini.key("ignore_repeated_source").ro(); | ||
| 57 | sp.ini.key("syslog.filter").ro(); | ||
| 58 | |||
| 59 | ## disable assert. assert() in PHP can evaluate arbitrary code just like eval() | ||
| 60 | sp.ini.key("assert.active").set("0").ro(); | ||
| 61 | sp.ini.key("assert.bail").ro(); | ||
| 62 | sp.ini.key("assert.callback").ro(); | ||
| 63 | sp.ini.key("assert.exception").ro(); | ||
| 64 | sp.ini.key("assert.warning").ro(); | ||
| 65 | |||
| 66 | ## enforce color codes. prevents potential XSS | ||
| 67 | sp.ini.key("highlight.comment").regexp("^#[0-9a-fA-F]{6}$"); | ||
| 68 | sp.ini.key("highlight.default").regexp("^#[0-9a-fA-F]{6}$"); | ||
| 69 | sp.ini.key("highlight.html").regexp("^#[0-9a-fA-F]{6}$"); | ||
| 70 | sp.ini.key("highlight.keyword").regexp("^#[0-9a-fA-F]{6}$"); | ||
| 71 | sp.ini.key("highlight.string").regexp("^#[0-9a-fA-F]{6}$"); | ||
| 72 | |||
| 73 | ## prevent remote access via fopen/include | ||
| 74 | sp.ini.key("allow_url_fopen").set("0").ro(); | ||
| 75 | sp.ini.key("allow_url_include").set("0").ro(); | ||
| 76 | |||
| 77 | ## prevent code execution from auto-included files | ||
| 78 | sp.ini.key("auto_append_file").ro(); | ||
| 79 | sp.ini.key("auto_prepend_file").ro(); | ||
| 80 | |||
| 81 | ## make rarely used features read-only. you can always set the value in php.ini | ||
| 82 | sp.ini.key("arg_separator.input").ro(); | ||
| 83 | sp.ini.key("arg_separator.output").ro(); | ||
| 84 | sp.ini.key("auto_detect_line_endings").ro(); | ||
| 85 | sp.ini.key("auto_globals_jit").ro(); | ||
| 86 | sp.ini.key("browscap").ro(); | ||
| 87 | sp.ini.key("default_charset").ro(); | ||
| 88 | sp.ini.key("register_argc_argv").ro(); | ||
| 89 | sp.ini.key("report_memleaks").ro(); | ||
| 90 | sp.ini.key("report_zend_debug").ro(); | ||
| 91 | sp.ini.key("request_order").ro(); | ||
| 92 | sp.ini.key("url_rewriter.hosts").ro(); | ||
| 93 | sp.ini.key("url_rewriter.tags").ro(); | ||
| 94 | sp.ini.key("variables_order").ro(); | ||
| 95 | sp.ini.key("from").ro(); | ||
| 96 | sp.ini.key("short_open_tag").ro(); | ||
| 97 | sp.ini.key("unserialize_callback_func").ro(); | ||
| 98 | sp.ini.key("zend.detect_unicode").ro(); | ||
| 99 | sp.ini.key("zend.enable_gc").ro(); | ||
| 100 | sp.ini.key("zend.exception_ignore_args").ro(); | ||
| 101 | sp.ini.key("zend.exception_string_param_max_len").ro(); | ||
| 102 | sp.ini.key("zend.multibyte").ro(); | ||
| 103 | sp.ini.key("zend.script_encoding").ro(); | ||
| 104 | |||
| 105 | ## date and timezone settings | ||
| 106 | #sp.ini.key("date.default_latitude").set("31.7667").ro(); | ||
| 107 | #sp.ini.key("date.default_longitude").set("35.2333").ro(); | ||
| 108 | #sp.ini.key("date.sunrise_zenith").set("90.833333").ro(); | ||
| 109 | #sp.ini.key("date.sunset_zenith").set("90.833333").ro(); | ||
| 110 | #sp.ini.key("date.timezone").set("").ro(); | ||
| 111 | |||
| 112 | ## setting a default mime type other than text/html can be a way to prevent XSS, so this will be set to read-write by default | ||
| 113 | sp.ini.key("default_mimetype").rw(); | ||
| 114 | |||
| 115 | ## allow reasonable socket timeouts | ||
| 116 | sp.ini.key("default_socket_timeout").min("1").max("300").rw(); | ||
| 117 | |||
| 118 | ## disable dynamic loading of PHP extensions in an apache/mod_php environment as it is a security risk. | ||
| 119 | sp.ini.key("enable_dl").set("0").ro(); | ||
| 120 | |||
| 121 | ## links to manual pages in error pages should not be set during runtime. | ||
| 122 | sp.ini.key("docref_ext").ro(); | ||
| 123 | sp.ini.key("docref_root").ro(); | ||
| 124 | sp.ini.key("html_errors").set("0").ro(); | ||
| 125 | |||
| 126 | ## preventing $_POST and $_FILES to be populated can be a security feature, so read-write is ok. | ||
| 127 | sp.ini.key("enable_post_data_reading").rw(); | ||
| 128 | |||
| 129 | ## disable error append/prepend which may lead to log forging. | ||
| 130 | sp.ini.key("error_append_string").ro(); | ||
| 131 | sp.ini.key("error_prepend_string").set("").ro(); | ||
| 132 | |||
| 133 | ## restrict limit settings to prevent Denial-of-Service | ||
| 134 | sp.ini.key("max_execution_time").min("30").max("600").rw(); | ||
| 135 | sp.ini.key("max_file_uploads").min("0").max("25").rw(); | ||
| 136 | sp.ini.key("max_input_nesting_level").min("16").max("64").rw(); | ||
| 137 | sp.ini.key("max_input_time").set("-1").ro(); | ||
| 138 | sp.ini.key("max_input_vars").min("0").max("1024").rw(); | ||
| 139 | sp.ini.key("memory_limit").min("4M").max("256M").rw(); | ||
| 140 | sp.ini.key("post_max_size").max("256M").rw(); | ||
| 141 | sp.ini.key("upload_max_filesize").max("256M").rw(); | ||
| 142 | sp.ini.key("precision").max("14").rw(); | ||
| 143 | sp.ini.key("unserialize_max_depth").min("128").max("4096").rw(); | ||
| 144 | sp.ini.key("serialize_precision").ro(); | ||
| 145 | |||
| 146 | ## some applications rely on these filters for security | ||
| 147 | ## even though they should implement proper input validation for each input field separately. | ||
| 148 | @condition extension_loaded("filter"); | ||
| 149 | sp.ini.key("filter.default").rw(); | ||
| 150 | sp.ini.key("filter.default_flags").rw(); | ||
| 151 | @end_condition; | ||
| 152 | |||
| 153 | ## scripts will not be terminated after a client has aborted their connection. | ||
| 154 | ## this feature may be needed for some time consuming server-side calculation | ||
| 155 | sp.ini.key("ignore_user_abort").rw(); | ||
| 156 | |||
| 157 | ## flushing may be needed | ||
| 158 | sp.ini.key("implicit_flush").rw(); | ||
| 159 | |||
| 160 | ## this feature may be required for some frameworks to work properly, | ||
| 161 | ## but setting the include path to a fixed value is always more secure. | ||
| 162 | sp.ini.key("include_path").ro(); | ||
| 163 | |||
| 164 | ## input/output and encoding options | ||
| 165 | sp.ini.key("input_encoding").ro(); | ||
| 166 | sp.ini.key("internal_encoding").ro(); | ||
| 167 | sp.ini.key("output_encoding").ro(); | ||
| 168 | sp.ini.key("output_buffering").min("0").max("4096").rw(); | ||
| 169 | sp.ini.key("output_handler").ro(); | ||
| 170 | |||
| 171 | ## mail options | ||
| 172 | #sp.ini.key("mail.add_x_header").set("0").ro(); | ||
| 173 | #sp.ini.key("mail.force_extra_parameters").set("").ro(); | ||
| 174 | #sp.ini.key("mail.log").set("").ro(); | ||
| 175 | ## windows smtp options | ||
| 176 | #sp.ini.key("SMTP").set("localhost").ro(); | ||
| 177 | #sp.ini.key("smtp_port").set("25").ro(); | ||
| 178 | #sp.ini.key("sendmail_from").ro(); | ||
| 179 | |||
| 180 | ## mysqli/mysqlnd options | ||
| 181 | @condition extension_loaded("mysqli"); | ||
| 182 | sp.ini.key("mysqli.allow_local_infile").ro(); | ||
| 183 | sp.ini.key("mysqli.allow_persistent").ro(); | ||
| 184 | sp.ini.key("mysqli.default_host").ro(); | ||
| 185 | sp.ini.key("mysqli.default_port").ro(); | ||
| 186 | sp.ini.key("mysqli.default_pw").ro(); | ||
| 187 | sp.ini.key("mysqli.default_socket").ro(); | ||
| 188 | sp.ini.key("mysqli.default_user").ro(); | ||
| 189 | sp.ini.key("mysqli.max_links").set("-1").ro(); | ||
| 190 | sp.ini.key("mysqli.max_persistent").set("-1").ro(); | ||
| 191 | sp.ini.key("mysqli.reconnect").set("0").ro(); | ||
| 192 | sp.ini.key("mysqli.rollback_on_cached_plink").set("0").ro(); | ||
| 193 | @condition extension_loaded("mysqlnd"); | ||
| 194 | sp.ini.key("mysqlnd.collect_memory_statistics").set("0").ro(); | ||
| 195 | sp.ini.key("mysqlnd.collect_statistics").set("1").ro(); | ||
| 196 | sp.ini.key("mysqlnd.debug").set("").ro(); | ||
| 197 | sp.ini.key("mysqlnd.log_mask").set("0").ro(); | ||
| 198 | sp.ini.key("mysqlnd.mempool_default_size").set("16000").ro(); | ||
| 199 | sp.ini.key("mysqlnd.net_cmd_buffer_size").set("4096").ro(); | ||
| 200 | sp.ini.key("mysqlnd.net_read_buffer_size").set("32768").ro(); | ||
| 201 | sp.ini.key("mysqlnd.net_read_timeout").set("86400").ro(); | ||
| 202 | sp.ini.key("mysqlnd.sha256_server_public_key").set("").ro(); | ||
| 203 | sp.ini.key("mysqlnd.trace_alloc").set("").ro(); | ||
| 204 | @condition extension_loaded("mysqlnd") && PHP_VERSION_ID < 80100; | ||
| 205 | sp.ini.key("mysqlnd.fetch_data_copy").set("0").ro(); | ||
| 206 | @end_condition; | ||
| 207 | |||
| 208 | ## open basedir is a security feature similar to chroot. | ||
| 209 | ## why should it be allowed to disable this feature during runtime? | ||
| 210 | sp.ini.key("open_basedir").ro(); | ||
| 211 | |||
| 212 | ## pcre options | ||
| 213 | @condition extension_loaded("pcre"); | ||
| 214 | sp.ini.key("pcre.backtrack_limit").min("1000").max("1000000").rw(); | ||
| 215 | sp.ini.key("pcre.jit").rw(); | ||
| 216 | sp.ini.key("pcre.recursion_limit").min("1000").max("100000").ro(); | ||
| 217 | @end_condition; | ||
| 218 | |||
| 219 | ## phar options | ||
| 220 | @condition extension_loaded("phar"); | ||
| 221 | sp.ini.key("phar.cache_list").ro(); | ||
| 222 | sp.ini.key("phar.readonly").ro(); | ||
| 223 | sp.ini.key("phar.require_hash").ro(); | ||
| 224 | @end_condition; | ||
| 225 | |||
| 226 | ## session options | ||
| 227 | @condition extension_loaded("session"); | ||
| 228 | #sp.ini.key("session.auto_start").set("0").ro(); | ||
| 229 | #sp.ini.key("session.cache_expire").set("180").ro(); | ||
| 230 | #sp.ini.key("session.cache_limiter").set("nocache").ro(); | ||
| 231 | #sp.ini.key("session.cookie_domain").set("").ro(); | ||
| 232 | #sp.ini.key("session.cookie_httponly").set("0").ro(); | ||
| 233 | #sp.ini.key("session.cookie_lifetime").set("0").ro(); | ||
| 234 | #sp.ini.key("session.cookie_path").set("/").ro(); | ||
| 235 | #sp.ini.key("session.cookie_samesite").set("").ro(); | ||
| 236 | #sp.ini.key("session.cookie_secure").set("0").ro(); | ||
| 237 | #sp.ini.key("session.gc_divisor").set("100").ro(); | ||
| 238 | #sp.ini.key("session.gc_maxlifetime").set("1440").ro(); | ||
| 239 | #sp.ini.key("session.gc_probability").set("1").ro(); | ||
| 240 | #sp.ini.key("session.lazy_write").set("1").ro(); | ||
| 241 | #sp.ini.key("session.name").set("PHPSESSID").ro(); | ||
| 242 | #sp.ini.key("session.referer_check").set("").ro(); | ||
| 243 | #sp.ini.key("session.save_handler").set("files").ro(); | ||
| 244 | #sp.ini.key("session.save_path").set("").ro(); | ||
| 245 | #sp.ini.key("session.serialize_handler").set("php").ro(); | ||
| 246 | #sp.ini.key("session.sid_bits_per_character").set("4").ro(); | ||
| 247 | sp.ini.key("session.sid_length").min("32").max("128").rw(); | ||
| 248 | #sp.ini.key("session.trans_sid_hosts").set("").ro(); | ||
| 249 | #sp.ini.key("session.trans_sid_tags").set("a=href,area=href,frame=src,form=").ro(); | ||
| 250 | #sp.ini.key("session.upload_progress.cleanup").set("1").ro(); | ||
| 251 | #sp.ini.key("session.upload_progress.enabled").set("1").ro(); | ||
| 252 | #sp.ini.key("session.upload_progress.freq").set("1%").ro(); | ||
| 253 | #sp.ini.key("session.upload_progress.min_freq").set("1").ro(); | ||
| 254 | #sp.ini.key("session.upload_progress.name").set("PHP_SESSION_UPLOAD_PROGRESS").ro(); | ||
| 255 | #sp.ini.key("session.upload_progress.prefix").set("upload_progress_").ro(); | ||
| 256 | #sp.ini.key("session.use_cookies").set("1").ro(); | ||
| 257 | #sp.ini.key("session.use_only_cookies").set("1").ro(); | ||
| 258 | sp.ini.key("session.use_strict_mode").set("1").ro(); | ||
| 259 | #sp.ini.key("session.use_trans_sid").set("0").ro(); | ||
| 260 | @end_condition; | ||
| 261 | |||
| 262 | ## allow setting the user agent | ||
| 263 | sp.ini.key("user_agent").rw(); | ||
| 264 | |||
| 265 | ## allow setting the xmlrpc fault code | ||
| 266 | sp.ini.key("xmlrpc_error_number").rw(); | ||
| 267 | |||
| 268 | ## these ini entries can only be set by php.ini anyway, | ||
| 269 | ## but better set them to read-only anyway, just to be sure. | ||
| 270 | sp.ini.key("disable_classes").ro(); | ||
| 271 | sp.ini.key("disable_functions").ro(); | ||
| 272 | sp.ini.key("doc_root").ro(); | ||
| 273 | sp.ini.key("extension_dir").ro(); | ||
| 274 | sp.ini.key("file_uploads").ro(); | ||
| 275 | sp.ini.key("hard_timeout").ro(); | ||
| 276 | sp.ini.key("realpath_cache_size").ro(); | ||
| 277 | sp.ini.key("realpath_cache_ttl").ro(); | ||
| 278 | sp.ini.key("sendmail_path").ro(); | ||
| 279 | @condition extension_loaded("sqlite3"); | ||
| 280 | sp.ini.key("sqlite3.defensive").ro(); | ||
| 281 | sp.ini.key("sqlite3.extension_dir").ro(); | ||
| 282 | @end_condition; | ||
| 283 | sp.ini.key("sys_temp_dir").ro(); | ||
| 284 | sp.ini.key("syslog.facility").ro(); | ||
| 285 | sp.ini.key("syslog.ident").ro(); | ||
| 286 | sp.ini.key("upload_tmp_dir").ro(); | ||
| 287 | sp.ini.key("user_dir").ro(); | ||
| 288 | sp.ini.key("user_ini.cache_ttl").ro(); | ||
| 289 | sp.ini.key("user_ini.filename").ro(); | ||
| 290 | sp.ini.key("zend.assertions").ro(); | ||
| 291 | sp.ini.key("zend.signal_check").set("0").ro(); | ||
diff --git a/config/rips.rules b/config/rips.rules index 52e3f27..dcb08c1 100644 --- a/config/rips.rules +++ b/config/rips.rules | |||
| @@ -30,4 +30,3 @@ sp.disable_function.filename("/forgot_passwd.php").function("cpg_db_query").var( | |||
| 30 | # CVE-2017-1001000 - https://blog.sucuri.net/2017/02/content-injection-vulnerability-wordpress-rest-api.html | 30 | # CVE-2017-1001000 - https://blog.sucuri.net/2017/02/content-injection-vulnerability-wordpress-rest-api.html |
| 31 | sp.disable_function.filename("/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php").function("register_routes").var("_GET[id]").value_r("[^0-9]").drop(); | 31 | sp.disable_function.filename("/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php").function("register_routes").var("_GET[id]").value_r("[^0-9]").drop(); |
| 32 | sp.disable_function.filename("/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php").function("register_routes").var("_POST[id]").value_r("[^0-9]").drop(); | 32 | sp.disable_function.filename("/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php").function("register_routes").var("_POST[id]").value_r("[^0-9]").drop(); |
| 33 | |||
diff --git a/config/suhosin.rules b/config/suhosin.rules new file mode 100644 index 0000000..0bdc453 --- /dev/null +++ b/config/suhosin.rules | |||
| @@ -0,0 +1,281 @@ | |||
| 1 | ## This file is part of the Suhosin-NG (SNG) PHP Hardening project | ||
| 2 | ## - see https://suhosin.org/ for more information. | ||
| 3 | ## | ||
| 4 | ## Snuffleupagus compatibility: Version 0.7.0 with SNG patches and above | ||
| 5 | ## https://github.com/sektioneins/snuffleupagus | ||
| 6 | ## | ||
| 7 | ############################# ### # --------- | ||
| 8 | ## | ||
| 9 | ## This file documents the effort to port as many Suhosin features as possible to Snuffleupagus rules. | ||
| 10 | ## It is meant as a proof of concept and it will serve multiple purposes: | ||
| 11 | ## * Create a reasonably secure configuration for Snuffleupagus. | ||
| 12 | ## * Make it apparent which Suhosin features cannot be easily implemented in SP by just using configuration | ||
| 13 | ## rules. These will be collected and some features will be implemented as part of the Suhosin-NG project. | ||
| 14 | ## * Create a base set of Snuffleupagus rules to make the expert task of configuring a PHP hardening | ||
| 15 | ## extension accessible to a broader audience. This base set of rules will be integrated into a Tool - | ||
| 16 | ## see Milestone 6 (MS6) here: https://github.com/sektioneins/suhosin-ng/projects/1 | ||
| 17 | ## * Provide more configuration examples. | ||
| 18 | ## | ||
| 19 | ############################# ### # --------- | ||
| 20 | |||
| 21 | ## Let's enable relevant features first. | ||
| 22 | sp.ini_protection.enable(); | ||
| 23 | |||
| 24 | ## ===================== | ||
| 25 | ## Logging Configuration | ||
| 26 | ## ===================== | ||
| 27 | |||
| 28 | ## suhosin.log.syslog | ||
| 29 | ## suhosin.log.syslog.facility | ||
| 30 | ## suhosin.log.syslog.priority | ||
| 31 | ## suhosin.log.sapi | ||
| 32 | ## suhosin.log.stdout | ||
| 33 | ## suhosin.log.file | ||
| 34 | ## suhosin.log.file.name | ||
| 35 | ## suhosin.log.file.time | ||
| 36 | ## suhosin.log.script | ||
| 37 | ## suhosin.log.script.name | ||
| 38 | ## suhosin.log.phpscript | ||
| 39 | ## suhosin.log.phpscript.name | ||
| 40 | ## suhosin.log.phpscript.is_safe | ||
| 41 | ## suhosin.log.use-x-forwarded-for | ||
| 42 | |||
| 43 | ## SP will always use either REMOTE_ADDR or HTTP_X_FORWARDED_FOR. | ||
| 44 | |||
| 45 | ## Logging output can be one of | ||
| 46 | sp.log_media("php"); | ||
| 47 | #sp.log_media("syslog"); | ||
| 48 | |||
| 49 | ## More logging options are not implemented in SP. | ||
| 50 | |||
| 51 | ## ================ | ||
| 52 | ## Executor Options | ||
| 53 | ## ================ | ||
| 54 | |||
| 55 | ## suhosin.executor.max_depth | ||
| 56 | ## Not implemented in SP. | ||
| 57 | |||
| 58 | ## suhosin.executor.include.max_traversal | ||
| 59 | ## SP example for max_traversal = 3 | ||
| 60 | sp.disable_function.function_r("^(require|include)(_once)?$").value_r("\\.\\./+\\.\\./+\\.\\./+").drop(); | ||
| 61 | |||
| 62 | ## suhosin.executor.include.whitelist | ||
| 63 | ## suhosin.executor.include.blacklist | ||
| 64 | ## SP version with wrapper whitelist and regex matching include/require: | ||
| 65 | sp.wrappers_whitelist.list("file,php,phar"); | ||
| 66 | sp.disable_function.function_r("^(require|include)(_once)?$").value_r("^php://(stdin|stdout|stderr|input|output|memory|temp)").drop(); | ||
| 67 | |||
| 68 | ## suhosin.executor.include.allow_writable_files | ||
| 69 | ## SP can enable readonly protection | ||
| 70 | #sp.readonly_exec.enable(); | ||
| 71 | |||
| 72 | ## suhosin.executor.func.whitelist | ||
| 73 | ## suhosin.executor.func.blacklist | ||
| 74 | #sp.disable_function.function("...").drop(); | ||
| 75 | |||
| 76 | ## suhosin.executor.eval.whitelist | ||
| 77 | ## suhosin.executor.eval.blacklist | ||
| 78 | #sp.eval_blacklist.list("system,exec,shell_exec"); | ||
| 79 | |||
| 80 | ## suhosin.executor.disable_eval | ||
| 81 | #sp.disable_function.function("eval").drop(); | ||
| 82 | |||
| 83 | |||
| 84 | ## suhosin.executor.disable_emodifier | ||
| 85 | ## This is actually not needed anymore in PHP 7 and above | ||
| 86 | |||
| 87 | ## suhosin.executor.allow_symlink | ||
| 88 | ## SP can simply disable the symlink function. | ||
| 89 | ## Other ways to create symlinks should be disabled as well, e.g. system("ln -s ...") | ||
| 90 | #sp.disable_function.function("symlink").drop(); | ||
| 91 | #sp.disable_function.function("system").drop(); | ||
| 92 | #sp.disable_function.function("shell_exec").drop(); | ||
| 93 | #sp.disable_function.function("exec").drop(); | ||
| 94 | #sp.disable_function.function("proc_open").drop(); | ||
| 95 | |||
| 96 | |||
| 97 | ## | ||
| 98 | ## ============ | ||
| 99 | ## Misc Options | ||
| 100 | ## ============ | ||
| 101 | ## | ||
| 102 | |||
| 103 | ## suhosin.simulation | ||
| 104 | ## SP provides individual .simulation() switches for most features. | ||
| 105 | |||
| 106 | ## suhosin.perdir | ||
| 107 | ## Not implemented in SP. | ||
| 108 | |||
| 109 | |||
| 110 | ## suhosin.protectkey | ||
| 111 | ## SP does not actually need to protect its secret key this way, as it is not a native PHP ini directive shown in phpinfo() | ||
| 112 | |||
| 113 | ## suhosin.coredump | ||
| 114 | ## SP can be started in gdb/lldb, so this feature may not be needed. | ||
| 115 | |||
| 116 | ## suhosin.stealth | ||
| 117 | ## Not implemented in SP. | ||
| 118 | ## If ionCube support or similar extensions should ever be requested to run with SP, this feature may be implemented some day. | ||
| 119 | |||
| 120 | ## suhosin.apc_bug_workaround | ||
| 121 | ## This is not a thing anymore with PHP7+ | ||
| 122 | |||
| 123 | ## suhosin.disable.display_errors | ||
| 124 | #sp.ini.key("display_errors").set("0").ro(); | ||
| 125 | #sp.ini.key("display_startup_errors").set("0").ro(); | ||
| 126 | #sp.ini.key("expose_php").set("0").ro(); | ||
| 127 | |||
| 128 | ## suhosin.multiheader | ||
| 129 | ## There is a PHP filter in place to prevent multiple headers in one header() call - let's hope it works. | ||
| 130 | |||
| 131 | ## suhosin.mail.protect | ||
| 132 | sp.disable_function.function("mail").param("to").value_r("\\n").alias("newline in mail() To:").drop(); | ||
| 133 | sp.disable_function.function("mail").param("subject").value_r("\\n").alias("newline in mail() Subject:").drop(); | ||
| 134 | sp.disable_function.function("mail").param("additional_headers").param_type("STRING").drop(); | ||
| 135 | sp.disable_function.function("mail").param("additional_headers").param_type("NULL").allow(); | ||
| 136 | sp.disable_function.function("mail").param("additional_headers").key_r("^(to|b?cc)$").drop(); | ||
| 137 | |||
| 138 | |||
| 139 | ## suhosin.memory_limit | ||
| 140 | ## SP can either disable or limit the memory_limit setting | ||
| 141 | #sp.ini.key("memory_limit").ro(); | ||
| 142 | sp.ini.key("memory_limit").min("4M").max("256M").rw(); | ||
| 143 | |||
| 144 | |||
| 145 | ## ======================== | ||
| 146 | ## SQL Injection Protection | ||
| 147 | ## ======================== | ||
| 148 | |||
| 149 | ## suhosin.sql.bailout_on_error | ||
| 150 | ## SP example for mysqli and PDO | ||
| 151 | #sp.disable_function.function("mysqli_query").ret("FALSE").drop(); | ||
| 152 | #sp.disable_function.function("mysqli::query").ret("FALSE").drop(); | ||
| 153 | #sp.disable_function.function("mysqli_real_query").ret("FALSE").drop(); | ||
| 154 | #sp.disable_function.function("mysqli::real_query").ret("FALSE").drop(); | ||
| 155 | #sp.disable_function.function("mysqli_prepare").ret("FALSE").drop(); | ||
| 156 | #sp.disable_function.function("mysqli::prepare").ret("FALSE").drop(); | ||
| 157 | #sp.disable_function.function("mysqli_stmt_execute").ret("FALSE").drop(); | ||
| 158 | #sp.disable_function.function("mysqli_stmt::execute").ret("FALSE").drop(); | ||
| 159 | #sp.disable_function.function("mysqli_execute").ret("FALSE").drop(); | ||
| 160 | #sp.disable_function.function("PDO::query").ret("FALSE").drop(); | ||
| 161 | #sp.disable_function.function("PDO::prepare").ret("FALSE").drop(); | ||
| 162 | #sp.disable_function.function("PDO::exec").ret("FALSE").drop(); | ||
| 163 | #sp.disable_function.function("PDOStatement::execute").ret("FALSE").drop(); | ||
| 164 | |||
| 165 | |||
| 166 | ## suhosin.sql.user_match | ||
| 167 | ## suhosin.sql.user_prefix | ||
| 168 | ## suhosin.sql.user_postfix | ||
| 169 | ## SP example for mysqli | ||
| 170 | set SQL_USER "^public_"; | ||
| 171 | sp.disable_function.function("mysqli::__construct").param("username").value_r(SQL_USER).allow(); | ||
| 172 | sp.disable_function.function("mysqli::__construct").drop(); | ||
| 173 | sp.disable_function.function("mysqli_connect").param("username").value_r(SQL_USER).allow(); | ||
| 174 | sp.disable_function.function("mysqli_connect").drop(); | ||
| 175 | sp.disable_function.function("mysqli::change_user").param("username").value_r(SQL_USER).allow(); | ||
| 176 | sp.disable_function.function("mysqli::change_user").drop(); | ||
| 177 | sp.disable_function.function("mysqli_change_user").param("username").value_r(SQL_USER).allow(); | ||
| 178 | sp.disable_function.function("mysqli_change_user").drop(); | ||
| 179 | |||
| 180 | ## suhosin.sql.comment | ||
| 181 | ## suhosin.sql.opencomment | ||
| 182 | ## Not implemented in SP. | ||
| 183 | ## It is possible to try and find common injection patterns such as ' or 1=1 -- via regex, | ||
| 184 | ## but that would likely trigger valid SQL strings containing these patterns as well. The same argument | ||
| 185 | ## applies to multiselect and union: | ||
| 186 | |||
| 187 | ## suhosin.sql.multiselect | ||
| 188 | ## suhosin.sql.union | ||
| 189 | ## Not implemented in SP. | ||
| 190 | |||
| 191 | |||
| 192 | ## ============================== | ||
| 193 | ## Transparent Encryption Options | ||
| 194 | ## ============================== | ||
| 195 | |||
| 196 | ## suhosin.session.cryptkey | ||
| 197 | ## suhosin.session.cryptua | ||
| 198 | ## suhosin.cookie.cryptkey | ||
| 199 | ## suhosin.cookie.cryptua | ||
| 200 | |||
| 201 | ## SP's session encryption and cookie encryption features rely on a secret key that is derived from | ||
| 202 | ## * the user agent string from the environment variable HTTP_USER_AGENT | ||
| 203 | ## * the value of the environment variable specified using sp.global.cookie_env_var(), | ||
| 204 | ## usually either REMOTE_ADDR or SSL_SESSION_ID | ||
| 205 | ## * a very secret key as specified using sp.global.secret_key() | ||
| 206 | sp.global.secret_key("c6a0e02b3b818f7559d5f85303d8fe44"); ## this key should be unique to your installation. | ||
| 207 | sp.global.cookie_env_var("REMOTE_ADDR"); | ||
| 208 | #sp.global.cookie_env_var("SSL_SESSION_ID"); | ||
| 209 | |||
| 210 | ## suhosin.session.encrypt | ||
| 211 | sp.session.encrypt(); | ||
| 212 | |||
| 213 | ## suhosin.cookie.encrypt | ||
| 214 | ## suhosin.cookie.cryptlist | ||
| 215 | ## suhosin.cookie.plainlist | ||
| 216 | #sp.cookie.name("my_cookie_name").encrypt(); | ||
| 217 | #sp.cookie.name_r("^enc_[a-z]+$").encrypt(); | ||
| 218 | |||
| 219 | ## suhosin.session.cryptdocroot | ||
| 220 | ## suhosin.session.cryptraddr | ||
| 221 | ## suhosin.session.checkraddr | ||
| 222 | ## suhosin.cookie.cryptdocroot | ||
| 223 | ## suhosin.cookie.cryptraddr | ||
| 224 | ## suhosin.cookie.checkraddr | ||
| 225 | ## For SP to include the document root or part of the IP address in the encryption key, the .cookie_env_var() | ||
| 226 | ## can be constructed by the web server to include these values. | ||
| 227 | |||
| 228 | |||
| 229 | ## ================= | ||
| 230 | ## Filtering Options | ||
| 231 | ## ================= | ||
| 232 | |||
| 233 | ## suhosin.filter.action | ||
| 234 | ## suhosin.cookie|get|post|request.max_array_depth | ||
| 235 | ## suhosin.cookie|get|post|request.max_array_index_length | ||
| 236 | ## suhosin.cookie|get|post.max_name_length | ||
| 237 | ## suhosin.request.max_varname_length | ||
| 238 | ## suhosin.cookie|get|post|request.max_totalname_length | ||
| 239 | ## suhosin.cookie|get|post|request.max_value_length | ||
| 240 | ## suhosin.cookie|get|post|request.max_vars | ||
| 241 | ## suhosin.cookie|get|post|request.disallow_nul | ||
| 242 | ## suhosin.cookie|get|post|request.disallow_ws | ||
| 243 | ## suhosin.request.array_index_blacklist | ||
| 244 | ## suhosin.request.array_index_whitelist | ||
| 245 | ## suhosin.upload.max_uploads | ||
| 246 | ## suhosin.upload.max_newlines | ||
| 247 | ## suhosin.upload.disallow_elf | ||
| 248 | ## suhosin.upload.disallow_binary | ||
| 249 | ## suhosin.upload.remove_binary | ||
| 250 | ## suhosin.upload.allow_utf8 | ||
| 251 | ## Not implemented in SP. | ||
| 252 | |||
| 253 | ## suhosin.upload.verification_script | ||
| 254 | #sp.upload_validation.script("/var/www/is_valid_php.py").enable(); | ||
| 255 | |||
| 256 | |||
| 257 | ## suhosin.session.max_id_length | ||
| 258 | ## suhosin.server.encode | ||
| 259 | ## suhosin.server.strip | ||
| 260 | ## Not implemented in SP. | ||
| 261 | |||
| 262 | ## suhosin.rand.seedingkey | ||
| 263 | ## suhosin.rand.reseed_every_request | ||
| 264 | ## suhosin.srand.ignore | ||
| 265 | ## suhosin.mt_srand.ignore | ||
| 266 | ## Instead of removing srand()/mt_srand(), SP basically replaces rand()/mt_rand() with the more secure random_int() | ||
| 267 | sp.harden_random.enable(); | ||
| 268 | |||
| 269 | ############################# ### # --------- | ||
| 270 | ## | ||
| 271 | ## features included in SP that are not covered by Suhosin rule equivalents | ||
| 272 | ## - see https://snuffleupagus.readthedocs.io/ for more information | ||
| 273 | |||
| 274 | # sp.unserialize_hmac.enable(); | ||
| 275 | # sp.global_strict.enable(); | ||
| 276 | sp.auto_cookie_secure.enable(); | ||
| 277 | #sp.cookie.name("cookie1").samesite("lax"); | ||
| 278 | #sp.cookie.name("cookie2").samesite("strict");; | ||
| 279 | sp.xxe_protection.enable(); | ||
| 280 | #sp.sloppy_comparison.enable(); | ||
| 281 | |||
diff --git a/config/typo3.rules b/config/typo3.rules index c76cf91..0838b89 100644 --- a/config/typo3.rules +++ b/config/typo3.rules | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | sp.disable_function.function("chmod").param("mode").filename_r("typo3/sysext/core/Classes/Utility/GeneralUtility.php$").value_r("^[0-9]{2}6$").allow(); | 2 | sp.disable_function.function("chmod").param("mode").filename_r("typo3/sysext/core/Classes/Utility/GeneralUtility.php$").value_r("^[0-9]{2}6$").allow(); |
| 3 | sp.disable_function.function("chmod").param("mode").value_r("^[0-9]{2}[67]$").drop(); | 3 | sp.disable_function.function("chmod").param("mode").value_r("^[0-9]{2}[67]$").drop(); |
| 4 | 4 | ||
| 5 | ##Prevent various `include`-related vulnerabilities | 5 | # Prevent various `include`-related vulnerabilities |
| 6 | sp.disable_function.function("require_once").value_r("\.php$").allow(); | 6 | sp.disable_function.function("require_once").value_r("\.php$").allow(); |
| 7 | sp.disable_function.function("include_once").value_r("\.php$").allow(); | 7 | sp.disable_function.function("include_once").value_r("\.php$").allow(); |
| 8 | sp.disable_function.function("require").value_r("\.php$").allow(); | 8 | sp.disable_function.function("require").value_r("\.php$").allow(); |
| @@ -27,14 +27,14 @@ sp.disable_function.function("ini_set").param("var_name").value("memory_limit"). | |||
| 27 | sp.disable_function.function("ini_set").param("var_name").value("include_path").drop(); | 27 | sp.disable_function.function("ini_set").param("var_name").value("include_path").drop(); |
| 28 | sp.disable_function.function("ini_set").param("var_name").value("open_basedir").drop(); | 28 | sp.disable_function.function("ini_set").param("var_name").value("open_basedir").drop(); |
| 29 | 29 | ||
| 30 | # Detect some backdoors via environnement recon | 30 | # Detect some backdoors via environment recon |
| 31 | sp.disable_function.function("ini_get").param("var_name").filename_r("typo3/sysext/core/Classes/Cache/Backend/SimpleFileBackend.php$").value("open_basedir").allow(); | 31 | sp.disable_function.function("ini_get").param("var_name").filename_r("typo3/sysext/core/Classes/Cache/Backend/SimpleFileBackend.php$").value("open_basedir").allow(); |
| 32 | sp.disable_function.function("ini_get").param("var_name").filename_r("typo3/sysext/install/Classes/SystemEnvironment/Check.php$").value("open_basedir").allow(); | 32 | sp.disable_function.function("ini_get").param("var_name").filename_r("typo3/sysext/install/Classes/SystemEnvironment/Check.php$").value("open_basedir").allow(); |
| 33 | sp.disable_function.function("ini_get").param("var_name").filename_r("typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php$").value("allow_url_fopen").allow(); | 33 | sp.disable_function.function("ini_get").param("var_name").filename_r("typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php$").value("allow_url_fopen").allow(); |
| 34 | sp.disable_function.function("ini_get").param("var_name").filename_r("vendor/guzzlehttp/guzzle/src/functions.php$").value("allow_url_fopen").allow(); | 34 | sp.disable_function.function("ini_get").param("var_name").filename_r("vendor/guzzlehttp/guzzle/src/functions.php$").value("allow_url_fopen").allow(); |
| 35 | sp.disable_function.function("ini_get").param("var_name").value_r("^(?:allow_url_fopen|open_basedir|suhosin)$").drop(); | 35 | sp.disable_function.function("ini_get").param("var_name").value_r("^(?:allow_url_fopen|open_basedir|suhosin)$").drop(); |
| 36 | 36 | ||
| 37 | #need to be allow for example to execute Scheduled tasks | 37 | # Need to be allow for example to execute Scheduled tasks |
| 38 | sp.disable_function.function("function_exists").param("function_name").filename_r("vendor/guzzlehttp/guzzle/src/functions.php$").value_r("^(?:curl_multi_exec|curl_exec)$").allow(); | 38 | sp.disable_function.function("function_exists").param("function_name").filename_r("vendor/guzzlehttp/guzzle/src/functions.php$").value_r("^(?:curl_multi_exec|curl_exec)$").allow(); |
| 39 | sp.disable_function.function("function_exists").param("function_name").value_r("(?:eval|exec|system)").drop(); | 39 | sp.disable_function.function("function_exists").param("function_name").value_r("(?:eval|exec|system)").drop(); |
| 40 | sp.disable_function.function("is_callable").param("var").value_r("(?:eval|exec|system)").drop(); | 40 | sp.disable_function.function("is_callable").param("var").value_r("(?:eval|exec|system)").drop(); |
| @@ -48,6 +48,6 @@ sp.disable_function.function("QueryBuilder::setParameter").param("value").value_ | |||
| 48 | sp.disable_function.function("QueryBuilder::setParameter").param("value").value_r("sleep").drop(); | 48 | sp.disable_function.function("QueryBuilder::setParameter").param("value").value_r("sleep").drop(); |
| 49 | sp.disable_function.function("QueryBuilder::setParameter").param("value").value_r("information_schema").drop(); | 49 | sp.disable_function.function("QueryBuilder::setParameter").param("value").value_r("information_schema").drop(); |
| 50 | 50 | ||
| 51 | #File upload | 51 | # File upload |
| 52 | sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ph").drop(); | 52 | sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ph").drop(); |
| 53 | sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ht").drop(); | 53 | sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ht").drop(); |
