CTF入門として評判のOverTheWire: Banditを、前提知識のほとんどない状態から挑んでみました。 始め方から、問題を解く際の試行錯誤までを詳細に記録します。
まずはLevel0からLevel10までを解いてみました。
[追記]Level20まで追加しました。
- はじめに
- 作業環境
- OverTheWire: Bandit
- Level 0
- Level 0 → Level 1
- Level 1 → Level 2
- Level 2 → Level 3
- Level 3 → Level 4
- Level 4 → Level 5
- Level 5 → Level 6
- Level 6 → Level 7
- Level 7 → Level 8
- Level 8 → Level 9
- Level 9 → Level 10
- Level 10 → Level 11
- Level 11 → Level 12
- Level 12 → Level 13
- Level 13 → Level 14
- Level 14 → Level 15
- Level 15 → Level 16
- Level 16 → Level 17
- Level 17 → Level 18
- Level 18 → Level 19
- Level 19 → Level 20
- おわりに
- 参考
はじめに
おはよう。@bioerrorlogです。
CTFをやってみたいと思い立ちました。 きっかけはこのLiveOverfow氏の動画です。
彼のリバースエンジニアリング入門動画などは好きで見ていたので1、彼の勧めるCTFには以前から興味がありました。
CTF (Capture The Flag)とは、その名の通り旗取り合戦のことです。 FPSゲームでの陣取り合戦もこれに当たるようですが、ここではコンピュータセキュリティにおけるCTFを指しています。 CTF用に用意されたサーバーに入ったり、プログラムを解析したりして、Flagと呼ばれる文字列の発見を目指すクイズ形式の競技のようなものだそうです。
正直あまりイメージが掴めませんが、とても面白そうな香りがします。 私はネットワークも全くわからない初心者なので、とりあえず初心者向けのCTFに挑戦してみたいと思います。
CTFには制限時間がある競技形式のものと、常に開かれている常設CTFがあります。 競技形式のものは初心者にはハードルが高いので、常設CTFをやってみることにしました。
上の動画でもおすすめされている、OverTheWireというサイトで開かれているCTFに挑んでみることにします。
このサイトのWargamesというCTF集のうち、もっとも初心者向けのBanditをやっていきます。
右も左もわからない状態なので、ひとつひとつ確認していきながら、試行錯誤の記録を残します。
[関連記事] 逆アセンブル解析 - gdb | リバースエンジニアリング入門#2
作業環境
OSについては注意が必要です。 ターミナルからのUnixコマンド操作を前提としているそうなので、Windowsでやろうとすると何かと厄介でしょう。
私はUbuntu18.04.1 LTS を
Windows10の上に、VMwareによって構築した仮想環境で起動しています。
www.bioerrorlog.work
OverTheWire: Bandit
Level 0
sshの使い方
それではLevel0からやっていきます。 問題文はこれです。
The goal of this level is for you to log into the game using SSH. The host to which you need to connect is bandit.labs.overthewire.org, on port 2220. The username is bandit0 and the password is bandit0. Once logged in, go to the Level 1 page to find out how to beat Level 1.
sshなるものを用いて、このサイトにログインするのが一番最初のLevel 0 の目的のようです。
ログインするホスト名は bandit.labs.overthewire.org
ポート番号は 2220
ユーザーネームは bandit0
パスワードは bandit0
となっています。
ログインという操作は日常的に慣れ親しんでいますが、ここで出てきたsshコマンドでのログインには経験がありません。 少し調べることにします。
まずはsshのマニュアルを読みます。
$ man ssh
NAME ssh — OpenSSH SSH client (remote login program) ~ DESCRIPTION ssh (SSH client) is a program for logging into a remote machine and for executing commands on a remote machine.
sshは、遠隔マシンにログインしてコマンドを実行するためのプログラムのようです。
今回の私のケースだとbandit.labs.overthewire.org
にログインして、そこでコマンド操作が行えるようになる、ということでしょう。
マニュアルを読み進めて、sshコマンドの使い方を調べます。
SYNOPSIS ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port] [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file] [-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port] [-Q query_option] [-R address] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]] [user@]hostname [command]
膨大なオプションの記述に圧倒されそうですが、落ち着いて今回必要な部分を抽出します。 今回ログインに使う情報は、ホスト名、ポート番号、ユーザー名、パスワードでした。 これらを上のオプションから読み出すと、使い方は次のようになるはずです。
ssh hostname [-l login_name] [-p port]
パスワードを指定するオプションが見当たりませんが、後で接続時に要求されるのでしょうか。
とりあえずこれに従うなら、
ssh bandit.labs.overthewire.org -l bandit0 -p 2220
とすれば上手くいきそうです。
※次のように記述しても上手くいきました。
ssh bandit0@bandit.labs.overthewire.org -p 2220
コマンドを実践する前に、もう一点確認したいことがあります。 sshで接続を確立した後、どのようにして接続を切ればいいのでしょうか。 再びマニュアルを確認すると、
~. Disconnect.
接続を切るには ~.
と入力すれば良いようです。
※exit
と入力しても、接続を終了することができました。
以上でだいたい使い方は分かりました。
さっそく実践してみます。
sshログイン
それでは上記コマンドを実行します。
$ ssh bandit.labs.overthewire.org -l bandit0 -p 2220 The authenticity of host '[bandit.labs.overthewire.org]:2220 ([176.9.9.172]:2220)' can't be established.ECDSA key fingerprint is SHA256:98UL0ZWr85496EtCRkKlo20X3OPnyPSB5tB5RPbhczc. Are you sure you want to continue connecting (yes/no)?
何やら警告を吐かれました。 ホストの信憑性が確立できませんでしたが、接続を続けていいですか?という感じのことを聞かれています。
よくわからなかったので検索をかけてみると、これはログインしたことのないホストにアクセスする際に出る警告だそうです。
yes
として先へ進みます。
yes Warning: Permanently added '[bandit.labs.overthewire.org]:2220,[176.9.9.172]:2220' (ECDSA) to the list of known hosts. This is a OverTheWire game server. More information on http://www.overthewire.org/wargames bandit0@bandit.labs.overthewire.org's password:
パスワードを要求されました。
bandit0
を入力すると、
Linux bandit 4.18.12 x86_64 GNU/Linux ,----.. ,----, .---. / / \ ,/ .`| /. ./| / . : ,` .' : .--'. ' ; . / ;. \ ; ; / /__./ \ : | . ; / ` ; .'___,/ ,' .--'. ' \' . ; | ; \ ; | | : | /___/ \ | ' ' | : | ; | ' ; |.'; ; ; \ \; : . | ' ' ' : `----' | | \ ; ` | ' ; \; / | ' : ; . \ .\ ; \ \ ', / | | ' \ \ ' \ | ; : / ' : | : ' |--" \ \ .' ; |.' \ \ ; www. `---` ver '---' he '---" ire.org Welcome to OverTheWire! ・ ・ 中略 ・ Enjoy your stay! bandit0@bandit:~$ # bandit0にログイン完了
見事、bandit0へのログインに成功しました。
Level0の目的達成です。
[関連記事] radare2の使い方 | リバースエンジニアリング入門#5
Level 0 → Level 1
次の問題です。
The password for the next level is stored in a file called readme located in the home directory. Use this password to log into bandit1 using SSH. Whenever you find a password for a level, use SSH (on port 2220) to log into that level and continue the game.
次のレベルに行くためのパスワードは、ホームディレクトリにあるreadmeというファイルに書かれている、とあります。 そのパスワードを用いてbandit1にログインせよ、とのことです。
さっそく調べます。
$ ls #カレントディレクトリのファイルを表示 readme $ cat readme #readmeの中身を表示 boJ9jbbUNNfktd78OOpsqOltutMc3MY1
readmeファイルの中にパスワードboJ9jbbUNNfktd78OOpsqOltutMc3MY1
を見つけました。
exit
でbandit0への接続を終了してから、見つけたパスワードを使ってbandit1にログインします。
$ ssh bandit.labs.overthewire.org -l bandit1 -p 2220 This is a OverTheWire game server. More information on http://www.overthewire.org/wargames bandit1@bandit.labs.overthewire.org's password: # boJ9jbbUNNfktd78OOpsqOltutMc3MY1を入力 ・ ・ 中略 ・ Enjoy your stay! bandit1@bandit:~$
bandit1へのログインに成功しました。 Level1達成です。
Level 1 → Level 2
次の問題です。
The password for the next level is stored in a file called - located in the home directory
パスワードは-
というファイルに入っている、とのことです。
さっそく調べてみます。
$ ls - $ cat - # コマンドが実行されない
ここで問題が生じました。
-
ファイルの中身を見るためにcat -
を打ち込んだのですが、コマンドが実行されませんでした。
これは考えてみれば当然のことです。
コマンドラインでは-
という文字はオプションの指定に使われます。
なので、cat -
と打ってしまうと、ターミナルは次に続くオプションの入力を待ってしまうわけです。
そこで、まず思いついたのはエスケープ記号を使うことです。
調べてみると、bashでは3つのエスケープ方法があるようです。
\
を打つやり方、シングルクオーテーション' '
で囲むやり方、ダブルクオーテーション" "
で囲むやり方です。
しかし、このどれを実行しても今回の問題は解決されませんでした。
そこで、別の方法を考えてみます。 思いついたのは、もう少し丁寧にファイル名を指定してあげることです。 つまり、パスを含めてファイルを指定します。
$ cat ./- CV1DtqXWVFXTvM2F0k09SHz0YwRINYA9
見事、パスワードを読み出すことができました。
このパスワードを使ってLevel2にログインすれば、Level1達成です。
Level 2 → Level 3
次の問題です。
The password for the next level is stored in a file called spaces in this filename located in the home directory
spaces in this filename
というファイルの中に、次のパスワードが入っているようです。
注意したいのは、ファイル名にスペースが含まれていることです。
そのままのファイル名をcat
コマンドに渡すと、次のようにspaces
、 in
、 this
、 filename
それぞれが別のファイルとみなされてしまいます。
$ ls spaces in this filename $ cat spaces in this filename cat: spaces: No such file or directory cat: in: No such file or directory cat: this: No such file or directory cat: filename: No such file or directory
そこで、Level1でも言及したエスケープ文字を使います。
spaces in this filename
を、シングルクォーテーション' '
で囲んであげる訳です。
$ cat 'spaces in this filename' UmHadQclWmgdLOKQ3YNgjWxGoRMb5luK
これで、パスワードが手に入りました。
Level 3 → Level 4
次の問題です。
The password for the next level is stored in a hidden file in the inhere directory.
inhere
ディレクトリの中にある隠しファイルに、パスワードが書かれているようです。
まずはinhere
ディレクトリに移動し、そこにあるファイルをls
コマンドで見てみます。
$ ls inhere $ cd inhere # inhereに移動 $ ls # ファイルが一つも表示されない
ls
コマンドでは、ファイルが表示されませんでした。
そこで、ls
コマンドのオプション-a
を使うことにします。
-a
オプションは、マニュアルによると、
-a, --all do not ignore entries starting with .
.
からはじまる隠しファイルを無視せず表示することができます。
さっそくやってみます。
$ ls -a . .. .hidden
.hidden
という隠しファイルが現れました。
中身を見ます。
$ cat .hidden pIwrPrtPN36QITSp3EQaw936yaFoFgAB
みごとパスワードがありました。
Level 4 → Level 5
The password for the next level is stored in the only human-readable file in the inhere directory. Tip: if your terminal is messed up, try the “reset” command.
inhere
ディレクトリの中には"人間が読める"ファイルがあり、そこにパスワードが書いてある、とあります。
さっそくinhere
ディレクトリに行き、ファイルを見てみます。
$ cd inhere $ ls -la #すべてのファイルをリストで表示 total 48 drwxr-xr-x 2 root root 4096 Oct 16 2018 . drwxr-xr-x 3 root root 4096 Oct 16 2018 .. -rw-r----- 1 bandit5 bandit4 33 Oct 16 2018 -file00 -rw-r----- 1 bandit5 bandit4 33 Oct 16 2018 -file01 -rw-r----- 1 bandit5 bandit4 33 Oct 16 2018 -file02 -rw-r----- 1 bandit5 bandit4 33 Oct 16 2018 -file03 -rw-r----- 1 bandit5 bandit4 33 Oct 16 2018 -file04 -rw-r----- 1 bandit5 bandit4 33 Oct 16 2018 -file05 -rw-r----- 1 bandit5 bandit4 33 Oct 16 2018 -file06 -rw-r----- 1 bandit5 bandit4 33 Oct 16 2018 -file07 -rw-r----- 1 bandit5 bandit4 33 Oct 16 2018 -file08 -rw-r----- 1 bandit5 bandit4 33 Oct 16 2018 -file09
-file00
から-file09
までの9つのファイルがあります。
どのファイルが"人間が読める"ファイルなのかを確認するために、file
コマンドでファイルタイプを確認します。
ここで、-
がそれぞれのファイル名の先頭にあることに注意です。
次のように安易にfile
コマンドを使ってしまうと、
$ file * # すべてのファイルにfileコマンドを実行 file: Cannot open `ile00' (No such file or directory). file: Cannot open `ile01' (No such file or directory). file: Cannot open `ile02' (No such file or directory). file: Cannot open `ile03' (No such file or directory). file: Cannot open `ile04' (No such file or directory). file: Cannot open `ile05' (No such file or directory). file: Cannot open `ile06' (No such file or directory). file: Cannot open `ile07' (No such file or directory). file: Cannot open `ile08' (No such file or directory). file: Cannot open `ile09' (No such file or directory).
-
をオプション記号と捉えられ、うまく実行できません。
そういうときは、Level2で出てきたように、パスから指定してあげれば上手くいきそうです。
$ file ./* ./-file00: data ./-file01: data ./-file02: data ./-file03: data ./-file04: data ./-file05: data ./-file06: data ./-file07: ASCII text ./-file08: data ./-file09: data
まさしく、-file07
のみがASCIIテキストファイルであることが分かりました。
中身を見ると、
$ cat ./-file07 koReBOKuIDDepwhWk7jZC0RTdopnAYKh
パスワードが見つかりました。
ちなみに-file07
以外のファイルを見ようとすると、
$ cat ./-file01 ���U"7�w���H��ê�Q����(���#���
まさに、"人間には理解できない"文字列が入っていました。
Level 5 → Level 6
The password for the next level is stored in a file somewhere under the inhere directory and has all of the following properties:
human-readable
1033 bytes in size
not executable
inhere
ディレクトリ下のどこかに、次の条件を満たすファイルがあるとのことです。
・"人間が読める"
・1033バイトのファイルサイズ
・実行可能でない
まずはとりあえず、inhere
ディレクトリのファイルを見てみます
$ cd inhere/ $ ls -la total 88 drwxr-x--- 22 root bandit5 4096 Oct 16 2018 . drwxr-xr-x 3 root root 4096 Oct 16 2018 .. drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere00 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere01 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere02 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere03 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere04 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere05 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere06 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere07 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere08 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere09 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere10 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere11 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere12 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere13 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere14 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere15 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere16 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere17 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere18 drwxr-x--- 2 root bandit5 4096 Oct 16 2018 maybehere19
maybehere00
からmaybehere19
までの20個のファイルがありました。
これらのファイルタイプを確認してみると、
$ file * maybehere00: directory maybehere01: directory maybehere02: directory maybehere03: directory maybehere04: directory maybehere05: directory maybehere06: directory maybehere07: directory maybehere08: directory maybehere09: directory maybehere10: directory maybehere11: directory maybehere12: directory maybehere13: directory maybehere14: directory maybehere15: directory maybehere16: directory maybehere17: directory maybehere18: directory maybehere19: directory
すべてがディレクトリでした。 これらの中に入っているファイルのうち、上記3つの条件を満たしているものを探します。
find
コマンドを用いて、「1033バイトのファイルサイズ」かつ「実行可能でない」ものを検索します。
まずはfind
コマンドのマニュアルから、ファイルサイズ検索に関するオプションを探しました。
-size n[cwbkMG] File uses n units of space, rounding up. The following suffixes can be used: (中略) `c' for bytes
これによると、-size 1033c
とすれば、1033バイトのファイルサイズを持つファイルが見つけられそうです。
次に実行可能性を検索するオプションを探すと、
-executable Matches files which are executable and directories which are searchable
-executable
オプションによって、実行可能なファイルが検索できるようです。
今回私は「実行可能でない」ファイルを検索したいので、逆に! -executable
とすれば良いでしょう。
この2つの条件でfind
してみます。
$ find -size 1033c ! -executable ./maybehere07/.file2
見事ひとつのファイルが検索に引っかかりました。
このmabehere07
ディレクトリにある.file2
のファイルタイプを確認すると、
$ file ./maybehere07/.file2 ./maybehere07/.file2: ASCII text, with very long lines
ASCIIテキストファイルなので、もう一つの条件「人間が読める」も満たしそうです。 このファイルの中身を見てみます。
$ cat ./maybehere07/.file2 DXjZPULLxYr17uwoI01bNLQbtFemEgo7
見事、パスワードがありました。
Level 6 → Level 7
The password for the next level is stored somewhere on the server and has all of the following properties:
owned by user bandit7
owned by group bandit6
33 bytes in size
サーバーのどこかに、次の3つの条件を満たすファイルがあるそうです。
・ユーザーbandit7に所有されている
・グループbandit6に所有されている
・サイズが33バイト
では、とりあえずfind
コマンドで33バイトのファイルを検索してみます。
「サーバーのどこかに」とあるので、ルートディレクトリから検索をかけます。
$ find / -size 33c # / はルートディレクトリを示す find: ‘/run/lvm’: Permission denied find: ‘/run/screen/S-bandit10’: Permission denied find: ‘/run/screen/S-bandit4’: Permission denied find: ‘/run/screen/S-bandit3’: Permission denied find: ‘/run/screen/S-bandit22’: Permission denied find: ‘/run/screen/S-bandit18’: Permission denied find: ‘/run/screen/S-bandit17’: Permission denied find: ‘/run/screen/S-bandit25’: Permission denied ・ ・以下略 ・
膨大な量のファイルがヒットしてしまいました。 やはり、ファイルサイズ以外の2つの条件を上手く使わないとダメみたいです。
ユーザーとグループによる所有権を検索するオプションがないか、find
のマニュアルを調べてみると、
-user uname File is owned by user uname (numeric user ID allowed). ・・・ -group gname File belongs to group gname (numeric group ID allowed).
-user
と-group
によって、それぞれの所有権を指定できるようです。
さっそくやってみます。
$ find / -size 33c -user bandit7 -group bandit6 find: ‘/run/lvm’: Permission denied find: ‘/run/screen/S-bandit10’: Permission denied find: ‘/run/screen/S-bandit4’: Permission denied find: ‘/run/screen/S-bandit3’: Permission denied find: ‘/run/screen/S-bandit22’: Permission denied find: ‘/run/screen/S-bandit18’: Permission denied ・ ・以下略 ・
さっきよりは検索結果が絞られましたが、まだfind: ~~~ : Permission denied
などのエラー出力が大量に残っています。
そこで、検索結果のなかでエラー出力を非表示にする方法を調べました。
出力をリダイレクトする>
を使えば、エラーを排除できるようです。
ある記事2によると、
command 2>/dev/null
This syntax redirects the command error output messages to /dev/null where it is ignored by the shell.
2>
を使うことで、エラー出力をリダイレクトすることができるそうです3。
そしてリダイレクト先は/dev/null
です。
このファイルに書き込まれたデータは、システムによって破棄されます。
つまり2>/dev/null
とすることで、エラー出力を排除することができるというわけです。
さっそくやってみます。
$ find / -size 33c -user bandit7 -group bandit6 2>/dev/null /var/lib/dpkg/info/bandit7.password
お見事、ファイルがひとつだけヒットしました。 ファイルを読み出して、目的達成です。
$ cat /var/lib/dpkg/info/bandit7.password HKBPTKQnIay4Fw76bEy8PVxKEDQRKTzs
Level 7 → Level 8
The password for the next level is stored in the file data.txt next to the word millionth
data.txt
ファイルの中のmillionth
という単語の隣に、次のパスワードがあるそうです。
とりあえずdata.txt
を見てみます。
$ ls data.txt $ cat data.txt ・ ・ Sutherland GPj6IhYqUlcjb8hYdtbwpKUtIKeSHXNC Michigan's rjQZqJB52C0ioveSov6Wt0nLK5zZrUvw Arthurian HqnDL5cvz8MhI8ctfyGmQ7OoGVksICqg matrimony's rQTEVD0A0SvNHsNqgt4GICdnJX86TSkE tendering 5ARBlVJ1K20R1K7kYNNfp3cJ2KJWm9l1 ・ ・
このように、[単語] [文字列]
となっている行が延々と続いています。
このなかで、millionth
の単語に続く文字列がパスワードということでしょう。
grep
コマンドに出力を渡し、millionth
を検索します。
$ cat data.txt | grep millionth #catの結果をgrepにパイプする millionth cvX2JJa4CFALtqS87jk27qwqGhBM9plV
この右の部分がパスワードです。
[関連記事] Ghidraの使い方 | 初心者がリバースエンジニアリングツールGhidraを使ってみた
Level 8 → Level 9
The password for the next level is stored in the file data.txt and is the only line of text that occurs only once
data.txt
の中に一度だけ現れる行がパスワードとなるようです。
一度だけ現れるといえば、uniq
コマンドが使えそうです。
NAME uniq - report or omit repeated lines ・・・ -u, --unique only print unique lines
マニュアルによると、uniq -u
とすることで一度だけ現れる行を抽出できるようです。
さっそくやってみます。
$ uniq -u data.txt KerqNiDbY0zV2VxnOCmWX5XWxumldlAe MsxcvOe3PGrt78wpZG2bBNF5wfXpZhET L0nxAwlfV9V3J5onKIT8KYQ9InTcQ7yE 4c7EsUtqLnLR9hiepV5EQVhdMgyi8onL 1drBmDT7PYS7hVgoTWkJSjUZUK7ZAIAa L0nxAwlfV9V3J5onKIT8KYQ9InTcQ7yE ・ ・以下略 ・
予想外にも、膨大な行が抽出されてしまいました。
そこで、もう一度真面目にuniq
マニュアルを読んでみると、次のような記述がありました。
Note: 'uniq' does not detect repeated lines unless they are adjacent. You may want to sort the input first, or use 'sort -u' without 'uniq'.
uniq
コマンドは、隣り合った行でないと繰り返しを認識しないため、ソートしてから使いなさい、とあります。
そこで、今度はsort
コマンドでソートしてからuniq
コマンドに渡してみます。
$ sort data.txt | uniq -u UsvVyFSfZZWbi6wgC7dAFyFuR6jQQUhR
見事、検出された行がひとつに絞られました。 これがパスワードです。
Level 9 → Level 10
The password for the next level is stored in the file data.txt in one of the few human-readable strings, beginning with several ‘=’ characters.
data.txt
の中にある"人間が読める"文字列のうち、いくつかの=
文字からはじまるものが次のパスワードのようです。
まず、data.txt
ファイルの中の"人間が読める"文字列を探すために、strings
コマンドを使いました。
$ strings data.txt .MBB `B6ha nK)U2u &y@@2 5Lo% ru@n ・ ・ ・
この表示された大量のテキスト中から、先頭に=
を持つ行を検索すれば良いわけです。
検索には、grep
コマンドを正規表現と組み合わせて使いました。
つまり、行の先頭を指定する正規表現^
を組み合わせて、=
を検索するのです。
$ strings data.txt | grep ^= ========== password ========== isa =FQ?P\U = F[ =)$= ========== truKLdjsbJ5g7yyJ2X2R0o3a5HQJFuLk
見事、一番下に出たtruKLdjsbJ5g7yyJ2X2R0o3a5HQJFuLk
こそがパスワードです。
Level 10 → Level 11
The password for the next level is stored in the file data.txt, which contains base64 encoded data
次のパスワードは、base64エンコードされたデータを含むdata.txtのなかにあるそうです。
base64とは、wikipediaによると4、
Base64は、データを64種類の印字可能な英数字のみを用いて、それ以外の文字を扱うことの出来ない通信環境にてマルチバイト文字やバイナリデータを扱うためのエンコード方式である。 (中略) 具体的には、A–Z, a–z, 0–9 までの62文字と、記号2つ (+, /)、さらにパディング(余った部分を詰める)のための記号として = が用いられる。
A–Z, a–z, 0–9と、+、/そして余った部分に埋められる=を用いて行われるエンコード方式のようです。 これを読み出すには、base64方式でデコードする必要があるということでしょう。
試しに、まずは単純にstrings
コマンドでテキストを読み込んでみます。
$ strings data.txt VGhlIHBhc3N3b3JkIGlzIElGdWt3S0dzRlc4TU9xM0lSRnFyeEUxaHhUTkViVVBSCg==
この文末の==
が、余った部分に埋められるパディングということでしょう。
なので読み出した文字列はVGhlIHBhc3N3b3JkIGlzIElGdWt3S0dzRlc4TU9xM0lSRnFyeEUxaHhUTkViVVBSCg
ということになります。
しかし、案の定この文字列では次のLevel11にログインすることができませんでした。 base64でデコードしなきゃいけないわけでしょう。
そこでbase64
コマンドを使います。
マニュアルによると、
NAME base64 - base64 encode/decode data and print to standard output ・・・ -d, --decode decode data
base64
コマンドの-d
オプションを使えば、デコードできるようです。
$ base64 -d data.txt The password is IFukwKGsFW8MOq3IRFqrxE1hxTNEbUPR
これでパスワードを見つけました。
Level 11 → Level 12
The password for the next level is stored in the file data.txt, where all lowercase (a-z) and uppercase (A-Z) letters have been rotated by 13 positions
パスワードは、小文字(a-z)と大文字(A-Z)を13個ローテーションさせてあるdata.txtにあるそうです。
文字を13こローテーションさせるとは、どういうことでしょうか。 検索してみると、これは「ROT13」という暗号のようです。 wikipediaによると5、
ROT13 または ROT-13、rot13 は単換字式暗号(シーザー暗号)の一つである。アルファベットを一文字毎に13文字後のアルファベットに置き換える。Aは Nに、 B は O に置き換えられ、以下同様である。英語の "Rotate by 13 places" の略。
それではこの暗号を解くために、tr
コマンドを使います。
tr
コマンドは、マニュアルによると、
NAME tr - translate or delete characters ・・・ SYNOPSIS tr [OPTION]... SET1 [SET2]
例えばtr abc 127
とすれば、aは1、bは2、cは3と翻訳されるということです。
$ echo abc | tr abc 123 123
つまりROT13を解くためには、それぞれの文字に対応する13個ローテーションさせた翻訳を指定してあげればいいでしょう。 具体的には、次のようにしました。
$ cat data.txt | tr A-Za-z N-ZA-Mn-za-m The password is 5Te8Y4drgCRfCx8ugdwuEX8KFC6k2EUu
これで、パスワードを割り出すことができました。
Level 12 → Level 13
The password for the next level is stored in the file data.txt, which is a hexdump of a file that has been repeatedly compressed. For this level it may be useful to create a directory under /tmp in which you can work using mkdir. For example: mkdir /tmp/myname123. Then copy the datafile using cp, and rename it using mv (read the manpages!)
パスワードはdata.txt
の中に、繰り返し圧縮されたhexdumpとして記述されているようです。
そして、/tmp
ディレクトリ下にmkdir
コマンドで作業用のディレクトリを作り、そこにcp
コマンドでデータをコピーするのがいいですよ、と助言しています。
これはどういうことでしょうか。
とりあえずdata.txtの中を見てみます。
$ ls data.txt $ cat data.txt 00000000: 1f8b 0808 d7d2 c55b 0203 6461 7461 322e .......[..data2. 00000010: 6269 6e00 013c 02c3 fd42 5a68 3931 4159 bin..<...BZh91AY 00000020: 2653 591d aae5 9800 001b ffff de7f 7fff &SY............. 00000030: bfb7 dfcf 9fff febf f5ad efbf bbdf 7fdb ................ 00000040: f2fd ffdf effa 7fff fbd7 bdff b001 398c ..............9. 00000050: 1006 8000 0000 0d06 9900 0000 6834 000d ............h4.. 00000060: 01a1 a000 007a 8000 0d00 0006 9a00 d034 .....z.........4 00000070: 0d1a 3234 68d1 e536 a6d4 4000 341a 6200 ..24h..6..@.4.b. 00000080: 0069 a000 0000 0000 d003 d200 681a 0d00 .i..........h... 00000090: 0001 b51a 1a0c 201e a000 6d46 8068 069a ...... ...mF.h.. 000000a0: 6834 340c a7a8 3406 4000 0680 0001 ea06 h44...4.@....... 000000b0: 8190 03f5 4032 1a00 0343 4068 0000 0686 ....@2...C@h.... 000000c0: 8000 0320 00d0 0d00 0610 0014 1844 0308 ... .........D.. 000000d0: 04e1 c542 9ab8 2c30 f1be 0b93 763b fb13 ...B..,0....v;.. 000000e0: 50c4 c101 e008 3b7a 92a7 9eba 8a73 8d21 P.....;z.....s.! 000000f0: 9219 9c17 052b fb66 a2c2 fccc 9719 b330 .....+.f.......0 00000100: 6068 8c65 e504 5ec0 ae02 fa6d 16bc 904b `h.e..^....m...K 00000110: ba6c f692 356e c02b 0374 c394 6859 f5bb .l..5n.+.t..hY.. 00000120: 0f9f 528e 4272 22bb 103c 2848 d8aa 2409 ..R.Br"..<(H..$. 00000130: 24d0 d4c8 4b42 7388 ce25 6c1a 7ec1 5f17 $...KBs..%l.~._. 00000140: cc18 ddbf edc1 e3a4 67f1 7a4d 8277 c823 ........g.zM.w.# 00000150: 0450 2232 40e0 07f1 ca16 c6d6 ef0d ecc9 .P"2@........... 00000160: 8bc0 5e2d 4b12 8586 088e 8ca0 e67d a55c ..^-K........}.\ 00000170: 2ca0 18c7 bfb7 7d45 9346 ea5f 2172 01e4 ,.....}E.F._!r.. 00000180: 5598 673f 45af 69b7 a739 7814 8706 04ed U.g?E.i..9x..... 00000190: 5442 1240 0796 6cc8 b2f6 1ef9 8d13 421d TB.@..l.......B. 000001a0: 461f 2e68 4d91 5343 34b5 56e7 46d0 0a0a F..hM.SC4.V.F... 000001b0: 72b7 d873 71d9 6f09 c326 402d dbc0 7cef r..sq.o..&@-..|. 000001c0: 53b1 df60 9ec7 f318 00df 3907 2e85 d85b S..`......9....[ 000001d0: 6a1a e105 0207 c580 e31d 82d5 8646 183c j............F.< 000001e0: 6a04 4911 101a 5427 087c 1f94 47a2 270d j.I...T'.|..G.'. 000001f0: ad12 fc5c 9ad2 5714 514f 34ba 701d fb69 ...\..W.QO4.p..i 00000200: 8eed 0183 e2a1 53ea 2300 26bb bd2f 13df ......S.#.&../.. 00000210: b703 08a3 2309 e43c 44bf 75d4 905e 5f96 ....#..<D.u..^_. 00000220: 481b 362e e82d 9093 7741 740c e65b c7f1 H.6..-..wAt..[.. 00000230: 5550 f247 9043 5097 d626 3a16 da32 c213 UP.G.CP..&:..2.. 00000240: 2acd 298a 5c8a f0c1 b99f e2ee 48a7 0a12 *.).\.......H... 00000250: 03b5 5cb3 0037 cece 773c 0200 00 ..\..7..w<...
このように、データはhexdump形式で記述されています。 hexdumpとは、データを16進数で表現したもので、ちょうど上のような表示形式を取るものです。
このhexdumpで記述されたデータを、xxd
コマンドを使って読み出します。
NAME xxd - make a hexdump or do the reverse. ・・・ -r | -revert reverse operation
xxd
とは、hexdumpを作成したり解読(リバース)したりするコマンドです。
-r
オプションを使うとリバースすることができるようです。
さっそくやってみます。
$ xxd -r data.txt ���6��@4bi���hBZh91AY&SY����������ϟ�����������������9�� �mF�h�h44 D��B��,0�� ��4@�����@2C@h�� � �v;�P��;z�����s�!��+�f���̗�0`h�e�^���m��K�l��5n�+tÔhY���R�ɋ�^-K�����}�\,�ǿ�}E�F�_!r�U�g?E�i��9x��TB@�lȲ���BF.hM�SC4�V�F� ��\��WQO4�p�i�����S�#&��/߷�#ŀ��ՆF�<D�uԐ^_�H6.�-��wAt �[��UP�G�CP��&:�2�*�)�\�������H� �\�7��w<
このように、"人間には読めない"文字列が出てきてしまいました。 何が記述されているのか、検討もつきません。
そこで、この文字ファイルがどのようなファイルタイプなのか、調べることにします。
xxd
コマンドで読み出した結果を別ファイルに出力し、file
コマンドでファイルタイプを見れば良いでしょう。
問題文で推奨されているように、新しい作業用ディレクトリ(/tmp/lain) を作成してdata.txt
をコピーし、そこで作業することにします。
~$ mkdir /tmp/lain ~$ cp data.txt /tmp/lain ~$ cd /tmp/lain /tmp/lain$ ls data.txt
それでは、xxd
コマンドで読み出し、ファイルタイプを調べます。
$ xxd -r data.txt > data_rev $ file data_rev data_rev: gzip compressed data, was "data2.bin", last modified: Tue Oct 16 12:00:23 2018, max compression, from Unix
どうやら、gzip圧縮されたファイル形式だったようです。
-d
(decompress)オプションでgzip
コマンドを実行し、ファイルを解凍します。
$ gzip -d data_rev gzip: data_rev: unknown suffix -- ignored
接尾字がおかしい、と怒られてしましました。
そこで、gzipファイルの拡張子.gz
をつけてから実行してみます。
$ cat data_rev > data_gz.gz $ gzip -d data_gz.gz $ ls data_gz data_rev data.txt
解凍ファイルdata_gz
が作成されました。
またファイルタイプを確認します。
$ file data_gz data_gz: bzip2 compressed data, block size = 900k
今度はbzip2方式で圧縮されているようです。
まさに問題文にあったように、繰り返し圧縮されている、ということでしょう。 ここからは根気強く、ファイルタイプを調べては必要に応じて拡張子を変更し、圧縮方式にあった解凍を施していきます。
## 解凍2回目 $ cat data_gz > data_bz2.bz2 # bzip2の拡張子は .bz2 $ bzip2 -d data_bz2.bz2 # bzip2解凍 $ ls data_bz2 data_gz data_rev data.txt ## 解凍3回目 $ file data_bz2 data_bz2: gzip compressed data, was "data4.bin", last modified: Tue Oct 16 12:00:23 2018, max compression, from Unix $ cat data_bz2 > data_gz-2.gz $ gzip -d data_gz-2.gz # gzip2解凍 $ ls data_bz2 data_gz data_gz-2 data_rev data.txt ## 解凍4回目 $ file data_gz-2 data_gz-2: POSIX tar archive (GNU) $ cat data_gz-2 > data_tar.tar # tarの拡張子は .tar $ tar -xvf data_tar.tar # tar解凍 data5.bin $ ls data5.bin data_bz2 data_gz data_gz-2 data_rev data_tar.tar data.txt ## 解凍5回目 $ file data5.bin data5.bin: POSIX tar archive (GNU) $ tar -xvf data5.bin # tar解凍 (.binのままでも解凍できた) data6.bin $ ls data5.bin data_bz2 data_gz-2 data_tar.tar data6.bin data_gz data_rev data.txt ## 解凍6回目 $ file data6.bin data6.bin: bzip2 compressed data, block size = 900k $ cat data6.bin > data_bz2-2.bz2 $ bzip2 -d data_bz2-2.bz2 # bzip2解凍 $ ls data5.bin data_bz2 data_gz data_rev data.txt data6.bin data_bz2-2 data_gz-2 data_tar.tar ## 解凍7回目 $ file data_bz2-2 data_bz2-2: POSIX tar archive (GNU) $ cat data_bz2-2 > data_tar2.tar $ tar -xvf data_tar2.tar # tar解凍 data8.bin $ ls data5.bin data8.bin data_bz2-2 data_gz-2 data_tar2.tar data.txt data6.bin data_bz2 data_gz data_rev data_tar.tar ## 解凍8回目 $ file data8.bin data8.bin: gzip compressed data, was "data9.bin", last modified: Tue Oct 16 12:00:23 2018, max compression, from Unix $ cat data8.bin > data_gz-3.gz $ gzip -d data_gz-3.gz # gzip解凍 $ ls data5.bin data8.bin data_bz2-2 data_gz-2 data_rev data_tar.tar data6.bin data_bz2 data_gz data_gz-3 data_tar2.tar data.txt $ file data_gz-3 data_gz-3: ASCII text
計8回の解凍を経て、ついに生のASCII textにたどり着くことができました。
$ cat data_gz-3 The password is 8ZjyCRiBWFYkneahHwxCv3wb2a1ORpYL
長い道のりでしたが、ようやくパスワードにありつきました。
Level 13 → Level 14
The password for the next level is stored in /etc/bandit_pass/bandit14 and can only be read by user bandit14. For this level, you don’t get the next password, but you get a private SSH key that can be used to log into the next level. Note: localhost is a hostname that refers to the machine you are working on
次のパスワードは、ユーザーbandit14にしか読み込めない/etc/bandit_pass/bandit14
に入っています。
このレベルではパスワードが手に入らない代わりに、次のレベルにログインするためのSSH秘密鍵が手に入るそうです。
「次のレベルにログインするためのSSH秘密鍵」というのが、何を言っているのか私には分かりません。 問題文とともにヒントとして掲載してある次のページで、SSH秘密鍵でのログインについて調べてみます。
SSH/OpenSSH/Keys - Community Help Wiki
これによると、SSH鍵でのログインは、パスワードログインよりもより安全なログイン方法だそうです。
具体的に言うと、ログイン先PCの~/.ssh/authorized_keys
にSSH公開鍵が登録され、それと対になるSSH秘密鍵が自身の~/.ssh/id_rsa
に入っていれば、ログインが成功するという仕組みです。
つまり、SSH秘密鍵が手に入ったなら、~/.ssh/id_rsa
を作成し、それに書き込めば良さそうです。
それではやっていきます。
$ ls sshkey.private $ cat sshkey.private -----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAxkkOE83W2cOT7IWhFc9aPaaQmQDdgzuXCv+ppZHa++buSkN+ gg0tcr7Fw8NLGa5+Uzec2rEg0WmeevB13AIoYp0MZyETq46t+jk9puNwZwIt9XgB ・ ・中略 ・ kAWpXbv5tbkkzbS0eaLPTKgLzavXtQoTtKwrjpolHKIHUz6Wu+n4abfAIRFubOdN /+aLoRQ0yBDRbdXMsZN/jvY44eM+xRLdRVyMmdPtP8belRi2E2aEzA== -----END RSA PRIVATE KEY-----
さっそくSSH秘密鍵が見つかりました。
自分のPC側に戻り、~/.ssh/id_rsa
を作成してSSH秘密鍵をコピーペーストで追加します。
$ exit logout Connection to bandit.labs.overthewire.org closed. $ cd .ssh $ ls known_hosts # id_rsaはまだ存在しない $ vim id_rsa # id_rsaを作成し、上記SSH秘密鍵をコピーペースト $ ls id_rsa known_hosts $ file id_rsa id_rsa: PEM RSA private key # 秘密鍵として登録された
これで、~/.ssh/id_rsa
にSSH秘密鍵が登録されたはずです。
bandit14
へのログインを試みます。
$ ssh bandit14@bandit.labs.overthewire.org -p 2220 This is a OverTheWire game server. More information on http://www.overthewire.org/wargames @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Permissions 0644 for '/home/<user name>/.ssh/id_rsa' are too open. It is required that your private key files are NOT accessible by others. This private key will be ignored.
秘密鍵が守られていない、という警告が出され、秘密鍵が認証されませんでした。
パーミッションを確認してみると、
$ ls -l id_rsa -rw-r--r-- 1 user user 1680 5月 2 12:13 id_rsa
たしかに、オーナー以外にもファイルの読み込みが許可されています。
※パーミッションの読み方については、以前別記事に記録しました。 www.bioerrorlog.work
そこでchmod
コマンドを用いて、オーナー以外のパーミッションを拒否します。
$ chmod 600 id_rsa # オプションに600を与え、オーナー以外のパーミッションを拒否 (オーナーはrw) $ ls -l id_rsa -rw------- 1 user user 1680 5月 2 12:13 id_rsa
これでパーミッションも設定できました。
bandit14
のログインにリベンジします。
$ ssh bandit14@bandit.labs.overthewire.org -p 2220 This is a OverTheWire game server. More information on http://www.overthewire.org/wargames ・ ・ ・ Enjoy your stay! bandit14@bandit:~$
みごと、ログインに成功しました。
Level 14 → Level 15
The password for the next level can be retrieved by submitting the password of the current level to port 30000 on localhost.
このレベルのパスワードを、ローカルホストのポート30000に送ることで、次のレベルのパスワードを回収することができる、とあります。
まずこのレベルのパスワードですが、Level13の問題文によると/etc/bandit_pass/bandit14
にあるようです。
$ cat /etc/bandit_pass/bandit14 4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e
あとはこのパスワードを、ローカルホストのポート30000に送ればいいのでしょう。 ちなみにローカルホストとは、いま作業しているPCのことです。
データを送るには、今回nc
コマンドを使います。
マニュアルによると、
nc [destination] [port] # destinationは"送り先"
この使い方で接続が確保できるようです。
このnc
接続にパスワードを渡すことで、ローカルホスト/ポート30000にパスワードを送りつけます。
$ cat /etc/bandit_pass/bandit14 | nc localhost 30000 Correct! BfMYroe26WYalil77FoDi9qh59eK5xNr
これで次のパスワードが入手できました。
Level 15 → Level 16
The password for the next level can be retrieved by submitting the password of the current level to port 30001 on localhost using SSL encryption.
このレベルのパスワードを、SSL暗号化した上でローカルホストのポート30001に送ることで、次のレベルのパスワードを回収することができる、とあります。
先程の問題と似ていますが、今度はSSL暗号をかける必要があるようです。
そこで今回はopenssl s_client
コマンドを使います。
マニュアルによると、
The s_client command implements a generic SSL/TLS client which connects to a remote host using SSL/TLS.
遠隔ホストにSSL/TLSを使って接続する、クライアントとして振る舞ってくれるようです。
使い方は、
openssl s_client [-connect host:port]
となっていました。
それでは、これでパスワードを渡してみます。
$ echo BfMYroe26WYalil77FoDi9qh59eK5xNr | openssl s_client -connect localhost:30001 CONNECTED(00000003) ・ ・中略 ・ --- DONE
接続には成功したようですが、何もこちらに返さずに終了してしまいました。
ここで問題文に付記してある注意書きを見てみると、
Helpful note: Getting “HEARTBEATING” and “Read R BLOCK”? Use -ign_eof and read the “CONNECTED COMMANDS” section in the manpage. Next to ‘R’ and ‘Q’, the ‘B’ command also works in this version of that command…
-ign_eof
オプションを使いなさい、というアドバイスが載っています。
-ign_eof
とは、マニュアルによると、
-ign_eof inhibit shutting down the connection when end of file is reached in the input.
入力まで処理が届いたときに、接続を切断するのを防ぐ、とあります。
入力に対して何か反応があるときには、-ign_eof
を指定することでその反応を見ることができる、ということでしょうか。
さっそくやってみます。
$ echo BfMYroe26WYalil77FoDi9qh59eK5xNr | openssl s_client -connect localhost:30001 -ign_eof CONNECTED(00000003) ・ ・中略 ・ --- Correct! cluFn7wTiGryunymYOu4RcffSxQluehd closed
見事、次のパスワードが返ってきました。
[関連記事] Pythonで鍵生成 - Keygen | リバースエンジニアリング入門#7
Level 16 → Level 17
The credentials for the next level can be retrieved by submitting the password of the current level to a port on localhost in the range 31000 to 32000. First find out which of these ports have a server listening on them. Then find out which of those speak SSL and which don’t. There is only 1 server that will give the next credentials, the others will simply send back to you whatever you send to it.
このレベルのパスワードをローカルホストに送りつければ、次の認証が得られるようです。 ただし、31000~32000の範囲の開いているポートを使う必要があります。 まず開いているポートを見つけ出してから、SSLを受け付けるポートを探し、それを使ってパスワードを送ります。
31000~32000の範囲の開いているポートを探すために、nmap
コマンドを使いました。
マニュアルによると、
NAME nmap - Network exploration tool and security / port scanner ・・・ -p <port ranges>: Only scan specified ports Ex: -p22; -p1-65535;
nmap
はポートスキャナーとしての機能を持っており、-p
オプションでそのパート番号の範囲を指定できるようです。
さっそくやってみます。
$ nmap -p31000-32000 localhost Starting Nmap 7.40 ( https://nmap.org ) at 2019-05-02 09:49 CEST Nmap scan report for localhost (127.0.0.1) Host is up (0.00020s latency). Not shown: 998 closed ports PORT STATE SERVICE 31046/tcp open unknown 31790/tcp open unknown 31960/tcp open unknown
開いているポートが3つ検出できました。
つぎは、この3つのポートのうちSSL対応しているものを探します。
これには前のレベルで使ったopenssl s_client
を利用しました。
SSLに対応できないポートなら、openssl s_client
では接続できないはずです。
ポートを一つずつ試していきます。
$ openssl s_client -connect localhost:31046 CONNECTED(00000003) 140211373733120:error:141A10F4:SSL routines:ossl_statem_client_read_transition:unexpected message:../ssl/statem/statem_clnt.c:269: --- no peer certificate available --- No client certificate CA names sent ・ ・以下略 ・
1つめはエラーを吐きました。 SSL対応でなかったのでしょう。
次のポートを試します。
$ openssl s_client -connect localhost:31790 CONNECTED(00000003) depth=0 CN = localhost verify error:num=18:self signed certificate verify return:1 depth=0 CN = localhost verify return:1 --- Certificate chain 0 s:/CN=localhost i:/CN=localhost --- Server certificate ・ ・中略 ・ ---
今度は接続に成功しました。 そして入力待機状態なので、このレベルのパスワードを打ち込みます。
cluFn7wTiGryunymYOu4RcffSxQluehd Correct! -----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAvmOkuifmMg6HL2YPIOjon6iWfbp7c3jx34YkYWqUH57SUdyJ imZzeyGC0gtZPGujUSxiJSWI/oTqexh+cAMTSMlOJf7+BrJObArnxd9Y7YT2bRPQ Ja6Lzb558YW3FZl87ORiO+rW4LCDCNd2lUvLE/GL2GWyuKN0K5iCd5TbtJzEkQTu ・ ・中略 ・ blh9elyZ9FsGxsgtRBXRsqXuz7wtsQAgLHxbdLq/ZJQ7YfzOKU4ZxEnabvXnvWkU YOdjHdSOoKvDQNWu6ucyLRAWFuISeXw9a/9p7ftpxm0TSgyvmfLF2MIAEwyzRqaM 77pBAoGAMmjmIJdjp+Ez8duyn3ieo36yrttF5NSsJLAbxFpdlc1gvtGCWW+9Cq0b dxviW8+TFVEBl1O4f7HVm6EpTscdDxU+bCXWkfjuRb7Dy9GOtt9JPsX8MBTakzh3 vBgsyi/sN3RqRBcGU40fOoZyfAMT8s1m/uYv52O6IgeuZ/ujbjY= -----END RSA PRIVATE KEY-----
こうして秘密鍵が手に入りました。
後は、この秘密鍵を用いて次のレベルにログインします。
私の場合~/.ssh/id_rsa
にはLevel14の秘密鍵を書き込んであるので、今度は別名で秘密鍵を保存し、SSH接続時に-i
オプションで指定するやり方をとってみます。
$ vim .ssh/bandit17_rsa # 入手した秘密鍵を記入 $ ssh bandit17@bandit.labs.overthewire.org -p 2220 -i .ssh/bandit17_rsa # -i オプションで秘密鍵を指定 ・ ・中略 ・ Enjoy your stay! bandit17@bandit:~$
これで、Level17へのログインに成功しました。
Level 17 → Level 18
There are 2 files in the homedirectory: passwords.old and passwords.new. The password for the next level is in passwords.new and is the only line that has been changed between passwords.old and passwords.new
passwords.new
の中にある文字列のうち、passwords.old
との差分がパスワードだそうです。
diff
コマンドで差分を見ていきます。
$ ls passwords.new passwords.old $ diff passwords.new passwords.old 42c42 < kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd --- > hlbSBPAWJmL6WFDb06gpTx1pPButblOA
42c42
とあるので、42行目が両者の違いとなっているようです。
そのうち1つめの引数に渡したpasswords.new
にあった文字列は、---
の上側にでてきた方となります。
つまり、kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd
がパスワードです。
Level 18 → Level 19
The password for the next level is stored in a file readme in the homedirectory. Unfortunately, someone has modified .bashrc to log you out when you log in with SSH.
次のパスワードはホームディレクトリのreadme
ファイルの中にあります。
しかし、誰かが.bashrc
ファイルを書き換えてしまい、SSHでログインすると同時にログアウトするようになってしまいました、とのことです。
.bashrc
とは、bash起動時に実行されるシェルスクリプトです。
たしかに、このLevel18にログインすると、次のように勝手にログアウトされてしまいます。
$ ssh bandit18@bandit.labs.overthewire.org -p 2220 ・ ・中略 ・ Enjoy your stay! Byebye ! Connection to bandit.labs.overthewire.org closed.
そこで、ssh
コマンドを使って、ログインすることなくreadme
の中身を見ます。
ssh
コマンドは文末に別のコマンドを指定すると、ログインすることなく遠隔でそのコマンドを実行することができます。
ssh [user@]hostname [command] ・・・ If command is specified, it is executed on the remote host instead of a login shell.
さっそく試します。
$ ssh -p 2220 bandit18@bandit.labs.overthewire.org cat readme This is a OverTheWire game server. More information on http://www.overthewire.org/wargames bandit18@bandit.labs.overthewire.org's password: IueksS7Ubh8G3DCwVzrTd8rAVOwq3M5x
するとこのように、readme
に書かれていたパスワードを読み出すことができました。
Level 19 → Level 20
To gain access to the next level, you should use the setuid binary in the homedirectory. Execute it without arguments to find out how to use it. The password for this level can be found in the usual place (/etc/bandit_pass), after you have used the setuid binary.
次のレベルにアクセスするためには、ホームディレクトリにあるsetuidバイナリを使う必要があります。
引数なしで実行してみて、使い方を調べてください。
パスワードは/etc/bandit_pass
にあります、とのことです。
そもそもsetuidとは何でしょうか。 wikipediaによると、
setuid と setgid は、UNIXにおけるアクセス権を表すフラグの名称であり、ユーザーが実行ファイルを実行する際にその実行ファイルの所有者やグループの権限で実行できるようにする。それぞれ、set user ID と set group ID の略。一般ユーザーが高い特権レベルでしか実行できないタスクを一時的に実行できるようにする仕組みである。
要は、一時的に権限を高めるための仕組みだそうです。
本来は見ることができない/etc/bandit_pass
の下にあるパスワードファイルを、setuidで得た権限のもとに閲覧しようというわけです。
さっそくやっていきます。
$ ls bandit20-do $ file bandit20-do bandit20-do: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=8e941f24b8c5cd0af67b22b724c57e1ab92a92a1, not stripped $ ./bandit20-do Run a command as another user. Example: ./bandit20-do id
他のユーザーとしてコマンドを実行するには、./bandit20-do <command>
とやれば良いようです。
このsetuid下で、/etc/bandit_pass
下のパスワードファイルを見ます。
$ ./bandit20-do cat /etc/bandit_pass/bandit20 GbKksEFF4yrVs6il55v6gwY5aVje5f0j
パスワードを読み出すことができました。
おわりに
OverTheWire: Banditを、Level0からLevel10まで解いてみました。
[追記]Level20まで追加しました。
Bandit自体は、2019年4月現在Level34まであります。
sshで遠隔ログインしたことがなかったので初めは緊張しましたが、慣れてくると純粋に問題を楽しむことができました。 きれいにパスワードが特定できたときには、中々の興奮があります。
今回やったのは、コマンドの使い方を主軸に置いた入門用のCTFです。 これがもっと難しいものになれば、解いたときの快感は殊更でしょう。
ぜひこれからも遊んでいきたいものです。
参考
What is CTF? An introduction to security Capture The Flag competitions - YouTube
-
参考にした記事もいくつか書きました
逆アセンブル解析 - gdb | リバースエンジニアリング入門#2 - 生物系がゼロから始めるTech Blog↩ -
/dev/null discards unwanted output - Linux Shell Scripting Tutorial - A Beginner's handbook↩
-
ちなみに
>
を使えば標準出力が、&>
を使えば標準出力とエラー出力の両方がリダイレクトされます。↩