Wednesday, 12 September 2012

Is Your SMB Bruteforcer Lying To You?

A few weeks back, on a job, I had enumerated a list of domain users from a linux device attached to a windows domain due to anonymous access. Not knowing the lockout policy I gave a quick attempt to enumerate which accounts had a weak password, 'Password1', using Metasploit's smb_login module.

I got one positive result back, a normal domain user. But unknown to me at the time, in that sea of red error responses, I had domain admin accounts responding to valid credentials. However it was not a login success, but rather STATUS_PASSWORD_MUST_CHANGE which wasn't highlighted by Metasploit. Domain Admins can RDP in and update their password so this was an instant win - when I finally spotted it by accident sometime later...

I tried again with Hydra which picked up a second account, but not a third account responding with a different error message (STATUS_ACCOUNT_LOCKED_OUT).

When I got back I set about updating the smb_login module to catch these valid credentials and looked at the different responses. It's easy to lose track of these valid creds when you are enumerating thousands of other accounts reporting STATUS_LOGIN_FAILURE:

 
Looking at the Microsft SMB Error Codes and NTSTATUS values, the NMAP smb-brute script, and Medusa source code I found the following status codes probably indicate correct credentials:
 
STATUS_SUCCESS
STATUS_PASSWORD_MUST_CHANGE
STATUS_PASSWORD_EXPIRED
STATUS_ACCOUNT_DISABLED
STATUS_ACCOUNT_LOCKED_OUT (Correction: LOCKED_OUT responds with invalid creds as well)
STATUS_ACCOUNT_EXPIRED
STATUS_ACCOUNT_RESTRICTION
STATUS_INVALID_LOGON_HOURS
STATUS_LOGON_TYPE_NOT_GRANTED
STATUS_INVALID_WORKSTATION
AUTHENTICATION_FIREWALL_PROTECTION
 
 
I was able to test all of these, with the exception of STATUS_INVALID_WORKSTATION, by modifying Active Directory user accounts, GPO, or Local Security Policies. AUTHENTICATION_FIREWALL_PROTECTION is named by Medusa but does not appear to map to a known SMB Error Code but appears to map to 0x00000064 and occurs when the machine is protected by some kind of authentication firewall.
 
STATUS_LOGIN_TYPE_NOT_GRANTED - GPO/Security Settings/Local Policies/Deny access to this computer from the network
STATUS_ACCOUNT_RESTRICTION - Local Security Policy/Accounts: Limit local account use of blank passwords to computer.
 
Due to the disparities I had seen in my toolkit, I thought it best to see which provide the most accurate and useful feedback so I went about testing and comparing the following:

Metasploit 4.5.0 smb_login module
Hydra 7.3
Ncrack 0.4ALPHA
Medusa v2.1.1
NMAP 6.01 smb-brute plugin

The following table shows the results of each tool against the expected 'valid' credential status codes:

STATUS Metasploit Hydra Ncrack Medusa NMAP
STATUS_PASSWORD_MUST_CHANGE x y x y *
STATUS_PASSWORD_EXPIRED x x x y *
STATUS_ACCOUNT_DISABLED x x x y *
STATUS_ACCOUNT_EXPIRED x y x y *
STATUS_ACCOUNT_RESTRICTION x y x y *
STATUS_INVALID_LOGON_HOURS x x x y *
STATUS_LOGON_TYPE_NOT_GRANTED x y x y *

Hydra identified some status codes but not others. It may be a design decision to not report certain creds such as ACCOUNT_DISABLED, as they are unlikely to be useful when testing. However PASSWORD_EXPIRED can often be fixed with a console or RDP login, ACCOUNT_LOCKED_OUT may reset after a certain period (default 30 mins), and INVALID_LOGIN_HOURS just means you just need to try again later.

The NMAP smb-brute failed to identify a valid login against even my positive test case but did identify all accounts as 'locked'. Perhaps I was using it incorrectly and happy to be corrected, see later for output. It also automatically performed attempts with a blank password, locking out accounts earlier than expected and I would avoid it for now.

Ncrack identified a correct login but failed to identify any of the other status codes. I believe it is no longer under development in favour of Nmap scripts.

Medusa performed admirably identifying all cases and marking them as successful.

Metasploit presents the status codes but does not flag the credentials as valid. It also performs unpredictably depending on the SMBDomain setting:

Firstly 'unset SMBDomain' will likely cause all accounts to fail.

Against the DC with SMBDomain set to a random value, 'SomeIncorrectDomain1234', all status codes are correctly returned and valid domain accounts are marked correctly. The same is true for '' and '.'.

Against a Domain Workstation with SMBDomain set to a random value, all status codes return STATUS_LOGON_FAILURE except for valid credentials which will login. Set to  '.' will also return STATUS_LOGON_FAILURE however a blank SMBDomain. '', will return the detailed error codes.

With the correct SMBDomain things work as expected (but you may not always know this).

For now I would recommend Medusa for brute forcing SMB. I have a pull request to submit an updated Metasploit smb_login module, but this requires more testing as I have just been using it against Windows 2k12 DC and a Windows XP SP3 so some validation especially against Linux SAMBA installations is necessary, and possibly on LM systems?

My changes to the module pick out valid credentials in blue, these should be much more visible when placed against a lot of red STATUS_LOGON_FAILURE. They are also all reported to the database but as inactive credentials so need to be accessed with the command 'creds all'.



Tool output (for anyone that is interested):

Medusa

root@bt:~# medusa -h 192.168.1.38 -p "" -C /root/jobs/users_medusa.txt -M smbnt -O ~medusa_output
Medusa v2.1.1 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks <
jmk@foofus.net>
ACCOUNT CHECK: [smbnt] Host: 192.168.1.38 (1 of 2, 0 complete) User: test1 (1 of 8, 0 complete) Password: Password1 (1 of 2 complete)
ACCOUNT FOUND: [smbnt] Host: 192.168.1.38 User: test1 Password: Password1 [SUCCESS (0x000224:STATUS_PASSWORD_MUST_CHANGE)]
ACCOUNT CHECK: [smbnt] Host: 192.168.1.38 (1 of 2, 0 complete) User: test2 (2 of 8, 1 complete) Password: Password1 (1 of 2 complete)
ACCOUNT FOUND: [smbnt] Host: 192.168.1.38 User: test2 Password: Password1 [SUCCESS (0x000071:STATUS_PASSWORD_EXPIRED)]
ACCOUNT CHECK: [smbnt] Host: 192.168.1.38 (1 of 2, 0 complete) User: test3 (3 of 8, 2 complete) Password: Password1 (1 of 2 complete)
ACCOUNT FOUND: [smbnt] Host: 192.168.1.38 User: test3 Password: Password1 [SUCCESS (0x000072:STATUS_ACCOUNT_DISABLED)]
ACCOUNT CHECK: [smbnt] Host: 192.168.1.38 (1 of 2, 0 complete) User: test4 (4 of 8, 3 complete) Password: Password1 (1 of 2 complete)
ACCOUNT FOUND: [smbnt] Host: 192.168.1.38 User: test4 Password: Password1 [SUCCESS (0x000193:STATUS_ACCOUNT_EXPIRED)]
ACCOUNT CHECK: [smbnt] Host: 192.168.1.38 (1 of 2, 0 complete) User: test5 (5 of 8, 4 complete) Password: Password1 (1 of 2 complete)
ACCOUNT FOUND: [smbnt] Host: 192.168.1.38 User: test5 Password: Password1 [SUCCESS (0x00006F:STATUS_INVALID_LOGON_HOURS)]
ACCOUNT CHECK: [smbnt] Host: 192.168.1.38 (1 of 2, 0 complete) User: test6 (6 of 8, 5 complete) Password: Password1 (1 of 2 complete)
ACCOUNT FOUND: [smbnt] Host: 192.168.1.38 User: test6 Password: Password1 [SUCCESS]
ACCOUNT CHECK: [smbnt] Host: 192.168.1.38 (1 of 2, 0 complete) User: test7 (7 of 8, 6 complete) Password: Password1 (1 of 2 complete)
ACCOUNT FOUND: [smbnt] Host: 192.168.1.38 User: test7 Password: Password1 [ERROR (0x000234:STATUS_ACCOUNT_LOCKED_OUT)]
ACCOUNT CHECK: [smbnt] Host: 192.168.1.38 (1 of 2, 0 complete) User: test9 (8 of 8, 7 complete) Password: Password1 (1 of 2 complete)
ACCOUNT FOUND: [smbnt] Host: 192.168.1.38 User: test9 Password: Password1 [SUCCESS (0x00015B:STATUS_LOGON_TYPE_NOT_GRANTED)]
ACCOUNT CHECK: [smbnt] Host: 192.168.1.28 (2 of 2, 1 complete) User: test8 (1 of 1, 0 complete) Password:  (1 of 2 complete)
ACCOUNT FOUND: [smbnt] Host: 192.168.1.28 User: test8 Password:  [SUCCESS (0x00006E:STATUS_ACCOUNT_RESTRICTION)]


Ncrack

root@bt:~/nmap# ncrack -U /root/jobs/users_nopass.txt --pass Password1 smb://192.168.1.38:445
Starting Ncrack 0.4ALPHA ( http://ncrack.org ) at 2012-09-12 21:24 BST
Discovered credentials for smb on 192.168.1.38 445/tcp:
192.168.1.38 445/tcp smb: 'test6' 'Password1'

Ncrack done: 1 service scanned in 3.00 seconds.
Ncrack finished.root@bt:~/nmap# ncrack -U /root/jobs/users_nopass.txt --pass Password1 smb://192.168.1.28:445
Starting Ncrack 0.4ALPHA ( http://ncrack.org ) at 2012-09-12 21:24 BST
Discovered credentials for smb on 192.168.1.28 445/tcp:
192.168.1.28 445/tcp smb: 'test6' 'Password1'

Ncrack done: 1 service scanned in 3.01 seconds.
Ncrack finished.

Hydra

root@bt:~/jobs# hydra -C users_colon.txt 192.168.1.38 smb
Hydra v7.3 (c)2012 by van Hauser/THC & David Maciejak - for legal purposes only

Hydra (http://www.thc.org/thc-hydra) starting at 2012-09-12 21:24:39
[INFO] Reduced number of tasks to 1 (smb does not like parallel connections)
[DATA] 1 task, 1 server, 9 login tries, ~9 tries per task
[DATA] attacking service smb on port 445
[445][smb] host: 192.168.1.38   login: test1   password: Password1
[445][smb] host: 192.168.1.38   login: test4   password: Password1
[445][smb] host: 192.168.1.38   login: test6   password: Password1
[445][smb] host: 192.168.1.38   login: test8   password:
[445][smb] host: 192.168.1.38   login: test9   password: Password1
[STATUS] attack finished for 192.168.1.38 (waiting for children to finish)
1 of 1 target successfuly completed, 5 valid passwords found
Hydra (
http://www.thc.org/thc-hydra) finished at 2012-09-12 21:24:39root@bt:~/jobs# hydra -C users_colon.txt 192.168.1.28 smb
Hydra v7.3 (c)2012 by van Hauser/THC & David Maciejak - for legal purposes only

Hydra (http://www.thc.org/thc-hydra) starting at 2012-09-12 21:24:53
[INFO] Reduced number of tasks to 1 (smb does not like parallel connections)
[DATA] 1 task, 1 server, 9 login tries, ~9 tries per task
[DATA] attacking service smb on port 445
[445][smb] host: 192.168.1.28   login: test1   password: Password1
[445][smb] host: 192.168.1.28   login: test4   password: Password1
[445][smb] host: 192.168.1.28   login: test6   password: Password1
[445][smb] host: 192.168.1.28   login: test8   password:
[445][smb] host: 192.168.1.28   login: test9   password: Password1
[STATUS] attack finished for 192.168.1.28 (waiting for children to finish)
1 of 1 target successfuly completed, 5 valid passwords found
Hydra (
http://www.thc.org/thc-hydra) finished at 2012-09-12 21:24:53

Metasploit smb_login

  Name              Current Setting       Required  Description
   ----              ---------------       --------  -----------
   BLANK_PASSWORDS   false                 no        Try blank passwords for all users
   BRUTEFORCE_SPEED  5                     yes       How fast to bruteforce, from 0 to 5
   PASS_FILE                               no        File containing passwords, one per line
   PRESERVE_DOMAINS  true                  no        Respect a username that contains a domain name.
   RECORD_GUEST      false                 no        Record guest-privileged random logins to the database
   RHOSTS            192.168.1.38          yes       The target address range or CIDR identifier
   RPORT             445                   yes       Set the SMB service port
   SMBDomain         WORKGROUP             no        SMB Domain
   SMBPass                                 no        SMB Password
   SMBUser                                 no        SMB Username
   STOP_ON_SUCCESS   false                 yes       Stop guessing when a credential works for a host
   THREADS           1                     yes       The number of concurrent threads
   USERPASS_FILE     /root/jobs/users.txt  no        File containing users and passwords separated by space, one pair per line
   USER_AS_PASS      false                 no        Try the username as the password for all users
   USER_FILE                               no        File containing usernames, one per line
   VERBOSE           true                  yes       Whether to print output for all attempts


[*] 192.168.1.38:445 SMB - Starting SMB login bruteforce
[-] 192.168.1.38 - This system allows guest sessions with any credentials, these instances will not be reported.
[-] 192.168.1.38:445 - FAILED LOGIN (Windows Server 2012 Release Candidate Datacenter 8400) test1 : Password1 (STATUS_PASSWORD_MUST_CHANGE)
[-] 192.168.1.38:445 - FAILED LOGIN (Windows Server 2012 Release Candidate Datacenter 8400) test2 : Password1 (STATUS_PASSWORD_EXPIRED)
[-] 192.168.1.38:445 - FAILED LOGIN (Windows Server 2012 Release Candidate Datacenter 8400) test3 : Password1 (STATUS_ACCOUNT_DISABLED)
[-] 192.168.1.38:445 - FAILED LOGIN (Windows Server 2012 Release Candidate Datacenter 8400) test4 : Password1 (STATUS_ACCOUNT_EXPIRED)
[-] 192.168.1.38:445 - FAILED LOGIN (Windows Server 2012 Release Candidate Datacenter 8400) test5 : Password1 (STATUS_INVALID_LOGON_HOURS)
[*] Auth-User: "test6"
[+] 192.168.1.38:445 - SUCCESSFUL LOGIN (Windows Server 2012 Release Candidate Datacenter 8400) 'test6' : 'Password1'
[-] 192.168.1.38:445 - FAILED LOGIN (Windows Server 2012 Release Candidate Datacenter 8400) test7 : Password1 (STATUS_ACCOUNT_LOCKED_OUT)
[*] Auth-User: "test8"
[+] 192.168.1.38:445 - SUCCESSFUL LOGIN (Windows Server 2012 Release Candidate Datacenter 8400) 'test8' : ''
[-] 192.168.1.38:445 - FAILED LOGIN (Windows Server 2012 Release Candidate Datacenter 8400) test9 : Password1 (STATUS_LOGON_TYPE_NOT_GRANTED)
[-] 192.168.1.38:445 SMB - [10/10] - FAILED LOGIN (Windows Server 2012 Release Candidate Datacenter 8400) test9 :  (STATUS_LOGON_FAILURE)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed


Nmap smb-brute

root@bt:~# nmap -p445 --script=smb-brute --script-args smblockout=true,userdb=/root/jobs/users_nopass.txt,passdb=/root/jobs/passes.txt 192.168.1.38
Starting Nmap 6.01 ( http://nmap.org ) at 2012-09-12 22:31 BST
Nmap scan report for WIN-0T8EP9QMRVD.HMS (192.168.1.38)
Host is up (0.00068s latency).
PORT    STATE SERVICE
445/tcp open  microsoft-ds
MAC Address: 00:0C:29:49:2B:21 (VMware)

Host script results:
| smb-brute:
|   No accounts found
|_  Locked accounts found: test1, test2, test3, test4, test5, test6, test7

Nmap done: 1 IP address (1 host up) scanned in 0.43 seconds

4 comments:

  1. Really good article and feedback/experience on tools.
    I'm really suprised of what i'm reading but it's clear that the tests are there !
    Would you mind to do later or to give me recommendation (link/website/videos/series/msf plugins) to the first part i.e 'pre' attack: "A few weeks back, on a job, I had enumerated a list of domain users from a linux device attached to a windows domain due to anonymous access. " I mean how did you do that, context, commands, remediations, it'll be very good training for practitioners not really experienced (like me) on Windows platform !
    Thanks for your great work !

    ReplyDelete
    Replies
    1. Google Books has a preview chapter from Network Security Assessment which is a good starting point:

      http://books.google.co.uk/books?id=zKhCEYRGFuYC&lpg=PA267&ots=7bWyPRa9X5&dq=RID%20Cycling%20domain&pg=PA285#v=onepage&q=RID%20Cycling%20domain&f=false

      Delete
  2. I just finished a pentest where I had similar results from Metasploit and ended up using a variety of tools to sort my problem. I still found all tools lacking as I was searching across numerous subnets with almost 3000 machines on the network. What I thought was going to be an easy task ended up requiring more manual intervention than expected. I appreciate the digging you did into this problem and feel relieved I'm not the only one who struggled to get accurate results.

    ReplyDelete
  3. thx for the tests, in hydra ACCOUNT_DISABLED and PASSWORD_EXPIRED
    are considered as a failed login (-v option can gives you more output). I added INVALID_LOGIN_HOURS code for next hydra version which will be considered as a success login.

    ReplyDelete