
CakePHP 5.4.2 - Alta - Remoto - CRLF - Content-Type de anexo e Content-ID remanescente
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-attachment-crlf
Write-up: https://abraxaslabs.tech/research/cakephp-attachment-crlf
Classe: injeção de cabeçalho de parte MIME Alcance: Remoto
CakePHP 5.4.2 (887b641) - Cake Software Foundation
A versão 5.4.2 já remove ", \r e \n de name= / filename= em multipart (FormDataPart::_headerParameterToString). Esse é o controle. Content-Type e Content-ID foram deixados como concatenação bruta. Message::setAttachments copia o tipo de mídia de cliente de um UploadedFile para esse campo de tipo sem filtro adicional.
Um app que anexa um upload de usuário, ou que passa um contentId de usuário, coloca esses bytes na parte MIME. getBodyString() então exibe uma segunda linha de cabeçalho sob essa parte.
| ID | sem CVE ainda |
| Classe | injeção de cabeçalho de parte MIME |
| Alcance | Remoto (app que anexa um upload de usuário ou um contentId de usuário) |
| CWE | CWE-93 |
| CVSS | Médio: 5.4 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N |
| Produto | CakePHP |
| Afetado | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| Autenticação | aplicação que anexa um upload de usuário (MIME de cliente de UploadedFile) ou um contentId de usuário |
| Licença | GNU Affero GPL v3.0 |
| Lab | apenas 127.0.0.1 |
Alguém capaz de influenciar metadados de anexo que o app passa para Message::setAttachments / addAttachment pode injetar cabeçalhos de parte MIME.
| Privilégio | Método / sink | Tipo | Comprovado em lab ou inferido |
|---|---|---|---|
Linha extra de cabeçalho Content-Type | setAttachments com 'mimetype' => "text/plain\\r\\nX-Injected: …" | Integridade dos cabeçalhos da parte MIME | Comprovado em lab. Linha testemunha presente |
Linha extra de cabeçalho Content-ID | 'contentId' => "cid@…>\\r\\nX-Injected: …" (parte inline) | Integridade dos cabeçalhos da parte MIME | Comprovado em lab. Linha testemunha presente |
| Mesma injeção via MIME de upload | UploadedFile::getClientMediaType() copiado para mimetype | Integridade dos cabeçalhos da parte MIME | Comprovado em lab. Linha testemunha presente |
CRLF em filename= | nome do anexo com CR/LF | Fechado | Comprovado fechado em lab. A remoção da 5.4.2 se mantém |
RCPT de envelope / Bcc via este sink | cabeçalhos de parte MIME no corpo | Fechado | É a remoção apenas de par do SmtpTransport, um caso irmão |
| Envio SMTP | o lab chama apenas getBodyString() | Fechado | Sem transporte, sem shell |
Inferido da mesma concatenação, não demonstrado: um tipo ou contentId forjado que inclua um boundary multipart poderia dividir a mensagem em partes extras em um MUA receptor. Não enviei e-mail.
Sobras do mesmo pin: window SQLi, collate SQLi, cache unserialize.
Fixe o pin em cakephp/cakephp 5.4.2 após a nota do bakery de que a injeção em filename= do Content-Disposition multipart havia sido corrigida. _headerParameterToString é o sanitizador:
$transliterated = Text::transliterate(str_replace(['"', "\r", "\n"], '', $value));
__toString() ainda faz:
if ($this->type) {
$out .= 'Content-Type: ' . $this->type . "\r\n";
}
if ($this->contentId) {
$out .= 'Content-ID: <' . $this->contentId . ">\r\n";
}
Message::setAttachments copia o tipo de cliente de upload sem remoção. attachFiles / attachInlineFiles então chamam $part->type($fileInfo['mimetype']) e $part->contentId($fileInfo['contentId']).
Caminhos errados já registrados: tratar o RCPT do envelope como este resíduo (a linha extra está no corpo); afirmar que filename= ainda injeta (não injeta); enviar SMTP; um reverse shell. Teatro.
python3 cakephp-attachment-crlf-Abraxas-Labs.py
ou
cd lab
./run.sh
Aponte apenas para http://127.0.0.1:19460. PHP 8.3, CakePHP tag 5.4.2 clonado na build. lab_server.php expõe Message::setAttachments. Quatro casos: controle de filename, mimetype, contentId, tipo de mídia do 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
Passe type, contentId e transferEncoding pela mesma remoção de " / \r / \n aplicada em _headerParameterToString. Rejeite o valor se ele ainda contiver uma quebra de linha após a remoção. Cubra o MIME do cliente UploadedFile e o mimetype / contentId explícitos nos testes do mailer, não apenas filename=.
887b641de9f7aba06071f98f17edcbc573cbcf63)FormDataPart.php · Message.phpfilename= na bakery 5.4.2GNU Affero GPL v3.0. Consulte LICENSE. Apenas laboratório em loopback. Sem garantias.