miketeo / pysmb

pysmb is an experimental SMB/CIFS library written in Python. It implements the client-side SMB/CIFS protocol (SMB1 and SMB2) which allows your Python application to access and transfer files to/from SMB/CIFS shared folders like your Windows file sharing and Samba folders.
Other
341 stars 94 forks source link

SMB2 generating bad signatures #151

Closed theoharr closed 4 years ago

theoharr commented 4 years ago

I've been trying to use pysmb to connect to an SMB server which requires SMB2 signatures on each message. Reviewing wireshark traces, I could see every request was failing due to STATUS_ACCESS_DENIED

On the server (which uses Samba) ... I found logs that pointed to bad signatures:

[2020/02/18 13:37:24.472262,  0] ../libcli/smb/smb2_signing.c:179(smb2_signing_check_pdu)
  Bad SMB2 signature for message
[2020/02/18 13:37:24.472404,  0] ../lib/util/util.c:555(dump_data)
  [0000] 4C 74 8E 9E 67 79 A6 54   B9 C5 57 28 C2 D9 DE 1E   Lt..gy.T ..W(....
[2020/02/18 13:37:24.472457,  0] ../lib/util/util.c:555(dump_data)
  [0000] 29 0E D4 08 45 B9 02 F5   A6 93 BF 8C 3A F6 51 3E   )...E... ....:.Q>

Pretty new to all this, but I found a pretty good example of the signature key generation method here:

https://github.com/SecureAuthCorp/impacket/blob/master/impacket/ntlm.py#L686

I applied a change to pysmb, and its working now!

--- base.py 2020-02-19 16:25:49.468491855 -0700
+++ base_new.py 2020-02-19 16:25:43.731333790 -0700
@@ -9,6 +9,10 @@
 from nmb.base import NMBSession
 from .utils import convertFILETIMEtoEpoch
 from . import ntlm, securityblob
+from six import b
+import random
+import string
+from Cryptodome.Cipher import ARC4

 try:
     import hashlib
@@ -371,10 +375,17 @@
             self.log.info('Performing NTLMv1 authentication (on SMB2) with server challenge "%s"', binascii.hexlify(server_challenge))
             nt_challenge_response, lm_challenge_response, session_key = ntlm.generateChallengeResponseV1(self.password, server_challenge, True)

+        session_base_key = session_key
+        session_sign_key = b("".join([random.choice(string.digits+string.ascii_letters) for _ in range(16)]))
+        cipher = ARC4.new(session_key)
+        cipher_encrypt = cipher.encrypt
+        session_encrypted_key = cipher_encrypt(session_sign_key)
+        self.log.info("SMB keys = %s:%s:%s", session_encrypted_key.hex(), session_base_key.hex(), session_sign_key.hex())
+
         ntlm_data = ntlm.generateAuthenticateMessage(server_flags,
                                                      nt_challenge_response,
                                                      lm_challenge_response,
-                                                     session_key,
+                                                     session_encrypted_key,
                                                      self.username,
                                                      self.domain,
                                                      self.my_name)
@@ -397,7 +408,8 @@

         if self.is_signing_active:
             self.log.info("SMB signing activated. All SMB messages will be signed.")
-            self.signing_session_key = (session_key + b'\0'*16)[:16]
+            self.signing_session_key = session_sign_key
+            self.log.info("SMB signing key = %s", self.signing_session_key.hex())
             if self.capabilities & CAP_EXTENDED_SECURITY:
                 self.signing_challenge_response = None
             else:

Not sure if this is an SMB1 vs SMB2 issue? But it does seem like SMB2 signing is broken at the moment.

miketeo commented 4 years ago

Changes integrated in pysmb 1.2.3