
CakePHP 5.4.2 - Élevé - À distance - CRLF - Content-Type de pièce jointe et résidu de Content-ID
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-attachment-crlf
Write-up : https://abraxaslabs.tech/research/cakephp-attachment-crlf
Classe : injection d'en-tête de partie MIME Portée : distante
CakePHP 5.4.2 (887b641) - Cake Software Foundation
La version 5.4.2 supprime déjà ", \r et \n des champs multipart name= / filename= (FormDataPart::_headerParameterToString). C'est le contrôle. Content-Type et Content-ID ont été laissés en concaténation brute. Message::setAttachments copie le type média client d'un UploadedFile dans ce champ de type sans filtre supplémentaire.
Une application qui attache un fichier téléversé par l'utilisateur, ou qui transmet un contentId fourni par l'utilisateur, place ces octets sur la partie MIME. getBodyString() affiche alors une seconde ligne d'en-tête sous cette partie.
| ID | pas encore de CVE |
| Classe | injection d'en-tête de partie MIME |
| Portée | distante (application qui attache un fichier téléversé par l'utilisateur ou un contentId fourni par l'utilisateur) |
| CWE | CWE-93 |
| CVSS | Moyenne : 5.4 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N |
| Produit | CakePHP |
| Affecté | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| Auth | application qui attache un fichier téléversé par l'utilisateur (MIME client UploadedFile) ou un contentId fourni par l'utilisateur |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Une personne capable d'influencer les métadonnées de pièce jointe que l'application transmet à Message::setAttachments / addAttachment peut injecter des en-têtes de partie MIME.
| Privilège | Méthode / sink | Type | Prouvé en labo ou déduit |
|---|---|---|---|
Ligne d'en-tête Content-Type supplémentaire | setAttachments avec 'mimetype' => "text/plain\\r\\nX-Injected: …" | Intégrité des en-têtes de partie MIME | Prouvé en labo. Ligne témoin présente |
Ligne d'en-tête Content-ID supplémentaire | 'contentId' => "cid@…>\\r\\nX-Injected: …" (partie inline) | Intégrité des en-têtes de partie MIME | Prouvé en labo. Ligne témoin présente |
| Même injection via le MIME du téléversement | UploadedFile::getClientMediaType() copié sur mimetype | Intégrité des en-têtes de partie MIME | Prouvé en labo. Ligne témoin présente |
CRLF dans filename= | nom de pièce jointe avec CR/LF | Fermé | Prouvé fermé en labo. Le filtrage de 5.4.2 tient |
RCPT d'enveloppe / Bcc via ce sink | en-têtes de partie MIME dans le corps | Fermé | Il s'agit du filtrage par paire de SmtpTransport, un cas voisin |
| Envoi SMTP | le labo appelle uniquement getBodyString() | Fermé | Aucun transport, aucun shell |
Déduit de la même concaténation, non démontré : un type ou un contentId forgé incluant une frontière multipart pourrait scinder le message en parties supplémentaires dans un MUA récepteur. Je n'ai pas envoyé de courriel.
Autres restes du même pin : window SQLi, collate SQLi, cache unserialize.
J'ai épinglé cakephp/cakephp 5.4.2 après la note de la bakery indiquant que l'injection multipart dans filename= de Content-Disposition était corrigée. _headerParameterToString est l'assainisseur :
$transliterated = Text::transliterate(str_replace(['"', "\r", "\n"], '', $value));
__toString() fait toujours :
if ($this->type) {
$out .= 'Content-Type: ' . $this->type . "\r\n";
}
if ($this->contentId) {
$out .= 'Content-ID: <' . $this->contentId . ">\r\n";
}
Message::setAttachments copie le type de client d'upload sans suppression. attachFiles / attachInlineFiles appellent ensuite $part->type($fileInfo['mimetype']) et $part->contentId($fileInfo['contentId']).
Fausses pistes déjà consignées : traiter l'enveloppe RCPT comme ce résidu (la ligne supplémentaire est dans le corps) ; prétendre que filename= injecte encore (ce n'est pas le cas) ; envoyer du SMTP ; un reverse shell. Du théâtre.
python3 cakephp-attachment-crlf-Abraxas-Labs.py
ou
cd lab
./run.sh
Ciblez uniquement http://127.0.0.1:19460. PHP 8.3, CakePHP tag 5.4.2 cloné au build. lab_server.php expose Message::setAttachments. Quatre cas : contrôle du nom de fichier, mimetype, contentId, type de média 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
Faites passer type, contentId et transferEncoding par le même nettoyage des caractères " / \r / \n que _headerParameterToString. Rejetez la valeur si elle contient encore un saut de ligne après le nettoyage. Couvrez le MIME client d'UploadedFile et les paramètres explicites mimetype / contentId dans les tests du mailer, pas seulement filename=.
887b641de9f7aba06071f98f17edcbc573cbcf63)FormDataPart.php · Message.phpfilename= dans la bakery 5.4.2GNU Affero GPL v3.0. Voir LICENSE. Laboratoire en boucle locale uniquement. Aucune garantie.