I recently performed an assumed breach test against what I would consider an Apex Defender organization. The security team is smart, well-funded, extremely capable, and resourceful. The team has both hardened systems and instrumented great logging and monitoring. Although this organization has seemingly done everything right, a minor information disclosure ultimately led to the compromise of the entire organization.
Follow along to see how these issues aligned, allowing me to thread multiple needs and compromise the environment.
Full disclosure – Evading the blue team was not in scope for this assessment. Much of what I was doing was logged and observed by the defenders. The issues I’ll outline here have been found in many organizations we have tested. Against a lesser-prepared blue team, or an organization with significant gaps in logging and monitoring, these issues would undoubtedly go unnoticed until it was too late.
I will say it to anyone who will listen – information disclosure on overly permissive file-shares leads to organizational compromise in the majority of assessments I do. Whether it’s a share and admin created to transfer some files and meant to remove afterwards, shares created automatically when software was installed, or a share with excessive permissions granted, data in file-shares almost always leads to an organizational compromise. I want to be clear this does not mean domain admin. It can just as easily result in access to source code, customer PII/PHI, or whatever the keys to the kingdom may be. In this particular case, it started with a share containing a connection string for a MS SQL database on the same server hosting the share.
The underlying NTFS folder for the file share in question granted RWX permissions to the BUILTIN\Users group. This group contained the NT AUTHORITY\Authenticated Users group. Consequently, all domain users had access to this folder. As a result, any user in the domain could get access to a single set of SQL credentials. This information disclosure would have resulted in the exposure of a limited amount of client PII in a couple of SQL databases. Not ideal, but certainly not a severe issue.
One needled threaded…
Next, I used PowerUpSQL’s Get-SQLServerInfo cmdlet to enumerate some information about the database server found in the connection string. To my surprise, I found this account was granted SA (SQL Server Administrator) privileges. I now had the ability to execute operating system commands on the host running the SQL server. This is not ideal. However, if the SQL server is running using Network Service or LocalSystem privileges, it results in fairly limited access to the host. In this particular case, I found the SQL server was being operated using a domain service account. While the majority of SQL servers in the environment were configured to run as LocalSystem, this service account was granted local administrator access to all of the SQL servers including this particular server. Consequently, the disclosure of one username and password in a file resulted in the compromise of the majority, if not all, of the SQL servers in the client’s network. This in itself is enough to call it a win, as domain admin wasn’t necessary. All of the sensitive data stored in SQL servers within the environment could be accessed using these credentials.
Another needle threaded…
I was able to go a step further. The server in question, a Windows Server 2012 R2 host, did not have LSA protection enabled. Consequently, I was able to use procdump to the LSASS process memory and recover password hashes. An account used to backup domain-joined servers had recently logged into the system and the password hash was in memory. This account was a member of the Domain Admins group.
Game, set, match and the final needle threaded!
In the end, the disclosure of a credentials in a file-share resulted in the complete compromise of the client’s environment. There were a series of seemingly minor failures that added up to a total compromise. If any single failure in this chain had been resolved, my attack would have been dead in the water and unable to proceed. Let’s take a closer look at what failed and what the client could have done to prevent this outcome.
1. Excessive share permissions and information disclosure: I didn’t not get a good understanding of why these credentials were in the file on that share. Removing these credentials from the share, or removing the share would have prevented the information disclosure. Organzations should periodically review what shares are accessible using PowerView’s Find-DomainShare cmdlet.
2. Privilege management (part 1): The SQL credentials were granted SA access on the database server. Had this account not been granted SA access, the most I would have gained would have been a limited amount of customer PII in a database.
3. Privilege management (part 2): Network services should always be operated using the least privileges necessary to accomplish the task. I would normally expect to see a SQL server operating under LocalSystem or Network Service privileges. Instead, this elevated permission service account gave me local administrator access to all SQL servers.
4. Attack surface reduction: LSA protection was not enabled on this server. Consequently, I was able to use procdump (and Mimikatz) to extract password hashes from memory. LSA protection can be enabled by creating a new DWORD, RunAsPPL, under HKLM\SYSTEM\CurrentControlSet\Control\LSA, and set the value to 1.
5. Privilege management (part 3): The account used to backup the device was granted Domain Admin privileges. Once I extracted the password hash from LSASS memory, I was was able compromise the entire domain. Backup service accounts are often erroneously granted Domain Admin privileges.