Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/extra/vulnserver/vulnserver.py
3556 views
1
#!/usr/bin/env python
2
3
"""
4
vulnserver.py - Trivial SQLi vulnerable HTTP server (Note: for testing purposes)
5
6
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
7
See the file 'LICENSE' for copying permission
8
"""
9
10
from __future__ import print_function
11
12
import base64
13
import json
14
import random
15
import re
16
import sqlite3
17
import string
18
import sys
19
import threading
20
import traceback
21
22
PY3 = sys.version_info >= (3, 0)
23
UNICODE_ENCODING = "utf-8"
24
DEBUG = False
25
26
if PY3:
27
from http.client import INTERNAL_SERVER_ERROR
28
from http.client import NOT_FOUND
29
from http.client import OK
30
from http.server import BaseHTTPRequestHandler
31
from http.server import HTTPServer
32
from socketserver import ThreadingMixIn
33
from urllib.parse import parse_qs
34
from urllib.parse import unquote_plus
35
else:
36
from BaseHTTPServer import BaseHTTPRequestHandler
37
from BaseHTTPServer import HTTPServer
38
from httplib import INTERNAL_SERVER_ERROR
39
from httplib import NOT_FOUND
40
from httplib import OK
41
from SocketServer import ThreadingMixIn
42
from urlparse import parse_qs
43
from urllib import unquote_plus
44
45
SCHEMA = """
46
CREATE TABLE users (
47
id INTEGER,
48
name TEXT,
49
surname TEXT,
50
PRIMARY KEY (id)
51
);
52
INSERT INTO users (id, name, surname) VALUES (1, 'luther', 'blisset');
53
INSERT INTO users (id, name, surname) VALUES (2, 'fluffy', 'bunny');
54
INSERT INTO users (id, name, surname) VALUES (3, 'wu', 'ming');
55
INSERT INTO users (id, name, surname) VALUES (4, NULL, 'nameisnull');
56
INSERT INTO users (id, name, surname) VALUES (5, 'mark', 'lewis');
57
INSERT INTO users (id, name, surname) VALUES (6, 'ada', 'lovelace');
58
INSERT INTO users (id, name, surname) VALUES (7, 'grace', 'hopper');
59
INSERT INTO users (id, name, surname) VALUES (8, 'alan', 'turing');
60
INSERT INTO users (id, name, surname) VALUES (9, 'margaret','hamilton');
61
INSERT INTO users (id, name, surname) VALUES (10, 'donald', 'knuth');
62
INSERT INTO users (id, name, surname) VALUES (11, 'tim', 'bernerslee');
63
INSERT INTO users (id, name, surname) VALUES (12, 'linus', 'torvalds');
64
INSERT INTO users (id, name, surname) VALUES (13, 'ken', 'thompson');
65
INSERT INTO users (id, name, surname) VALUES (14, 'dennis', 'ritchie');
66
INSERT INTO users (id, name, surname) VALUES (15, 'barbara', 'liskov');
67
INSERT INTO users (id, name, surname) VALUES (16, 'edsger', 'dijkstra');
68
INSERT INTO users (id, name, surname) VALUES (17, 'john', 'mccarthy');
69
INSERT INTO users (id, name, surname) VALUES (18, 'leslie', 'lamport');
70
INSERT INTO users (id, name, surname) VALUES (19, 'niklaus', 'wirth');
71
INSERT INTO users (id, name, surname) VALUES (20, 'bjarne', 'stroustrup');
72
INSERT INTO users (id, name, surname) VALUES (21, 'guido', 'vanrossum');
73
INSERT INTO users (id, name, surname) VALUES (22, 'brendan', 'eich');
74
INSERT INTO users (id, name, surname) VALUES (23, 'james', 'gosling');
75
INSERT INTO users (id, name, surname) VALUES (24, 'andrew', 'tanenbaum');
76
INSERT INTO users (id, name, surname) VALUES (25, 'yukihiro','matsumoto');
77
INSERT INTO users (id, name, surname) VALUES (26, 'radia', 'perlman');
78
INSERT INTO users (id, name, surname) VALUES (27, 'katherine','johnson');
79
INSERT INTO users (id, name, surname) VALUES (28, 'hady', 'lamarr');
80
INSERT INTO users (id, name, surname) VALUES (29, 'frank', 'miller');
81
INSERT INTO users (id, name, surname) VALUES (30, 'john', 'steward');
82
83
CREATE TABLE creds (
84
user_id INTEGER,
85
password_hash TEXT,
86
FOREIGN KEY (user_id) REFERENCES users(id)
87
);
88
INSERT INTO creds (user_id, password_hash) VALUES (1, 'db3a16990a0008a3b04707fdef6584a0');
89
INSERT INTO creds (user_id, password_hash) VALUES (2, '4db967ce67b15e7fb84c266a76684729');
90
INSERT INTO creds (user_id, password_hash) VALUES (3, 'f5a2950eaa10f9e99896800eacbe8275');
91
INSERT INTO creds (user_id, password_hash) VALUES (4, NULL);
92
INSERT INTO creds (user_id, password_hash) VALUES (5, '179ad45c6ce2cb97cf1029e212046e81');
93
INSERT INTO creds (user_id, password_hash) VALUES (6, '0f1e2d3c4b5a69788796a5b4c3d2e1f0');
94
INSERT INTO creds (user_id, password_hash) VALUES (7, 'a1b2c3d4e5f60718293a4b5c6d7e8f90');
95
INSERT INTO creds (user_id, password_hash) VALUES (8, '1a2b3c4d5e6f708192a3b4c5d6e7f809');
96
INSERT INTO creds (user_id, password_hash) VALUES (9, '9f8e7d6c5b4a3928170605f4e3d2c1b0');
97
INSERT INTO creds (user_id, password_hash) VALUES (10, '3c2d1e0f9a8b7c6d5e4f30291807f6e5');
98
INSERT INTO creds (user_id, password_hash) VALUES (11, 'b0c1d2e3f405162738495a6b7c8d9eaf');
99
INSERT INTO creds (user_id, password_hash) VALUES (12, '6e5d4c3b2a190807f6e5d4c3b2a1908f');
100
INSERT INTO creds (user_id, password_hash) VALUES (13, '11223344556677889900aabbccddeeff');
101
INSERT INTO creds (user_id, password_hash) VALUES (14, 'ffeeddccbbaa00998877665544332211');
102
INSERT INTO creds (user_id, password_hash) VALUES (15, '1234567890abcdef1234567890abcdef');
103
INSERT INTO creds (user_id, password_hash) VALUES (16, 'abcdef1234567890abcdef1234567890');
104
INSERT INTO creds (user_id, password_hash) VALUES (17, '0a1b2c3d4e5f60718a9b0c1d2e3f4051');
105
INSERT INTO creds (user_id, password_hash) VALUES (18, '51f04e3d2c1b0a9871605f4e3d2c1b0a');
106
INSERT INTO creds (user_id, password_hash) VALUES (19, '89abcdef0123456789abcdef01234567');
107
INSERT INTO creds (user_id, password_hash) VALUES (20, '76543210fedcba9876543210fedcba98');
108
INSERT INTO creds (user_id, password_hash) VALUES (21, '13579bdf2468ace013579bdf2468ace0');
109
INSERT INTO creds (user_id, password_hash) VALUES (22, '02468ace13579bdf02468ace13579bdf');
110
INSERT INTO creds (user_id, password_hash) VALUES (23, 'deadbeefdeadbeefdeadbeefdeadbeef');
111
INSERT INTO creds (user_id, password_hash) VALUES (24, 'cafebabecafebabecafebabecafebabe');
112
INSERT INTO creds (user_id, password_hash) VALUES (25, '00112233445566778899aabbccddeeff');
113
INSERT INTO creds (user_id, password_hash) VALUES (26, 'f0e1d2c3b4a5968778695a4b3c2d1e0f');
114
INSERT INTO creds (user_id, password_hash) VALUES (27, '7f6e5d4c3b2a190807f6e5d4c3b2a190');
115
INSERT INTO creds (user_id, password_hash) VALUES (28, '908f7e6d5c4b3a291807f6e5d4c3b2a1');
116
INSERT INTO creds (user_id, password_hash) VALUES (29, '3049b791fa83e2f42f37bae18634b92d');
117
INSERT INTO creds (user_id, password_hash) VALUES (30, 'd59a348f90d757c7da30418773424b5e');
118
"""
119
120
LISTEN_ADDRESS = "localhost"
121
LISTEN_PORT = 8440
122
123
_conn = None
124
_cursor = None
125
_lock = None
126
_server = None
127
_alive = False
128
_csrf_token = None
129
130
def init(quiet=False):
131
global _conn
132
global _cursor
133
global _lock
134
global _csrf_token
135
136
_csrf_token = "".join(random.sample(string.ascii_letters + string.digits, 20))
137
138
_conn = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False)
139
_cursor = _conn.cursor()
140
_lock = threading.Lock()
141
142
_cursor.executescript(SCHEMA)
143
144
if quiet:
145
global print
146
147
def _(*args, **kwargs):
148
pass
149
150
print = _
151
152
class ThreadingServer(ThreadingMixIn, HTTPServer):
153
def finish_request(self, *args, **kwargs):
154
try:
155
HTTPServer.finish_request(self, *args, **kwargs)
156
except Exception:
157
if DEBUG:
158
traceback.print_exc()
159
160
class ReqHandler(BaseHTTPRequestHandler):
161
def do_REQUEST(self):
162
path, query = self.path.split('?', 1) if '?' in self.path else (self.path, "")
163
params = {}
164
165
if query:
166
params.update(parse_qs(query))
167
168
if "<script>" in unquote_plus(query):
169
self.send_response(INTERNAL_SERVER_ERROR)
170
self.send_header("X-Powered-By", "Express")
171
self.send_header("Connection", "close")
172
self.end_headers()
173
self.wfile.write("CLOUDFLARE_ERROR_500S_BOX".encode(UNICODE_ENCODING))
174
return
175
176
if hasattr(self, "data"):
177
if self.data.startswith('{') and self.data.endswith('}'):
178
params.update(json.loads(self.data))
179
elif self.data.startswith('<') and self.data.endswith('>'):
180
params.update(dict((_[0], _[1].replace("&apos;", "'").replace("&quot;", '"').replace("&lt;", '<').replace("&gt;", '>').replace("&amp;", '&')) for _ in re.findall(r'name="([^"]+)" value="([^"]*)"', self.data)))
181
else:
182
self.data = self.data.replace(';', '&') # Note: seems that Python3 started ignoring parameter splitting with ';'
183
params.update(parse_qs(self.data))
184
185
for name in self.headers:
186
params[name.lower()] = self.headers[name]
187
188
if "cookie" in params:
189
for part in params["cookie"].split(';'):
190
part = part.strip()
191
if '=' in part:
192
name, value = part.split('=', 1)
193
params[name.strip()] = unquote_plus(value.strip())
194
195
for key in params:
196
if params[key] and isinstance(params[key], (tuple, list)):
197
params[key] = params[key][-1]
198
199
self.url, self.params = path, params
200
201
if self.url == "/csrf":
202
if self.params.get("csrf_token") == _csrf_token:
203
self.url = "/"
204
else:
205
self.send_response(OK)
206
self.send_header("Content-type", "text/html; charset=%s" % UNICODE_ENCODING)
207
self.end_headers()
208
209
form = (
210
"<html><body>"
211
"CSRF protection check<br>"
212
"<form action='/csrf' method='POST'>"
213
"<input type='hidden' name='csrf_token' value='%s'>"
214
"id: <input type='text' name='id'>"
215
"<input type='submit' value='Submit'>"
216
"</form>"
217
"</body></html>"
218
) % _csrf_token
219
220
self.wfile.write(form.encode(UNICODE_ENCODING))
221
return
222
223
if self.url == '/':
224
if not any(_ in self.params for _ in ("id", "query")):
225
self.send_response(OK)
226
self.send_header("Content-type", "text/html; charset=%s" % UNICODE_ENCODING)
227
self.send_header("Connection", "close")
228
self.end_headers()
229
self.wfile.write(b"<!DOCTYPE html><html><head><title>vulnserver</title></head><body><h3>GET:</h3><a href='/?id=1'>link</a><hr><h3>POST:</h3><form method='post'>ID: <input type='text' name='id'><input type='submit' value='Submit'></form></body></html>")
230
else:
231
code, output = OK, "<body><html>"
232
233
try:
234
if self.params.get("echo", ""):
235
output += "%s<br>" % self.params["echo"]
236
237
if self.params.get("reflect", ""):
238
output += "%s<br>" % self.params.get("id")
239
240
with _lock:
241
if "query" in self.params:
242
_cursor.execute(self.params["query"])
243
elif "id" in self.params:
244
if "base64" in self.params:
245
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % base64.b64decode("%s===" % self.params["id"], altchars=self.params.get("altchars")).decode())
246
else:
247
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % self.params["id"])
248
results = _cursor.fetchall()
249
250
output += "<b>SQL results:</b><br>\n"
251
252
if self.params.get("code", ""):
253
if not results:
254
code = INTERNAL_SERVER_ERROR
255
else:
256
if results:
257
output += "<table border=\"1\">\n"
258
259
for row in results:
260
output += "<tr>"
261
for value in row:
262
output += "<td>%s</td>" % value
263
output += "</tr>\n"
264
265
output += "</table>\n"
266
else:
267
output += "no results found"
268
269
if not results:
270
output = "<title>No results</title>" + output
271
else:
272
output = "<title>Results</title>" + output
273
274
output += "</body></html>"
275
except Exception as ex:
276
code = INTERNAL_SERVER_ERROR
277
output = "%s: %s" % (re.search(r"'([^']+)'", str(type(ex))).group(1), ex)
278
279
self.send_response(code)
280
281
self.send_header("Content-type", "text/html")
282
self.send_header("Connection", "close")
283
284
if self.raw_requestline.startswith(b"HEAD"):
285
self.send_header("Content-Length", str(len(output)))
286
self.end_headers()
287
else:
288
self.end_headers()
289
self.wfile.write(output if isinstance(output, bytes) else output.encode(UNICODE_ENCODING))
290
else:
291
self.send_response(NOT_FOUND)
292
self.send_header("Connection", "close")
293
self.end_headers()
294
295
def do_GET(self):
296
self.do_REQUEST()
297
298
def do_PUT(self):
299
self.do_POST()
300
301
def do_HEAD(self):
302
self.do_REQUEST()
303
304
def do_POST(self):
305
length = int(self.headers.get("Content-length", 0))
306
if length:
307
data = self.rfile.read(length)
308
data = unquote_plus(data.decode(UNICODE_ENCODING, "ignore"))
309
self.data = data
310
elif self.headers.get("Transfer-encoding") == "chunked":
311
data, line = b"", b""
312
count = 0
313
314
while True:
315
line += self.rfile.read(1)
316
if line.endswith(b'\n'):
317
if count % 2 == 1:
318
current = line.rstrip(b"\r\n")
319
if not current:
320
break
321
else:
322
data += current
323
324
count += 1
325
line = b""
326
327
self.data = data.decode(UNICODE_ENCODING, "ignore")
328
329
self.do_REQUEST()
330
331
def log_message(self, format, *args):
332
return
333
334
def run(address=LISTEN_ADDRESS, port=LISTEN_PORT):
335
global _alive
336
global _server
337
try:
338
_alive = True
339
_server = ThreadingServer((address, port), ReqHandler)
340
print("[i] running HTTP server at 'http://%s:%d'" % (address, port))
341
_server.serve_forever()
342
except KeyboardInterrupt:
343
_server.socket.close()
344
raise
345
finally:
346
_alive = False
347
348
if __name__ == "__main__":
349
try:
350
init()
351
run(sys.argv[1] if len(sys.argv) > 1 else LISTEN_ADDRESS, int(sys.argv[2] if len(sys.argv) > 2 else LISTEN_PORT))
352
except KeyboardInterrupt:
353
print("\r[x] Ctrl-C received")
354
355