Nmap Development mailing list archives
Re: Bug in SMB when multiple scripts are connecting to same host
From: Chris Woodbury <woodbusy () gmail com>
Date: Mon, 28 Feb 2011 13:44:34 -0600
Ron- Thanks for the response. Don't worry about the delay - 'better late than never' is my motto ;). I hadn't thought of the lockout implications of separate account lists; so, yes, you certainly wouldn't want to go that route. With that in mind, I put some more thought into it, and it seems to me that mutexes are the best approach. I made a patch that adds mutexes to start_session_basic() and start_session_extended(). My thinking was that the first script to get there would be responsible for finding the right account (or exhausting the possibilities), and that, once that was done, the other scripts could follow along and already have that account waiting for their get_account() call. I had to put in an "unlock" before each of the short-circuit returns; so, it's not exactly pretty, but it gets the job done. I also tested the change empirically using my testsmb script and rigorlessly confirmed that the problem is fixed. Let me know what you think -chris On Sun, Feb 27, 2011 at 7:13 PM, Ron <ron () skullsecurity net> wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi Chris, Sorry for my delayed response. I'm... well, at this point 20 days behind on reading nmap-dev, but I'm doing my best to keep up! I'm going to be that this vulnerability was introduced a few months ago, when I decided to let SMB scripts run in parallel with each other - before that, I had a mutex in the start/stop functions so no two SMB scripts could ever go in parallel. I figured out how to run concurrent scripts in the protocol, though, and fixed it. Apparently, I introduced this when I did that. I wish I could think of an easy way to fix that at the moment. Having every script start from the first account is bad - that road leads to lockouts - and mutexes (mutices?) could get messy since it's across a send/recv. It *might* be possible to wrap a mutex around all the auth code (open at negotiate, release at successful login or failure). Neither solution is very pretty, though. Anybody have any other ideas? I'm going to mark this as unread and go back to it later. (Do we have a proper bugtracker yet? ;) ) Ron On Mon, 7 Feb 2011 19:28:18 -0600 Chris Woodbury <chris3e3 () gmail com> wrote:I've found what I think is a bug in the SMB library, which gets triggered in the following situation: 1. Multiple scripts/script instances are running concurrently against the same host via SMB and are in smb.start_session_basic()/start_session_extended() at the same time. 2. The first entry in the SMB accounts list (nmap.registry[ IP ][ "smbaccounts" ] cannot log in. 3. There are no username overrides. In this situation, script #1 gets the first account off the list and tries to authenticate (unsuccessfully, as it will turn out). The network I/O causes a switch to script #2, which also gets the first account off the list and tries to authenticate (unsuccessfully as well, of course). The scripts each get going again and both make it down to the point where it is recognized that authentication has failed (beginning on line 1216 or 1384) and smbauth.next_account() and smbauth.get_account() are called to get the next account to try to authenticate with. Here is the problem. Both scripts have realized that their authentication attempts failed and call next_account(), but next_account() and get_account() work on a list of accounts that is shared for the host. Thus, script #1 gets the second account on the list, but script #2 gets the *third* account on the list. I have attached a script that should demonstrate this. If you make another copy (e.g. testsmb2.nse) and run them both against a host that allows anonymous logins (e.g. nmap -d2 -p 445 --script testsmb,testsmb2 <host>), you should see one succeed and ther other fail with "No accounts left to try." You may need to run in a couple times to get this to happen. Off the top of my head, it seems that this might be solved by making the list of accounts (or the index) tied to the smbstate (and thus specific to each script instance), or by using a mutex. I won't pretend to understand SMB and the smb libraries like Ron does, so I haven't tried to patch this myself. Please let me know if I've missed or misunderstood anything, or if anyone has questions. -chris Illustrative scenario: Four scripts are attempting to connect to a share that is accessible with the anonymous login (i.e. null session). No SMB credentials are given or discovered. The scripts aren't doing anything fancy and are using the high-level SMB functions (e.g. start_session_ex() ). 1. Script #1 starts first (the others are "started" but don't run until Script #1 makes a network I/O call). 2. Script #1 calls smb.start_session_ex(), which calls smb.start(), which calls smbauth.init_account(), which populates the account list for the host with { guest, anonymous }. 3. Script #1's smb.start_session_ex() eventually calls smb.start_session(), which in this example calls smb.start_session_extended(). This calls smbauth.get_account(), retrieving the guest account, which is then used in an authentication attempt. 4. Script #1's authentication attempt is network I/O, so execution switches to Script #2, which gets to the same point as Script #1, also attempting to log in with the guest account. 5. The same for Script #3. 6. Execution switches back to Script #1, which sees that its login attempt failed, so it calls smbauth.next_account() [smb.lua line 1386], which moves to the anonymous login. Script #1 then calls smb.get_account() to get the new account to try, and loops back around to make an authentication attempt with it. 7. Execution switches to Script #2, which does the same thing, except that its call to next_account() exhausts the account list. Its call to smb.get_account() gets an error saying there are "No accounts left to try", which causes the original call to smb.start_session_ex() to fail. 8. Execution switches to Script #1, which just authenticated with the anonymous login, which was successful. Its call to smb.start_session_ex() returns successfully. 9. Execution switches to Script #3, which does the same thing as Script #2 in step 7. Its call to smb.start_session_ex() also fails with "No accounts left to try". 10. Execution switches to Script #4, which has been waiting patiently. Like the others, it starts with a call to smb.start_session_ex(), but when it gets to the first call to smbauth.get_account() [line 1257], there are no more accounts, and Script #4 also fails with "No accounts left to try". Thus, out of four scripts, only one of them was actually able to get and use the valid credentials that were in the account list.-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAk1q9rcACgkQ2t2zxlt4g/QT7QCfd24auwMBYhVylPleeHeTpP8Y Z5MAnjFhfS5ZyWK0hZ0oTlSvGvjW79SG =cF/r -----END PGP SIGNATURE----- _______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://seclists.org/nmap-dev/
Attachment:
smb_auth_mutex.patch
Description:
_______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://seclists.org/nmap-dev/
Current thread:
- Bug in SMB when multiple scripts are connecting to same host Chris Woodbury (Feb 07)
- Re: Bug in SMB when multiple scripts are connecting to same host Ron (Feb 27)
- Re: Bug in SMB when multiple scripts are connecting to same host Chris Woodbury (Feb 28)
- Re: Bug in SMB when multiple scripts are connecting to same host David Fifield (Mar 14)
- Re: Bug in SMB when multiple scripts are connecting to same host Ron (Mar 15)
- Re: Bug in SMB when multiple scripts are connecting to same host Chris Woodbury (Mar 31)
- Re: Bug in SMB when multiple scripts are connecting to same host Ron (Mar 31)
- Re: Bug in SMB when multiple scripts are connecting to same host Chris Woodbury (Feb 28)
- Re: Bug in SMB when multiple scripts are connecting to same host Ron (Feb 27)