Vulnerability Disclosure - MISP 2.4.155
Introduction
MISP (Malware Information Sharing Platform) is an open source threat intelligence platform. This web application is used for collecting, storing, distributing and sharing cyber security indicators and threats about cyber security incidents analysis and malware analysis.
The source code of MISP is built with CakePHP, an open-source web framework that follows the model–view–controller approach.
In February 2022, I was mandated to perform a security audit of the latest release of MISP. This two weeks long source code security audit resulted in the discovery of several security issues.
The most critical vulnerability could lead an authenticated attacker to gain remote code execution.
Vulnerability summary
CVE-2022-29528
- Insecure PHAR deserialization.CVE-2022-27245
- Server-side request forgery.CVE-2022-27243
- Local File Inclusion.CVE-2022-27246
- Cross-Site Scripting via SVG upload.CVE-2022-27244
- Stored Cross-Site Scripting.
Vulnerability details
Insecure PHAR deserialization - CVE-2022-29528
It is possible to trigger an insecure PHAR deserialization in the import
function of the DecayingModelController.php
controller. This vulnerability can lead to remote code execution.
As seen in the snippet of code below, when the import
function is being called in a POST or PUT HTTP request, the value of $this->request->data['DecayingModel']
is assigned to the $data
variable.
// app/Controller/DecayingModelController.php
public function import()
{
if ($this->request->is('post') || $this->request->is('put')) {
$data = $this->request->data['DecayingModel'];
// ...
if ($data['submittedjson']['size'] > 0) {
$filename = basename($data['submittedjson']['name']);
$file_content = file_get_contents($data['submittedjson']['tmp_name']);
// ...
}
}
}
If the value of $data['submittedjson']['size']
is greater than 0, then the value of $data['submittedjson']['tmp_name']
is passed to the file_get_contents
function as an argument.
CakePHP Request
In CakePHP 2.x, all POST data can be accessed using $this->request->data
associative array. Any form data that contains a data prefix will have that data prefix removed. For example:
// An input with a name attribute equal to 'data[DecayingModel][json]'
// is accessible at
$this->request->data['DecayingModel']['json'];
CakePHP merges the form data as well as uploaded files to the $this->request->data
property. When a file is uploaded in a CakePHP application, the item in the $_FILES
superglobal along some of its attributes (tmp_name
, error
, name
, type
and size
) are inserted as a new item to the $this->request->data
property.
In MISP, the /decayingModel/import
view generates a form containing a textarea with a name attribute equal to data[DecayingModel][json]
and a file input with a name attribute equal to data[DecayingModel][submittedjson]
.
<form action="/decayingModel/import" method="POST">
<textarea name="data[DecayingModel][json]"></textarea>
<input type="file" name="data[DecayingModel][submittedjson]">
...
</form>
When submitting the form with an attached file, CakePHP will merges all the POST data in the associative array. For example:
// The items in $_FILES are merged to $this->request->data
$data = $this->request->data['DecayingModel'];
echo $data['json'];
echo $data['submittedjson']['tmp_name'];
echo $data['submittedjson']['name'];
echo $data['submittedjson']['size'];
During a file upload, an attacker should not be able to control the value of tmp_name
because it's a file path that is randomly generated by the server to store the uploaded file. The path usually looks like /tmp/phpn3FmFr
.
However, because CakePHP merges all the POST data, it is possible to forge a fake file upload with attacker controlled attributes. An attacker can create a new form that replaces the file input with several text inputs named after each attributes of a regular $_FILE
entry. For example:
<form action="/decayingModel/import" method="POST">
<textarea name="data[DecayingModel][json]"></textarea>
<input type="text"
name="data[DecayingModel][submittedjson][tmp_name]"
value="phar:///tmp/exploit.phar/test">
<input type="text"
name="data[DecayingModel][submittedjson][error]"
value="">
<input type="text"
name="data[DecayingModel][submittedjson][name]"
value="name">
<input type="text"
name="data[DecayingModel][submittedjson][type]"
value="application/octet-stream">
<input type="text"
name="data[DecayingModel][submittedjson][size]"
value="1">
...
</form>
This way the value of tmp_name
can be controlled by an attacker and set to a phar://
(PHP Archive) stream wrapper such as phar:///tmp/exploit.phar/test
.
As we saw earlier, the function file_get_contents
is called with the value of tmp_name
as an argument. This function can be abused to execute arbitrary commands while the path is set to a malicious PHP Archive item.
INFO
Generating a ROP chain and uploading the PHAR archive at a predictable path is left as an exercise to the reader.