
Drupal 11.4.8 - उच्च - रिमोट - अपलोड - CKEditor 5 इमेज अपलोड अभी भी FileIsImage को छोड़ देता है
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · drupal-ckeditor-fileisimage
Class: Unrestricted upload / stored XSS Reach: Remote
Drupal core 11.4.8 (61044508) - Drupal
SA-CORE-2026-009 ने JSON:API और REST image fields पर FileIsImage जोड़ा। CKEditor5ImageController::getImageUploadValidators अभी भी केवल FileExtension, FileSizeLimit, और FileImageDimensions लौटाता है। जब फ़ाइल एक वैध image नहीं होती, तो FileImageDimensions बिना किसी violation के लौट आता है। फ़ाइल नाम का extension ही बचा हुआ check है।
CKEditor 5 image upload वाले text format का एक user, x.png नाम की non-image bytes को /ckeditor5/upload-image/{editor} पर POST कर सकता है और 201 के साथ एक public files URL प्राप्त कर सकता है।
| ID | अभी तक कोई CVE नहीं |
| Class | Unrestricted upload / sniff किए जाने पर stored XSS |
| Reach | Remote (authenticated format user) |
| CWE | CWE-434, CWE-79 |
| CVSS | Medium: 5.4 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N |
| Product | Drupal core |
| Affected | 11.4.8 (61044508071749629aaf3380aa85971e94df9e84) |
| Auth | CKEditor 5 image upload वाले text format का authenticated user (basic_html / full_html on Standard) |
| License | GNU Affero GPL v3.0 |
| Lab | केवल 127.0.0.1 |
ऐसे account की आवश्यकता है जो ऐसे format का उपयोग कर सके जिसके editor में image_upload.status true हो। Standard पर यह basic_html और full_html हैं। बिना account वाला पूर्ण अजनबी इस route को hit नहीं कर सकता (_entity_access: editor.use के साथ CSRF)।
| Privilege | Method / sink | Kind | Lab-proven या inferred |
|---|---|---|---|
sites/default/files/inline-images/ के अंतर्गत public .png में non-image bytes लिखना | POST /ckeditor5/upload-image/{editor} multipart upload | integrity | Lab-proven। x.png ने 201 और url=/sites/default/files/inline-images/x.png लौटाया |
| उन bytes को public files URL पर वापस पढ़ना | JSON url का GET | recon | Lab-proven। 200, 49 bytes, body में DRUPAL-CKEDITOR-FILEISIMAGE-WITNESS था |
| यदि web server या browser फ़ाइल को HTML/JS के रूप में sniff करे तो visitor में stored XSS | वही public URL, Content-Type image नहीं | integrity (visitor origin) | Inferred। इस lab ने Apache MIME नहीं बदला। Drupal ने bytes store कर लिए। |
| उसी route से एक असली image upload करना | Control control.png 1x1 PNG | intended | Lab-proven। 201 |
इस leftover पर बंद: .php के माध्यम से PHP/RCE (lab-proven 422 FileExtension); unauthenticated upload; JSON:API/REST ImageItem (वे paths पहले से FileIsImage जोड़ते हैं); LPE; default image-extension allowlist पर एक shell।
2026 SA-CORE wave के बाद मैंने Drupal 11.4.8 pin किया। JSON:API पहले से ही missing constraint जोड़ता है:
if (\is_a($field_definition->getItemDefinition()->getClass(), ImageItem::class, TRUE) && !array_key_exists('FileIsImage', $validators)) {
$validators['FileIsImage'] = [];
}
REST FileUploadResource.php भी वही करता है। CKEditor 5 को filename + size + dimensions पर छोड़ दिया गया:
return [
'FileExtension' => [
'extensions' => implode(' ', $allowed_extensions),
],
'FileSizeLimit' => [
'fileLimit' => $max_filesize,
],
'FileImageDimensions' => [
'maxDimensions' => $max_dimensions,
],
];
जब फ़ाइल एक वैध image नहीं होती, तो FileImageDimensionsConstraintValidator बिना किसी violation के लौट आता है। Hub drupal:11.4 11.4.9 पर float हो गया; यह pin composer-exact drupal/recommended-project:11.4.8 है। 11.4.0 ने Standard से Article हटा दिया, इसलिए image install के बाद core/recipes/article_content_type लागू करता है ताकि /node/add/article CKEditor 5 लोड करे।
पहले से दर्ज गलत रास्ते: FileImageDimensions को MIME check मानना (यह एक वैध image पर dimensions है, और अन्यथा no-op); default allowlist पर PHP shell का दावा करना (.php 422 है); floating hub tag का उपयोग करना और 11.4.9 आते देखना। Theatre: एक reverse shell। Oracle नकली x.png पर 201 और उन्हीं bytes के x.php नाम पर 422 है।
उसी pin के leftovers: oEmbed second-hop SSRF।
python3 drupal-ckeditor-fileisimage-Abraxas-Labs.py
या
cd lab
./run.sh
लक्ष्य केवल http://127.0.0.1:19500। php:8.4-apache-trixie पर Live Drupal 11.4.8 Standard, SQLite।
SUCCESS drupal-ckeditor-fileisimage png-http=201 php-http=422 control-png-http=201 editor=basic_html stored-http=200 stored-has-witness=yes url=/sites/default/files/inline-images/x.png DRUPAL-CKEDITOR-FILEISIMAGE-WITNESS
CKEditor5ImageController::getImageUploadValidators में 'FileIsImage' => [] जोड़ें। FileExtension रखें ताकि .php 422 बना रहे। Media Library में image media types को generic FileItem के बजाय ImageItem का उपयोग करना चाहिए ताकि वे वही constraint inherit करें।
61044508071749629aaf3380aa85971e94df9e84)CKEditor5ImageController.phpGNU Affero GPL v3.0। देखें LICENSE। केवल Loopback lab। कोई warranty नहीं।