🔥 TryHackMe「Linux PrivEsc」Task16〜18 詳細 WriteUp
〜 パスワードと秘密鍵は、人間が最後に残す“痕跡”である 〜

Linux PrivEsc
TryHackMe / WriteUp
■ はじめに
前回の Task11〜15 では、
- SUID 実行ファイルが「所有者の権限(例: root)」で動く仕組み
- その周辺にある PATH / 共有ライブラリ / Bash の仕様 を揺さぶることで
root まで落とし込むテクニック
を通じて、
「OS が“当たり前”だと思っている前提を壊すと、そのまま権限境界が崩れる」
という世界観を見てきました。
今回の Task16〜18 は、角度がガラッと変わります。
システムの穴より、**人間の痕跡(history・config・鍵管理)**のほうが危険
という、かなり現実的なテーマです。
- Task16:
historyに漏れたパスワード - Task17: Config ファイルに埋め込まれた認証情報
- Task18: world-readable な SSH 秘密鍵
それぞれについて、
- どうやって見つけるか(手順)
- OS / ミドルウェア的には何が起きているのか
- 実務だとどう防ぐか
という3段階で深掘りしていきます。
■ Task16:History Files
〜 “1回ミスって入力したパスワード” は永遠に残る 〜
● 何をしたか(手順)
問題文どおり、まずはユーザの history を一括で眺めます。
cat ~/.*history | less
これで、
~/.bash_history~/.mysql_history~/.psql_history- など、ドットで始まる history 系ファイルがまとめて表示されます。
その中に、次のような行が見つかります。
mysql -u root -pPASSWORD123
ポイントはここです。
-
-p PASSWORD123(間にスペースあり)なら「パスワード入力プロンプト」が出る -
-pPASSWORD123(スペースなし)だと「オプションの値」として扱われる
→ そのまま history に記録される
あとは、このパスワードで su するだけです。
su root
Password: PASSWORD123
whoami
# root
Exploit もコンパイルも不要。
**「history を見て、コピペで root」**という雑さです。
● 裏側で何が起きているか(技術的な話)
1. bash history の仕組み
bash は、対話セッション終了時に、実行したコマンドを ~/.bash_history に追加します。
- 記録されるのは「入力した文字列そのもの」
- どの引数が「パスワードなのか」は一切理解していない
- 「見られたら困るものかどうか」も当然考慮されない
つまり、CLI から見れば
mysql -u root -pPASSWORD123
は単なる「文字列」でしかなく、
-
mysql側も -
bash側も
「これは秘密情報だから特別扱いしよう」とはしない、ということです。
2. mysql クライアントの挙動
-p オプションは 2通りの使われ方ができます。
-
-pだけ → パスワードを非表示入力(プロンプトで) -
-p<password>→ その文字列をパスワードとして使う
後者を使うと、mysql のプロセス引数 (ps aux など) にも -pPASSWORD123 が見えてしまうので、本来はセキュリティ的に推奨されません。
✔ つまりこの Task は、
「安全でない mysql の使い方」+「bash history の仕様」
の掛け合わせが root 奪取に直結する例です。
● 実務だとどう防ぐか?
現場で守るべきはだいたいこのあたりです。
-
CLI オプションにパスワードを書かない
-
mysql -pとだけ打ってプロンプト入力する - 環境変数や
.my.cnf(権限600)などを使う
-
-
HISTCONTROL/HISTIGNOREを活用する- 例えば
HISTCONTROL=ignorespaceにしておき、
先頭にスペースを付けたコマンドは履歴に残さないようにする運用など
- 例えば
-
「history を定期的に削除する」のは根本対策にならない
→ 「そもそも載せない」文化を作るほうが重要
■ Task17:Config Files
〜 Config は設定ファイルではなく、認証情報の“集積所” 〜
● 何をしたか(手順)
ホームディレクトリを確認すると、VPN の設定ファイルっぽいものが見つかります。
ls /home/user
myvpn.ovpn
中身を見てみると:
cat /home/user/myvpn.ovpn
client
dev tun
proto udp
remote 10.10.10.10 1194
...
auth-user-pass /etc/openvpn/auth.txt
...
ここで重要なのは auth-user-pass ディレクティブです。
- OpenVPN クライアントは、このパスにあるファイルから
ユーザ名1行目 / パスワード2行目 を読み取る - つまり 認証情報の「置き場」がハードコードされている
指定されている /etc/openvpn/auth.txt を見ると:
cat /etc/openvpn/auth.txt
root
PASSWORD123
はい、また root の生パスワード。
su root
# → root シェル
● OpenVPN 的には何が起きているか?
auth-user-pass の挙動を整理するとこうなります。
-
auth-user-passだけ → 実行時にユーザへ username/password を対話入力させる -
auth-user-pass /path/to/file→ 指定ファイルから username/password を読み込む
今回は後者。
OpenVPN 側は「/etc/openvpn/auth.txt は安全に管理されているはず」という前提で動いているため、OS レベルで world-readable になっていようが知ったこっちゃありません。
つまりこの Task は、
「ミドルウェアの“信頼前提”が、OS のファイル権限設計と噛み合っていない」
例として見るとわかりやすいです。
● ファイル権限の観点
本来やるべきなのはこういう設計です。
-
/etc/openvpn/auth.txtのパーミッションを 600 にするchmod 600 /etc/openvpn/auth.txt chown root:root /etc/openvpn/auth.txt -
OpenVPN プロセスを root もしくは専用ユーザで動かし、
「そのユーザだけが読める」状態にしておく
Task の VM ではここがザルなので、
- ローカルの低権限ユーザが
cat /etc/openvpn/auth.txtできる - そのまま
su rootが通ってしまう
という状態になっています。
● 実務での「あるある」&対策
よくあるやらかし
- VPN・DB・API クライアントの設定ファイルに
ID/PW を平文で放り込む - しかも
/etcや 共有ディレクトリなど、
他ユーザも読める場所に置いてしまう
現実的な防御
- 平文で置かざるを得ない場合は「読めるユーザを厳密に制限」
→600+ 所有者適切設定は最低ライン - そもそも ID/PW ではなく、
証明書ベース認証やトークンベース認証への移行を検討する - 設定ファイルを Git にそのまま突っ込まない
→.gitignore/ 環境変数 / Secret Manager などで分離する
Task17 は、
「Config ファイルは“動かすためのメモ”ではなく、
最悪の場合 root 直行の鍵束になる」
という意識を持つきっかけになります。
■ Task18:SSH Keys
〜 鍵が落ちていたら、その家はもう所有者のものではない 〜
● 何をしたか(手順)
/ 直下に 不自然な隠しディレクトリがあるのに気付くところからスタートです。
ls -la /
drwxr-xr-x 2 root root 4096 ... .ssh
中身を確認すると:
ls -l /.ssh
-rw-r--r-- 1 root root 1679 ... root_key
-
root_keyというファイル名 - サイズ的にも「典型的な RSA 秘密鍵」
しかもパーミッションが 644 (rw-r--r--) で、
誰でも読み取り可能になっています。
● SSH 秘密鍵のフォーマット
中身を cat してみると、おなじみのやつが出てきます。
cat /.ssh/root_key
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
もしくは古い形式だと:
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
SSH 的にはこれは クライアント側に置くべき秘密鍵であり、
- サーバ側:
~/.ssh/authorized_keysに 公開鍵 を置く - クライアント側:
~/.ssh/id_rsa(秘密鍵)を所持し、ssh -iで使う
という役割分担になっています。
この VM では「サーバ側に“秘密鍵”が落ちっぱなし」という完全アウトな状態です。
● 権限 600 が必須な理由
手元にコピーしたあと、まずはパーミッションを直します。
chmod 600 root_key
なぜかというと、ssh クライアントは
「権限が甘い秘密鍵は危険」と判断して使うのを拒否する
という安全機構を持っているからです。
- 他ユーザに読み取り可能 = 秘密鍵とは呼べない
- なので、クライアント側で 600 以外なら文句を言う
これは逆に言うと、
「秘密鍵を world-readable にしているサーバ」は
もはやセキュアとかそういう次元にいない
ということでもあります。
● ログインコマンドとオプションの意味
問題文の SSH コマンドはこうなっています。
ssh -i root_key \
-oPubkeyAcceptedKeyTypes=+ssh-rsa \
-oHostKeyAlgorithms=+ssh-rsa \
root@MACHINE_IP
ここで指定しているのは、いわゆる レガシー暗号スイートの許可です。
最近の OpenSSH は、
-
ssh-rsa(SHA-1 ベース)の鍵種別・ホスト鍵を
デフォルトでは拒否するようになっている
ため、古い VM に接続する際には、
-
PubkeyAcceptedKeyTypes=+ssh-rsa
→ クライアント認証として ssh-rsa を許可 -
HostKeyAlgorithms=+ssh-rsa
→ サーバホスト鍵として ssh-rsa を許可
といったオプションが必要になることがあります。
Task としては
「鍵そのものは有効だが、暗号スイートが古くてそのままでは弾かれる」
という **“実務でも割と遭遇する問題”**もついでに体験させている形です。
● なぜこれが一番ヤバいのか?
パスワード漏洩と秘密鍵漏洩は、重さがそもそも違います。
- パスワード
→ 変えればまだ巻き返せる - 秘密鍵
→ すでに「署名」「認証」のベースに載ってしまっている
→ PKI 全体を張り替える必要が出てくることも
SSH の世界観では、
「秘密鍵を持っている=本人そのもの」
なので、
- root の秘密鍵が world-readable
- さらに
authorized_keysに対応する公開鍵が登録済み
という状況は、そのサーバの root という人格そのものが盗まれているのと同じです。
● 実務での対策
- root で SSH ログインさせない(
PermitRootLogin no)
→ そもそも「root に対する鍵認証」という概念を消す - 鍵ペアをユーザごとに発行し、
authorized_keysをユーザ単位で管理 -
.sshディレクトリの権限を定期チェック(700 / 600 以外を検出) - 古い ssh-rsa の整理(ED25519 / ECDSA などへの移行)
Task18 は、そういう「鍵運用全体をどう見るか」という視点まで含めて考えるとかなりおいしいタスクです。
■ Task16〜18 総括
〜 “人間の痕跡”は Exploit より強力な攻撃面になる 〜
3つを並べて整理するとこうです。
| Task | 起点 | 技術要素 | 実際の侵入パス |
|---|---|---|---|
| 16 | history に残ったコマンド | bash の履歴機能 / CLI オプションの扱い |
~/.bash_history → パスワード → su root
|
| 17 | Config ファイルの設定 | OpenVPN の auth-user-pass / ファイル権限 |
myvpn.ovpn → /etc/openvpn/auth.txt → su root
|
| 18 | 秘密鍵の雑な管理 | SSH 鍵・権限600制約 / レガシー ssh-rsa |
/.ssh/root_key → ssh -i root_key root@…
|
共通しているのは、
- 攻撃者は 難しい Exploit コードを投げていない
- やっているのは「ファイルを読む/そのまま使う」だけ
という点です。
権限昇格は「カーネル Exploit のエンドゲーム」だけではなく、
人間が残した痕跡と、“まあいいか”の積み重ねからも普通に起きる。
Task1〜15 が「OS/バイナリ/権限の仕組み」を揺さぶる回だとすると、
Task16〜18 は
「日々の運用・作業ログ・Config 設計」の甘さが
どれだけ root 直結かを叩きつける回
になっています。
■ おわりに
Task16〜18 を技術的に分解すると、こんな教訓が残ります。
-
history はログではなく“証拠”
→ パスワードを CLI オプションに乗せない -
Config ファイルは設定ではなく“リスク資産”
→ 認証情報を書くなら、権限と保管場所を本気で設計する -
秘密鍵は「本人そのもの」
→ world-readable な鍵があった時点で、そのアカウントは終わっている
次の Task19〜21 では、
人間ではなく NFS / Kernel / 自動化ツールを軸に
- 「ファイル所有者」
- 「カーネルの安全性」
- 「ツールが拾いきれない前提の穴」
といった、OS レベルの信仰を壊していくフェーズに入ります。
ここまで読んでくれた方へ
「人のミス × Linux の仕様」がどう root 直行になるかのイメージが
少しでもクリアになっていたら嬉しいです。
特に今回の章は理解しやすい内容を、さらにLinux的にはどうなっている?
という観点を記載したつもりです。
この次の Task19〜21 は、一つ一つが重ためなので、
それぞれを記事にしたいと思います。