Логотип exploitDog
Консоль
Логотип exploitDog

exploitDog

github логотип

GHSA-82vx-mm6r-gg8w

Опубликовано: 01 фев. 2024
Источник: github
Github: Прошло ревью
CVSS3: 3.7

Описание

Bref vulnerable to Body Parsing Inconsistency in Event-Driven Functions

Impacted Resources

bref/src/Event/Http/Psr7Bridge.php:130-168

Description

When Bref is used with the Event-Driven Function runtime and the handler is a RequestHandlerInterface, then the Lambda event is converted to a PSR7 object. During the conversion process, if the request is a MultiPart, each part is parsed and its content added in the $files or $parsedBody arrays. To do that, the following method is called with as first argument the result array ($files or $parsedBody), as second argument the part name, and as third argument the part content:

/** * Parse a string key like "files[id_cards][jpg][]" and do $array['files']['id_cards']['jpg'][] = $value */ private static function parseKeyAndInsertValueInArray(array &$array, string $key, mixed $value): void { if (! str_contains($key, '[')) { $array[$key] = $value; return; } $parts = explode('[', $key); // files[id_cards][jpg][] => [ 'files', 'id_cards]', 'jpg]', ']' ] $pointer = &$array; foreach ($parts as $k => $part) { if ($k === 0) { $pointer = &$pointer[$part]; continue; } // Skip two special cases: // [[ in the key produces empty string // [test : starts with [ but does not end with ] if ($part === '' || ! str_ends_with($part, ']')) { // Malformed key, we use it "as is" $array[$key] = $value; return; } $part = substr($part, 0, -1); // The last char is a ] => remove it to have the real key if ($part === '') { // [] case $pointer = &$pointer[]; } else { $pointer = &$pointer[$part]; } } $pointer = $value; }

The conversion process produces a different output compared to the one of plain PHP when keys ending with and open square bracket ([) are used.

Let's take for example the following part:

------WebKitFormBoundary Content-Disposition: form-data; name="key0[key1][key2][" value ------WebKitFormBoundary--

In plain PHP it would be converted to Array( [key0] => Array ( [key1] => Array ( [key2] => value) ) ), while in Bref it would be converted to Array( [key0] => Array ( [key1] => Array ( [key2] => ) ) [key0[key1][key2][] => value ).

Impact

Based on the application logic the difference in the body parsing might lead to vulnerabilities and/or undefined behaviors.

PoC

  1. Create a new Bref project.
  2. Create an index.php file with the following content:
<?php namespace App; require __DIR__ . '/vendor/autoload.php'; use Nyholm\Psr7\Response; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; class MyHttpHandler implements RequestHandlerInterface { public function handle(ServerRequestInterface $request): ResponseInterface { return new Response(200, [], var_export($request->getParsedBody(),true)); } } return new MyHttpHandler();
  1. Use the following serverless.yml to deploy the Lambda:
service: app provider: name: aws region: eu-central-1 plugins: - ./vendor/bref/bref # Exclude files from deployment package: patterns: - '!node_modules/**' - '!tests/**' functions: api: handler: index.php runtime: php-83 events: - httpApi: 'ANY /upload'
  1. Replay the following request after having replaced the <HOST> placeholder with the deployed Lambda domain:
POST /upload HTTP/2 Host: <HOST> Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryQqDeSZSSvmn2rfjb Content-Length: 180 ------WebKitFormBoundaryQqDeSZSSvmn2rfjb Content-Disposition: form-data; name="key0[key1][key2][" value ------WebKitFormBoundaryQqDeSZSSvmn2rfjb--
  1. Notice how the body has been parsed.
  2. Create a plain.php file with the following content:
<?php var_dump($_POST);
  1. Start a PHP server inside the project directory (e.g. php -S 127.0.0.1:8090).
  2. Replay the following request after having replaced the <HOST> placeholder with the PHP server address:
POST /plain.php HTTP/1.1 Host: <HOST> Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryQqDeSZSSvmn2rfjb Content-Length: 180 ------WebKitFormBoundaryQqDeSZSSvmn2rfjb Content-Disposition: form-data; name="key0[key1][key2][" value ------WebKitFormBoundaryQqDeSZSSvmn2rfjb--
  1. Notice the differences in the parsing compared to what observed at step 5.

Suggested Remediation

Use the PHP function parse_str to parse the body parameters to mimic the plain PHP behavior.

Пакеты

Наименование

bref/bref

composer
Затронутые версииВерсия исправления

< 2.1.13

2.1.13

EPSS

Процентиль: 45%
0.00227
Низкий

3.7 Low

CVSS3

Дефекты

CWE-436

Связанные уязвимости

CVSS3: 3.7
nvd
около 2 лет назад

Bref enable serverless PHP on AWS Lambda. When Bref is used with the Event-Driven Function runtime and the handler is a `RequestHandlerInterface`, then the Lambda event is converted to a PSR7 object. During the conversion process, if the request is a MultiPart, each part is parsed and its content added in the `$files` or `$parsedBody` arrays. The conversion process produces a different output compared to the one of plain PHP when keys ending with and open square bracket ([) are used. Based on the application logic the difference in the body parsing might lead to vulnerabilities and/or undefined behaviors. This vulnerability is patched in 2.1.13.

EPSS

Процентиль: 45%
0.00227
Низкий

3.7 Low

CVSS3

Дефекты

CWE-436