On a recent engagement, I was struggling to escalate my low level privileges to something higher. To their credit, the organization was doing a lot of the right things in terms of security best practices. For example, LLMNR and NBT-NS poisoning was not effective… so relaying NetNTLMv2 hashes was not a viable options. Right out the gate, this rendered some of “goto” tools (like Responder, smbrelayx, web_delivery module, etc) ineffective. I was able to eventually relay a couple of hashes; however, I came to realize that no users were local administrators on their workstations and all of the workstations were incredibly locked down. Additionally, ARP spoofing was also mostly ineffective and I suspect they had controls in place to prevent ARP cache poisoning.
That said, I was ultimately able to crack the NTLMv2 challenge/response hash of an end user who had a very weak password (“Summer2017”). This was my first foothold within the environment. However, given how locked down the environment was, I could not do much with my low level access. I ultimately resorted to enumerating and documenting all areas of the environment to which this account had some type of access. This took a while. I sprayed that user’s domain credentials across every known subnet and ultimately came to the conclusion I wasn’t going to get far by trying to target workstations…. I moved on to SMB enumeration of servers.
Every time I came across a server that had network shares, I would quickly peruse the list of files/folders and see if anything stood out as suspicious or helpful. This process eventually led me to a server with a single share. See below:
This user obviously had access and so I quickly browsed the list of files in this share and found a file named ********.ini (unfortunately, the share name and the file name would give away the name of the software vendor). This file contained a database connection string – along with a plaintext username and password.
Armed with this information, it was apparent that this server was mostly likely running MS SQL. Additionally, even with these credentials, there was still no guarantee that 1) the credentials were valid, and 2) (if they were) that the database access would be helpful with escalation of our privileges. Either way, I proceeded to nmap this server to get more information.
The server appeared to be an application server running MS SQL. The next step was to check to see if the discovered credentials were, in fact, valid:
With the confirmation that our credentials are valid, I surmised that I had two options: 1) use our credentials to dump tables in the database and look for sensitive information and/or 2) try to use our credentials to obtain a reverse shell on the box. Given the desire for escalated privileges, I opted to immediately try to get a shell on the box – which worked.
As seen above, we have SYSTEM privileges on this particular server….but I really need/want domain administrator privileges so that I can login to other critical servers and move freely throughout the environment. A quick look at the processes on this boxes, shows that a domain administrator is logged into this box and has mmc.exe open:
Upon migrating to this process, we are effectively able to issue commands against Active Directory as a domain administrator. At this point, it made sense to drop into a cmd shell and create a new account called “sys_admin” and immediately move this account into the “domain admins” group. Granted, there are more “stealthy” ways to take over the domain; however, part of the objective with this engagement was to determine how quickly internal teams were able to detect something like this. (they did not)
From here, with our new privileged domain account, we were able to quickly login to a domain controller and dump Active Directory password hashes, passwords from memory on other boxes, and exfiltrate sensitive data.
Given what I know about the organization and software vendor, I suspect the software vendor deploys this solution the same way to all of their clients. While the password in the database connection string is probably going to be different, documentation indicates the username is always the same. Additionally, it would seem that xp_cmdshell is enabled, which is what allowed me to get my meterpreter shell. While I don’t know a lot about the software, I would guess that this could probably be disabled.