File: default.rules

package info (click to toggle)
snuffleupagus 0.13.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,864 kB
  • sloc: ansic: 6,326; php: 128; makefile: 98; python: 80; sh: 3
file content (206 lines) | stat: -rw-r--r-- 11,873 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# This is the default configuration file for Snuffleupagus (https://snuffleupagus.rtfd.io).
# It contains "reasonable" defaults that won't break your websites,
# and a lot of commented directives that you can enable if you want to 
# have a better protection.

# Harden the PRNG
sp.harden_random.enable();

# Enable XXE protection
@condition extension_loaded("xml");
sp.xxe_protection.enable();
@end_condition;

# Global configuration variables
# sp.global.secret_key("YOU _DO_ NEED TO CHANGE THIS WITH SOME RANDOM CHARACTERS.");

# Globally activate strict mode
# https://www.php.net/manual/en/language.types.declarations.php#language.types.declarations.strict
# sp.global_strict.enable();

# Prevent unserialize-related exploits
# sp.unserialize_hmac.enable();

# Only allow execution of read-only files. This is a low-hanging fruit that you should enable.
# sp.readonly_exec.enable();

# PHP has a lot of wrappers, most of them aren't usually useful, you should
# only enable the ones you're using.
# sp.wrappers_whitelist.list("file,php,phar");

# Prevent sloppy comparisons.
# sp.sloppy_comparison.enable();

# Use SameSite on session cookie
# https://snuffleupagus.readthedocs.io/features.html#protection-against-cross-site-request-forgery
sp.cookie.name("PHPSESSID").samesite("lax");

# Harden the `chmod` function (0777 (oct = 511, 0666 = 438)
@condition PHP_VERSION_ID < 80000;
    sp.disable_function.function("chmod").param("mode").value("438").drop();
    sp.disable_function.function("chmod").param("mode").value("511").drop();
@condition PHP_VERSION_ID >= 80000;
    sp.disable_function.function("chmod").param("permissions").value("438").drop();
    sp.disable_function.function("chmod").param("permissions").value("511").drop();
@end_condition;

# Prevent various `mail`-related vulnerabilities
@condition PHP_VERSION_ID < 80300;
sp.disable_function.function("mail").param("additional_parameters").value_r("\\-").drop();
@condition PHP_VERSION_ID >= 80300;
sp.disable_function.function("mail").param("additional_params").value_r("\\-").drop();
@end_condition;

# Since it's now burned, me might as well mitigate it publicly
@condition PHP_VERSION_ID < 80000;
    sp.disable_function.function("putenv").param("setting").value_r("LD_").drop();
    sp.disable_function.function("putenv").param("setting").value("PATH").drop();
@condition PHP_VERSION_ID >= 80000;
    sp.disable_function.function("putenv").param("assignment").value_r("LD_").drop();
    sp.disable_function.function("putenv").param("assignment").value("PATH").drop();
@end_condition;

# This one was burned in Nov 2019 - https://gist.github.com/LoadLow/90b60bd5535d6c3927bb24d5f9955b80
@condition PHP_VERSION_ID < 80000;
    sp.disable_function.function("putenv").param("setting").value_r("GCONV_").drop()
@condition PHP_VERSION_ID >= 80000;
    sp.disable_function.function("putenv").param("assignment").value_r("GCONV_").drop()
@end_condition;

# Since people are stupid enough to use `extract` on things like $_GET or $_POST, we might as well mitigate this vector
@condition PHP_VERSION_ID < 80000;
sp.disable_function.function("extract").pos("0").value_r("^_").drop()
sp.disable_function.function("extract").pos("1").value("0").drop()
@condition PHP_VERSION_ID >= 80000;
sp.disable_function.function("extract").param("array").value_r("^_").drop()
sp.disable_function.function("extract").param("flags").value("0").drop()
@end_condition;

# This is also burned:
# ini_set('open_basedir','..');chdir('..');…;chdir('..');ini_set('open_basedir','/');echo(file_get_contents('/etc/passwd'));
# Since we have no way of matching on two parameters at the same time, we're
# blocking calls to open_basedir altogether: nobody is using it via ini_set anyway.
# Moreover, there are non-public bypasses that are also using this vector ;)
@condition PHP_VERSION_ID < 80000;
    sp.disable_function.function("ini_set").param("varname").value_r("open_basedir").drop()
@condition PHP_VERSION_ID >= 80000;
    sp.disable_function.function("ini_set").param("option").value_r("open_basedir").drop()
@end_condition;

# Prevent various `include`-related vulnerabilities
sp.disable_function.function("require_once").value_r("\.(inc|phtml|php)$").allow();
sp.disable_function.function("include_once").value_r("\.(inc|phtml|php)$").allow();
sp.disable_function.function("require").value_r("\.(inc|phtml|php)$").allow();
sp.disable_function.function("include").value_r("\.(inc|phtml|php)$").allow();
sp.disable_function.function("require_once").drop();
sp.disable_function.function("include_once").drop();
sp.disable_function.function("require").drop();
sp.disable_function.function("include").drop();

# Prevent `system`-related injections
sp.disable_function.function("system").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
@condition PHP_VERSION_ID < 80000;
    sp.disable_function.function("shell_exec").pos("0").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
@condition PHP_VERSION_ID >= 80000;
    sp.disable_function.function("shell_exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
@end_condition;
sp.disable_function.function("exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
sp.disable_function.function("proc_open").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();

# Prevent runtime modification of interesting things
@condition PHP_VERSION_ID < 80000;
sp.disable_function.function("ini_set").param("varname").value("assert.active").drop();
sp.disable_function.function("ini_set").param("varname").value("zend.assertions").drop();
sp.disable_function.function("ini_set").param("varname").value("memory_limit").drop();
sp.disable_function.function("ini_set").param("varname").value("include_path").drop();
sp.disable_function.function("ini_set").param("varname").value("open_basedir").drop();
@condition PHP_VERSION_ID >= 80000;
sp.disable_function.function("ini_set").param("option").value("assert.active").drop();
sp.disable_function.function("ini_set").param("option").value("zend.assertions").drop();
sp.disable_function.function("ini_set").param("option").value("memory_limit").drop();
sp.disable_function.function("ini_set").param("option").value("include_path").drop();
sp.disable_function.function("ini_set").param("option").value("open_basedir").drop();
@end_condition;

# Detect some backdoors via environment recon
@condition PHP_VERSION_ID < 80000;
sp.disable_function.function("ini_get").param("varname").value("allow_url_fopen").drop();
sp.disable_function.function("ini_get").param("varname").value("open_basedir").drop();
sp.disable_function.function("ini_get").param("varname").value_r("suhosin").drop();
sp.disable_function.function("function_exists").param("function_name").value("eval").drop();
sp.disable_function.function("function_exists").param("function_name").value("exec").drop();
sp.disable_function.function("function_exists").param("function_name").value("system").drop();
sp.disable_function.function("function_exists").param("function_name").value("shell_exec").drop();
sp.disable_function.function("function_exists").param("function_name").value("proc_open").drop();
sp.disable_function.function("function_exists").param("function_name").value("passthru").drop();
sp.disable_function.function("is_callable").param("var").value("eval").drop();
sp.disable_function.function("is_callable").param("var").value("exec").drop();
sp.disable_function.function("is_callable").param("var").value("system").drop();
sp.disable_function.function("is_callable").param("var").value("shell_exec").drop();
sp.disable_function.function("is_callable").param("var").value("proc_open").drop();
sp.disable_function.function("is_callable").param("var").value("passthru").drop();
@condition PHP_VERSION_ID >= 80000;
sp.disable_function.function("ini_get").param("option").value("allow_url_fopen").drop();
sp.disable_function.function("ini_get").param("option").value("open_basedir").drop();
sp.disable_function.function("ini_get").param("option").value_r("suhosin").drop();
sp.disable_function.function("function_exists").param("function").value("eval").drop();
sp.disable_function.function("function_exists").param("function").value("exec").drop();
sp.disable_function.function("function_exists").param("function").value("system").drop();
sp.disable_function.function("function_exists").param("function").value("shell_exec").drop();
sp.disable_function.function("function_exists").param("function").value("proc_open").drop();
sp.disable_function.function("function_exists").param("function").value("passthru").drop();
sp.disable_function.function("is_callable").param("value").value("eval").drop();
sp.disable_function.function("is_callable").param("value").value("exec").drop();
sp.disable_function.function("is_callable").param("value").value("system").drop();
sp.disable_function.function("is_callable").param("value").value("shell_exec").drop();
sp.disable_function.function("is_callable").param("value").value("proc_open").drop();
sp.disable_function.function("is_callable").param("value").value("passthru").drop();
@end_condition;


# Ghetto error-based sqli detection
# sp.disable_function.function("mysql_query").ret("FALSE").drop();
# sp.disable_function.function("mysqli_query").ret("FALSE").drop();
# sp.disable_function.function("PDO::query").ret("FALSE").drop();

# Ensure that certificates are properly verified
sp.disable_function.function("curl_setopt").param("value").value("1").allow();
sp.disable_function.function("curl_setopt").param("value").value("2").allow();
# `81` is SSL_VERIFYHOST and `64` SSL_VERIFYPEER
sp.disable_function.function("curl_setopt").param("option").value("64").drop().alias("Please don't turn CURLOPT_SSL_VERIFYCLIENT off.");
sp.disable_function.function("curl_setopt").param("option").value("81").drop().alias("Please don't turn CURLOPT_SSL_VERIFYHOST off.");

# Ensure that file:// protocol is not allowed in CURL
sp.disable_function.function("curl_setopt").param("value").value_r("file://").drop().alias("file:// protocol is disabled");
sp.disable_function.function("curl_init").param("url").value_r("file://").drop().alias("file:// protocol is disabled");

# File upload
@condition PHP_VERSION_ID >= 80000;
sp.disable_function.function("move_uploaded_file").param("to").value_r("\\.ph").drop();
sp.disable_function.function("move_uploaded_file").param("to").value_r("\\.ht").drop();
@condition PHP_VERSION_ID >= 70400;
sp.disable_function.function("move_uploaded_file").param("new_path").value_r("\\.ph").drop();
sp.disable_function.function("move_uploaded_file").param("new_path").value_r("\\.ht").drop();
@condition PHP_VERSION_ID >= 70000;
sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ph").drop();
sp.disable_function.function("move_uploaded_file").param("destination").value_r("\\.ht").drop();
@end_condition;

# Logging lockdown
@condition PHP_VERSION_ID >= 70000;
sp.disable_function.function("ini_set").param("varname").value_r("error_log").drop();
sp.disable_function.function("ini_set").param("varname").value_r("error_reporting").drop();
sp.disable_function.function("ini_set").param("varname").value_r("display_errors").drop();
@condition PHP_VERSION_ID >= 80000;
sp.disable_function.function("ini_set").param("option").value_r("error_log").drop();
sp.disable_function.function("ini_set").param("option").value_r("error_reporting").drop();
sp.disable_function.function("ini_set").param("option").value_r("display_errors").drop();
@end_condition;

# Classic webshells patterns
sp.disable_function.function("system>base64_decode").drop();
sp.disable_function.function("shell_exec>base64_decode").drop();
sp.disable_function.function("exec>base64_decode").drop();
sp.disable_function.function("passthru>base64_decode").drop();
sp.disable_function.function("proc_open>base64_decode").drop();
sp.eval_blacklist.list("system,exec,shell_exec,passthru,proc_open");