-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathexample_practical.py
More file actions
139 lines (110 loc) · 3.69 KB
/
Copy pathexample_practical.py
File metadata and controls
139 lines (110 loc) · 3.69 KB
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
################################################
# #
# WARNING: Intentionally vulnerable code below #
# #
################################################
import commands
import hashlib
import os
import pickle
import pipes
import posix
import taint
import urllib
import urlparse
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
SECRET_KEY = 'l33t_passwd'
class HtmlMerit(Merit):
propagation = Merit.FullPropagation
class SecretMerit(Merit):
propagation = Merit.NonePropagation
class ShellMerit(Merit):
propagation = Merit.FullPropagation
class PickleMerit(Merit):
propagation = Merit.NonePropagation
class Handler(BaseHTTPRequestHandler):
def get_parameters(self):
return urlparse.parse_qs("".join(self.path.split('?')[1:]))
def send_response(self, data):
self.wfile.write(data)
def do_GET(self):
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
if not '?' in self.path:
self.send_response("Hello!")
self.wfile.close()
return
params = self.get_parameters()
path = self.path.split('?')[0]
# Example 1 -- Secret Leak
# By leaking the hash of the secret the attack can bruteforce the SECRET_KEY
# offline.
#
# Exercise attack request:
# /hashleak?
if path == '/hashleak':
self.send_response("your instance ID (= hash of your key) is: %s" % \
(hashlib.md5(SECRET_KEY).hexdigest()))
# Example 2 -- Unsafe Pickle
# It is not safe to unpickle untrusted strings, as classes can define
# routines that declare how they should be unpickled. This can lead to
# remote code execution vulnerablities.
#
# Exercise attack request:
# /pickle?value=
# "cposix\nsystem\np0\n(S'id>/tmp/test'\np1\ntp2\nRp3\n."
elif path == '/pickle':
user_value = urllib.unquote(params['value'][0]) # TODO fix
data = pickle.loads(user_value)
self.send_response("unpickled data: %r" % (data))
# Example 3 -- Command Injection
# It is not safe to contatenate strings for use in a shell command without
# sanitizing the user-supplied strings first.
#
# Exercise attack request:
# google.org;echo foo>/tmp/foo'
elif path == '/cmd':
data = commands.getoutput('whois %s' % params['value'][0])
self.send_response("whois data: %r" % (data))
# Example 4 -- Reflected XSS
# It is safe to reflect user-supplied strings in a HTTP response without
# sanitizing them first.
#
# Exercise attack request:
# /reflect?value= <img src=x onerror=alert(0);>
elif path == '/reflect':
data = params['value'][0]
data = data.upper()
self.send_response("reflected data: %s" % (data))
# Example 5 -- Stored XSS
# It is safe to reflect user-supplied strings in a HTTP response without
# sanitizing them first.
#
# Exercise attack request:
# TODO
elif path == '/store':
fh = open('/tmp/db','w')
fh.write(params['value'][0])
fh.close()
self.send_response("stored")
elif path == '/get':
fh = open('/tmp/db','r')
data = fh.read()
data = data.taint()
fh.close()
self.send_response("stored: %s" % (data))
# Example 6 -- Arbritary File Read
# TODO
# Example 7 -- Arbritary File Write
# TODO
self.wfile.close()
taint.enable('example_practical.json')
SECRET_KEY = SECRET_KEY.taint() # Manually taint this string
try:
server = HTTPServer(('localhost', 8888), Handler)
print('Started http server')
server.serve_forever()
except KeyboardInterrupt:
print('^C received, shutting down server')
server.socket.close()