WordPress Media Upload PostScript Content Disguised As Image (Imagick/Ghostscript RCE) - STRICT
SIGMA detection rule by Adama ASSIONGBON (SOC & CTI Consultant), https://linkedin.com/in/adama-assiongbon-9029893a · Unknown
Detects the CVE-2026-65640 exploitation primitive: a file uploaded to a WordPress media endpoint whose filename claims a common image extension (png, jpg, jpeg, gif, webp, bmp) but whose actual content begins with a PostScript header ("%!"). WordPress trusts the filename extension to route the file to Imagick, which then reads the real content, recognizes PostScript, and hands it to Ghostscript for processing. No valid image file of any of these formats can begin with "%!": PNG requires a fixed 8-byte magic signature, JPEG requires 0xFFD8, GIF requires "GIF8x", so this combination has no legitimate origin. The rule is not anchored to the "async-upload" field name used by the classic media uploader, since the REST API media endpoint and other upload flows use different multipart field names for the same underlying primitive. The multipart branch tolerates any number of additional header lines between Content-Disposition and the blank-line separator, not only an optional Content-Type line, since a crafted request can pad extra headers to break a narrower pattern without affecting how PHP parses the field. A second branch covers the REST API's raw-body upload mode, where the file content is the entire request body with no multipart wrapping at all and the filename travels in an HTTP header outside RequestBody: any POST to a media endpoint whose body starts with "%!" has no legitimate origin regardless of wrapping. SOC L1 should verify the source, affected host, user, process or request fields, timing, and related activity.
Detecte la primitive d'exploitation de CVE-2026-65640 : un fichier uploade vers un endpoint media WordPress dont le nom de fichier revendique une extension d'image courante (png, jpg, jpeg, gif, webp, bmp) mais dont le contenu reel commence par un en-tete PostScript ("%!"). WordPress fait confiance a l'extension du nom de fichier pour router le fichier vers Imagick, qui lit ensuite le contenu reel, reconnait du PostScript, et le transmet a Ghostscript pour traitement. Aucun fichier image valide dans ces formats ne peut commencer par "%!" : PNG exige une signature magique fixe de 8 octets, JPEG exige 0xFFD8, GIF exige "GIF8x", cette combinaison n'a donc aucune origine legitime. La regle n'est pas ancree au nom de champ "async-upload" utilise par l'uploader classique, car l'endpoint REST media et d'autres flux d'upload utilisent des noms de champ multipart differents pour la meme primitive. La branche multipart tolere un nombre quelconque de lignes d'en-tete supplementaires entre Content-Disposition et la ligne vide, pas seulement une ligne Content-Type optionnelle, car une requete forgee peut ajouter des en-tetes de remplissage pour casser un motif plus etroit sans affecter la maniere dont PHP analyse le champ. Une deuxieme branche couvre le mode d'upload en corps brut de l'API REST, ou le contenu du fichier constitue l'integralite du corps de requete sans encapsulation multipart et ou le nom de fichier voyage dans un en-tete HTTP hors de RequestBody : tout POST vers un endpoint media dont le corps commence par "%!" n'a aucune origine legitime quel que soit l'encapsulage. Le SOC L1 doit vérifier la source, l’hôte affecté, l’utilisateur, les champs de processus ou de requête, la chronologie et les activités associées.
title: WordPress Media Upload PostScript Content Disguised As Image (Imagick/Ghostscript RCE) - STRICT
id: ef153a8d-c9d6-472c-b9c3-78e9ef3cff12
status: experimental
description: |
Detects the CVE-2026-65640 exploitation primitive: a file uploaded to a WordPress media endpoint whose filename claims a common image extension (png, jpg, jpeg, gif, webp, bmp) but whose actual content begins with a PostScript header ("%!"). WordPress trusts the filename extension to route the file to Imagick, which then reads the real content, recognizes PostScript, and hands it to Ghostscript for processing. No valid image file of any of these formats can begin with "%!": PNG requires a fixed 8-byte magic signature, JPEG requires 0xFFD8, GIF requires "GIF8x", so this combination has no legitimate origin. The rule is not anchored to the "async-upload" field name used by the classic media uploader, since the REST API media endpoint and other upload flows use different multipart field names for the same underlying primitive. The multipart branch tolerates any number of additional header lines between Content-Disposition and the blank-line separator, not only an optional Content-Type line, since a crafted request can pad extra headers to break a narrower pattern without affecting how PHP parses the field. A second branch covers the REST API's raw-body upload mode, where the file content is the entire request body with no multipart wrapping at all and the filename travels in an HTTP header outside RequestBody: any POST to a media endpoint whose body starts with "%!" has no legitimate origin regardless of wrapping. SOC L1 should verify the source, affected host, user, process or request fields, timing, and related activity.
Detecte la primitive d'exploitation de CVE-2026-65640 : un fichier uploade vers un endpoint media WordPress dont le nom de fichier revendique une extension d'image courante (png, jpg, jpeg, gif, webp, bmp) mais dont le contenu reel commence par un en-tete PostScript ("%!"). WordPress fait confiance a l'extension du nom de fichier pour router le fichier vers Imagick, qui lit ensuite le contenu reel, reconnait du PostScript, et le transmet a Ghostscript pour traitement. Aucun fichier image valide dans ces formats ne peut commencer par "%!" : PNG exige une signature magique fixe de 8 octets, JPEG exige 0xFFD8, GIF exige "GIF8x", cette combinaison n'a donc aucune origine legitime. La regle n'est pas ancree au nom de champ "async-upload" utilise par l'uploader classique, car l'endpoint REST media et d'autres flux d'upload utilisent des noms de champ multipart differents pour la meme primitive. La branche multipart tolere un nombre quelconque de lignes d'en-tete supplementaires entre Content-Disposition et la ligne vide, pas seulement une ligne Content-Type optionnelle, car une requete forgee peut ajouter des en-tetes de remplissage pour casser un motif plus etroit sans affecter la maniere dont PHP analyse le champ. Une deuxieme branche couvre le mode d'upload en corps brut de l'API REST, ou le contenu du fichier constitue l'integralite du corps de requete sans encapsulation multipart et ou le nom de fichier voyage dans un en-tete HTTP hors de RequestBody : tout POST vers un endpoint media dont le corps commence par "%!" n'a aucune origine legitime quel que soit l'encapsulage. Le SOC L1 doit vérifier la source, l’hôte affecté, l’utilisateur, les champs de processus ou de requête, la chronologie et les activités associées.
references:
- https://www.cve.org/CVERecord?id=CVE-2026-65640
- https://nvd.nist.gov/vuln/detail/CVE-2026-65640
- https://wordpress.org/news/2026/08/wordpress-7-0-4-release/
- https://www.securityweek.com/wordpress-7-0-4-patches-remote-code-execution-vulnerability/
- https://cybersecuritynews.com/wordpress-imagick-rce-vulnerability/
author: Adama ASSIONGBON (SOC & CTI Consultant), https://linkedin.com/in/adama-assiongbon-9029893a
date: 2026-08-14
related:
- id: 37dbb2fa-b95a-4322-bcc0-3c14fbc3e412
type: derived
- id: 4bc5899c-59fa-4d9d-b32a-6447436078e7
type: derived
- id: 94b4dcf3-8f11-4c2d-8132-40743026958a
type: derived
tags:
- attack.initial-access
- attack.execution
- attack.t1190
- cve.2026-65640
logsource:
category: webserver
definition: >
Web server, WAF or reverse-proxy access logs with request body inspection on WordPress
media upload endpoints. Expected fields: Url, HttpMethod, RequestBody. Field names vary by
log source; adapt RequestBody to the local pipeline (e.g. http.request.body.content,
post_data). Only usable if the log pipeline captures multipart file upload bodies, which
many WAF/proxy configurations exclude by default for size reasons.
detection:
selection_endpoint:
Url|contains:
- 'async-upload.php'
- 'media-new.php'
- '/wp-json/wp/v2/media'
- '/wp/v2/media'
selection_method:
HttpMethod: POST
selection_postscript_disguised_image:
RequestBody|re: '(?i)filename="[^"\n]*\.(png|jpe?g|gif|webp|bmp)"[^\n]*\n([^\n]+\n)*?\s*\n%!'
# Covers the REST API raw-body upload mode: no multipart wrapping, the file content is the
# entire body, filename travels in an HTTP header outside RequestBody.
selection_postscript_raw_body:
RequestBody|startswith: '%!'
condition: >
selection_endpoint and selection_method and
(selection_postscript_disguised_image or selection_postscript_raw_body)
fields:
- SourceIp
- DestinationIp
- DestinationPort
- HttpMethod
- Url
- RequestBody
- UserAgent
- StatusCode
falsepositives:
- None identified for the multipart branch (selection_postscript_disguised_image). A file whose extension claims a raster image format can never legitimately begin with a PostScript header; any occurrence has no benign origin.
- The raw-body branch (selection_postscript_raw_body) cannot see the declared filename, which travels in an HTTP header outside RequestBody for this upload mode, so it cannot distinguish a malicious image-disguised upload from a legitimate raw-body EPS/PostScript upload on sites that intentionally support this content type through the media endpoint. If such a workflow is confirmed legitimate in the environment, tune by excluding it at the SIEM level rather than removing the branch, since removing it reopens the raw-body evasion entirely.
- Log pipelines that do not capture RequestBody for media upload endpoints, or that truncate/exclude binary multipart bodies, will silently miss this rule; verify body capture is enabled before relying on it as the sole detection for this CVE.
level: high