
CakePHP 5.4.2 — высокий — удалённый — CRLF — вложение Content-Type и остаток Content-ID
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-attachment-crlf
Разбор: https://abraxaslabs.tech/research/cakephp-attachment-crlf
Класс: инъекция заголовков MIME-части Доступ: удалённый
CakePHP 5.4.2 (887b641) — Cake Software Foundation
5.4.2 уже удаляет ", \r и \n из multipart name= / filename= (FormDataPart::_headerParameterToString). Это и есть защита. Content-Type и Content-ID остались простой конкатенацией. Message::setAttachments копирует клиентский media type из UploadedFile в это поле типа без дополнительной фильтрации.
Приложение, которое прикрепляет пользовательскую загрузку или передаёт пользовательский contentId, помещает эти байты в MIME-часть. Затем getBodyString() показывает вторую строку заголовка под этой частью.
| ID | CVE пока нет |
| Класс | инъекция заголовков MIME-части |
| Доступ | удалённый (приложение, прикрепляющее пользовательскую загрузку или пользовательский contentId) |
| CWE | CWE-93 |
| CVSS | Средний: 5.4 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N |
| Продукт | CakePHP |
| Затронуто | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| Аутентификация | приложение, прикрепляющее пользовательскую загрузку (клиентский MIME из UploadedFile) или пользовательский contentId |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1 |
Тот, кто может влиять на метаданные вложения, которые приложение передаёт в Message::setAttachments / addAttachment, может внедрять заголовки MIME-части.
| Привилегия | Метод / точка сброса | Тип | Доказано в лаборатории или выведено |
|---|---|---|---|
Дополнительная строка заголовка Content-Type | setAttachments с 'mimetype' => "text/plain\\r\\nX-Injected: …" | Целостность заголовков MIME-части | Доказано в лаборатории. Строка-свидетель присутствует |
Дополнительная строка заголовка Content-ID | 'contentId' => "cid@…>\\r\\nX-Injected: …" (inline-часть) | Целостность заголовков MIME-части | Доказано в лаборатории. Строка-свидетель присутствует |
| Та же инъекция через MIME загрузки | UploadedFile::getClientMediaType(), скопированный в mimetype | Целостность заголовков MIME-части | Доказано в лаборатории. Строка-свидетель присутствует |
CRLF в filename= | имя вложения с CR/LF | Закрыто | Доказано в лаборатории, что закрыто. Защита 5.4.2 работает |
RCPT конверта / Bcc через эту точку сброса | заголовки MIME-части в теле | Закрыто | Это парная очистка только в SmtpTransport, смежный случай |
| Отправка по SMTP | лаборатория вызывает только getBodyString() | Закрыто | Без транспорта, без оболочки |
Выведено из той же конкатенации, но не продемонстрировано: специально сформированные type или contentId, включающие multipart boundary, могли бы разделить сообщение на дополнительные части в принимающем MUA. Я не отправлял почту.
Остатки того же пина: window SQLi, collate SQLi, cache unserialize.
Я зафиксировал cakephp/cakephp 5.4.2 после заметки bakery о том, что инъекция в multipart Content-Disposition filename= исправлена. _headerParameterToString — это санитайзер:
$transliterated = Text::transliterate(str_replace(['"', "\r", "\n"], '', $value));
__toString() по-прежнему выполняет:
if ($this->type) {
$out .= 'Content-Type: ' . $this->type . "\r\n";
}
if ($this->contentId) {
$out .= 'Content-ID: <' . $this->contentId . ">\r\n";
}
Message::setAttachments копирует тип клиента загрузки без очистки. Затем attachFiles / attachInlineFiles вызывают $part->type($fileInfo['mimetype']) и $part->contentId($fileInfo['contentId']).
Уже зафиксированные неверные повороты: трактовка конверта RCPT как этого остатка (лишняя строка находится в теле); утверждение, что filename= всё ещё внедряется (это не так); отправка SMTP; обратная оболочка. Театр.
python3 cakephp-attachment-crlf-Abraxas-Labs.py
или
cd lab
./run.sh
Цель — только http://127.0.0.1:19460. PHP 8.3, CakePHP tag 5.4.2 клонируется при сборке. lab_server.php предоставляет Message::setAttachments. Четыре случая: управление именем файла, mimetype, contentId, медиатип UploadedFile.
SUCCESS cakephp-attachment-crlf how=live pin=5.4.2 sha=887b641de9f7aba06071f98f17edcbc573cbcf63 mimetype=yes contentId=yes upload=yes filename-stripped=yes CAKEPHP-ATTACHMENT-CRLF-WITNESS
Пропустите type, contentId и transferEncoding через ту же очистку от " / \r / \n, что и _headerParameterToString. Отклоните значение, если после очистки в нём всё ещё остаётся разрыв строки. Покройте MIME клиента UploadedFile и явные mimetype / contentId в тестах почтовой рассылки, а не только filename=.
887b641de9f7aba06071f98f17edcbc573cbcf63)FormDataPart.php · Message.phpfilename= в 5.4.2 bakeryGNU Affero GPL v3.0. См. LICENSE. Только для лаборатории с loopback. Без гарантий.