1
1
import http
2
2
import urllib .parse
3
+ import uuid
3
4
from random import randrange
4
5
5
6
import pytest
@@ -13,6 +14,10 @@ def get_url(path: str) -> str:
13
14
return urllib .parse .urljoin (ENDPOINT , path )
14
15
15
16
17
+ def url_encode_all (string ):
18
+ return "" .join ("%{0:0>2x}" .format (ord (char )) for char in string )
19
+
20
+
16
21
@pytest .fixture
17
22
def user_agent ():
18
23
return {"User-Agent" : UA }
@@ -75,37 +80,78 @@ def test_password_json_3(request_kwargs):
75
80
assert response .status_code == http .HTTPStatus .FORBIDDEN
76
81
77
82
83
+ def test_nosql_1 (request_kwargs ):
84
+ """This should work as it uses NOSQL"""
85
+ data = {}
86
+ data [str (uuid .uuid1 ())] = "test' or '1'='1"
87
+ response = requests .post (get_url ("/nosql/update" ), data = data , ** request_kwargs )
88
+ assert response .status_code == http .HTTPStatus .OK
89
+
90
+
91
+ def test_nosql_2 (request_kwargs ):
92
+ """NOSQL exploitation attempts should be blocked"""
93
+ data = {"username" : {"$eq" : "admin" }, "password" : {"$regex" : "^mdp" }}
94
+ response = requests .post (get_url ("/nosql/update" ), json = data , ** request_kwargs )
95
+ assert response .status_code == http .HTTPStatus .FORBIDDEN
96
+
97
+
78
98
def test_cookie_1 (user_agent ):
79
- """As an example, this cookie is considered safe and WAF should not block it"""
80
- cookie = "yummy_cookie=uname-it ; tasty_cookie=strawberry"
99
+ """These cookies are considered safe and WAF should not block it"""
100
+ cookie = "yummy_cookie=banana ; tasty_cookie=strawberry"
81
101
headers = {** user_agent , "Cookie" : cookie }
82
102
response = requests .get (get_url ("/cookies" ), headers = headers )
83
103
assert response .status_code == http .HTTPStatus .OK
84
104
85
105
86
106
def test_cookie_2 (user_agent ):
107
+ """As an example, this cookie is considered safe and WAF should not block it"""
108
+ cookie = "delicious_cookie=uname-it; tasty_cookie=strawberry"
109
+ headers = {** user_agent , "Cookie" : cookie }
110
+ response = requests .get (get_url ("/cookies" ), headers = headers )
111
+ assert response .status_code == http .HTTPStatus .OK
112
+
113
+
114
+ def test_cookie_3 (user_agent ):
87
115
"""Create custom rule to detect use of `username` cookie and prevent use of it"""
88
116
cookie = "username=admin; session-id=73101f80-727c-4c4d-b812-9023d40e8510"
89
117
headers = {** user_agent , "Cookie" : cookie }
90
118
response = requests .get (get_url ("/cookies" ), headers = headers )
91
119
assert response .status_code == http .HTTPStatus .FORBIDDEN
92
120
93
121
94
- def test_cookie_3 (user_agent ):
122
+ def test_cookie_4 (user_agent ):
95
123
"""Lets assume this is a legit cookie and needs to be allowed"""
96
- cookie = 'SESSION=a:2:{i:0 ;s:4:"bob";i:1 ;s:33:"admin \' istrator \' =" ;}'
124
+ cookie = 'SESSION=O:13:"ConvisoPerson":5:{s:8:"username" ;s:6:"Antony";s: 4:"team";s:5:"PTaaS";s:3:"age";i:17 ;s:6:"office";s:6:"Intern";s:12:"accountAdmin";b:0 ;}'
97
125
headers = {** user_agent , "Cookie" : cookie }
98
126
response = requests .get (get_url ("/cookies" ), headers = headers )
99
127
assert response .status_code == http .HTTPStatus .OK
100
128
101
129
130
+ def test_cookie_5 (user_agent ):
131
+ """Lets assume this is a legit cookie and needs to be allowed"""
132
+ cookie = f"SESSION={ str (uuid .uuid1 ())} |uname -a"
133
+ headers = {** user_agent , "Cookie" : cookie }
134
+ response = requests .get (get_url ("/cookies" ), headers = headers )
135
+ assert response .status_code == http .HTTPStatus .FORBIDDEN
136
+
137
+
102
138
def test_get_params_1 (request_kwargs ):
103
- """This get parameter should not be blocked"""
139
+ """This get parameter value is considered safe and should not be blocked"""
104
140
response = requests .get (get_url ("/status" ) + "?action=netstat" , ** request_kwargs )
105
141
assert response .status_code == http .HTTPStatus .OK
106
142
107
143
108
- def test_get_params_2 (request_kwargs ):
144
+ @pytest .mark .parametrize (
145
+ "cmd" ,
146
+ ["whoami" , "uname" , "netcat" , "wget" ],
147
+ )
148
+ def test_get_params_2 (cmd : str , request_kwargs ):
149
+ """This and any other potential RCE attack parameter values should be blocked"""
150
+ response = requests .get (get_url ("/status" ) + f"?action={ cmd } " , ** request_kwargs )
151
+ assert response .status_code == http .HTTPStatus .FORBIDDEN
152
+
153
+
154
+ def test_get_params_3 (request_kwargs ):
109
155
"""The below activity should be blocked"""
110
156
response = requests .get (get_url ("/status" ) + "?cmd=whoami" , ** request_kwargs )
111
157
assert response .status_code == http .HTTPStatus .FORBIDDEN
@@ -118,3 +164,90 @@ def test_user_agent_1():
118
164
}
119
165
response = requests .get (get_url ("/ua" ), headers = headers )
120
166
assert response .status_code == http .HTTPStatus .OK
167
+
168
+
169
+ def test_user_agent_2 ():
170
+ """The below user-agent includes RCE attack attempt and must be blocked"""
171
+ headers = {
172
+ "User-Agent" : 'Mozilla/5.0 (Linux; Android 10; id) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Mobile Safari/537.3; echo "<h1>Defaced</h1>" > /var/www/html/public/index.php'
173
+ }
174
+ response = requests .get (get_url ("/ua" ), headers = headers )
175
+ assert response .status_code == http .HTTPStatus .FORBIDDEN
176
+
177
+
178
+ @pytest .mark .parametrize (
179
+ "filename" ,
180
+ ["backup.sql" , "dump.sql" , "backup.old" , "HEAD" , "settings.xml" , "config.json" ],
181
+ )
182
+ def test_file_1 (
183
+ filename : str ,
184
+ ):
185
+ """Prevent users from accessing sensitive files anywhere on the server"""
186
+ path = f"/{ str (uuid .uuid1 ())} /{ filename } "
187
+ response = requests .get (get_url (path ))
188
+ assert response .status_code == http .HTTPStatus .NOT_FOUND
189
+
190
+
191
+ @pytest .mark .parametrize (
192
+ "filename" ,
193
+ [
194
+ "jquery.js" ,
195
+ "index.css" ,
196
+ "latin-wght-normal.woff2" ,
197
+ ],
198
+ )
199
+ def test_file_2 (filename : str , request_kwargs ):
200
+ """Allow to download static content"""
201
+ path = f"/{ str (uuid .uuid1 ())} /{ filename } "
202
+ response = requests .get (get_url (path ), ** request_kwargs )
203
+ assert response .status_code == http .HTTPStatus .OK
204
+
205
+
206
+ @pytest .mark .parametrize (
207
+ "path" ,
208
+ [
209
+ "/var/www/html/config.json" ,
210
+ "/var/www/html/public/index.php" ,
211
+ "/etc/passwd" ,
212
+ "/proc/self/environ" ,
213
+ "/var/log/nginx/access.log" ,
214
+ ],
215
+ )
216
+ def test_file_3 (path : str , request_kwargs ):
217
+ """Prevent users from accessing files outside /home/* directory"""
218
+ response = requests .get (
219
+ get_url ("/file/api" ) + f"?path={ url_encode_all (path )} " , ** request_kwargs
220
+ )
221
+ assert response .status_code == http .HTTPStatus .NOT_FOUND
222
+
223
+
224
+ @pytest .mark .parametrize (
225
+ "path" ,
226
+ [
227
+ "/etc/passwd" ,
228
+ "/proc/self/environ" ,
229
+ ],
230
+ )
231
+ def test_file_4 (path : str , request_kwargs ):
232
+ """Requests for system files should be blocked in general"""
233
+ response = requests .get (
234
+ get_url ("/system/manage" ) + f"?path={ url_encode_all (path )} " , ** request_kwargs
235
+ )
236
+ assert response .status_code == http .HTTPStatus .FORBIDDEN
237
+
238
+
239
+ @pytest .mark .parametrize (
240
+ "filename" ,
241
+ [
242
+ "report.pdf" ,
243
+ "notes.txt" ,
244
+ "index.php" ,
245
+ ],
246
+ )
247
+ def test_file_5 (filename : str , request_kwargs ):
248
+ """Allow accessing specific files"""
249
+ response = requests .get (
250
+ get_url ("/file/api" ) + f"?path=/home/{ str (uuid .uuid1 ())} /{ filename } " ,
251
+ ** request_kwargs ,
252
+ )
253
+ assert response .status_code == http .HTTPStatus .OK
0 commit comments