Drupal's security team has released patches for two critical vulnerabilities that allow remote code execution on websites running any supported version of the content management system — and, in an unusually blunt warning, told site operators that public exploitation is likely to emerge soon. That combination — a critical RCE in a widely deployed CMS plus an advance warning of imminent weaponization — is the exact signature of a 'patch now, verify twice' event. If your organization operates public-facing Drupal sites, treat this as a drop-everything remediation, not a next-maintenance-window item.
Drupal powers a substantial share of government, university, and enterprise websites globally. Historically, critical Drupal RCEs have been weaponized within hours to days of patch release — attackers routinely reverse-engineer the diff between patched and unpatched code to build working exploits. The Drupal security team's explicit warning that 'a security issue may emerge soon' should be read as: assume exploit code will be public before your next patch cycle completes.
What Happened
The Drupal project shipped security releases addressing two critical flaws that, combined or independently, can allow an attacker to execute arbitrary code on the underlying web server. Critically, the advisory states the issues affect all supported versions of Drupal core — meaning this is not a narrow, edge-case misconfiguration. Any supported branch of Drupal that has not applied the update is exposed.
The attack surface here is the classic CMS worst case: a remote, unauthenticated or minimally authenticated path to code execution on a server that typically holds database credentials, session data, and in many organizations, direct line-of-sight into internal networks. Once an RCE lands on a Drupal host, the standard attacker playbook follows immediately: drop a web shell, establish persistence, harvest the settings.php database credentials, and pivot.
Technical Analysis
Affected products and platforms: All supported versions of Drupal core prior to the security releases referenced in the official advisory. Operators should pull exact fixed version numbers from the advisory at drupal.org/security and map them against every Drupal instance in their estate — including forgotten microsites, marketing landing pages, and development/staging instances exposed to the internet.
How these flaws work (defender's view): Drupal core RCEs historically cluster around a few recurring patterns — unsafe deserialization in form or AJAX handlers, injection through render arrays, or improper input sanitization in contributed-API-adjacent core components. Regardless of the precise code path, the observable outcome of successful exploitation is consistent and highly detectable:
- The web server process (Apache, nginx + PHP-FPM) spawns an unexpected child process — a shell, a network tool (
curl,wget), or a reconnaissance binary (id,whoami,uname). - New or modified executable PHP files appear in writable directories such as
sites/default/files/,sites/default/files/php/,modules/, orthemes/— the classic web shell drop. - Anomalous HTTP requests hit unusual core paths (form/AJAX endpoints,
admin/-prefixed routes from unauthenticated sources, or requests with serialized object payloads in POST bodies). - Outbound connections from the web tier to unfamiliar hosts for payload retrieval or C2.
Exploitation status: No public proof-of-concept is confirmed in the source reporting at time of writing — but Drupal's own security team is warning that exploits may emerge imminently. That warning is based on the mechanics of how these patches get reversed. Defenders should treat the exploitation window as already open and validate that their sites are not only patched but also uncompromised. Patch-first-then-investigate is a mistake here: if an attacker got in between advisory and patch, the patch does not evict them.
Detection & Response
The detections below target the behavioral outcome of successful exploitation — web server processes spawning shells, web shell deployment in Drupal directories, and suspicious request patterns. These remain valid regardless of the exact exploitation vector.
Sigma Rules
---
title: Web Server Process Spawning Shell or Reconnaissance Tools
description: Detects Apache, nginx, or PHP-FPM worker processes spawning shells, network utilities, or reconnaissance commands — a hallmark of successful CMS RCE exploitation such as the critical Drupal flaws. Web server workers should essentially never spawn interactive shells or download tools.
references:
- https://attack.mitre.org/techniques/T1190/
- https://attack.mitre.org/techniques/T1059/
- https://www.bleepingcomputer.com/news/security/drupal-patches-critical-rce-flaws-warns-exploits-may-emerge-soon/
author: Security Arsenal
date: 2026/01/15
status: experimental
logsource:
category: process_creation
product: linux
detection:
selection_parent:
ParentImage|endswith:
- '/apache2'
- '/httpd'
- '/php-fpm'
- '/nginx'
- '/php-cgi'
selection_child:
Image|endswith:
- '/sh'
- '/bash'
- '/dash'
- '/curl'
- '/wget'
- '/nc'
- '/ncat'
- '/python'
- '/python3'
- '/perl'
- '/id'
- '/whoami'
condition: selection_parent and selection_child
falsepositives:
- Drupal cron or Drush maintenance tasks executed through the web context (rare; tune by parent process path)
- Legitimate backup or cache-purge plugins invoking system utilities
level: high
---
title: Executable PHP File Created in Drupal Writable Directories
description: Detects creation of PHP files in Drupal upload and files directories, consistent with web shell deployment following exploitation of a Drupal RCE. The sites/default/files tree should never legitimately contain newly written PHP files.
references:
- https://attack.mitre.org/techniques/T1505/003/
- https://www.bleepingcomputer.com/news/security/drupal-patches-critical-rce-flaws-warns-exploits-may-emerge-soon/
author: Security Arsenal
date: 2026/01/15
status: experimental
logsource:
category: file_event
product: linux
detection:
selection_path:
TargetFilename|contains:
- '/sites/default/files/'
- '/files/php/'
- '/tmp/'
- '/var/tmp/'
selection_ext:
TargetFilename|endswith:
- '.php'
- '.phtml'
- '.phar'
- '.php5'
- '.inc'
condition: selection_path and selection_ext
falsepositives:
- Deployment pipelines writing compiled templates — filter by CI/CD service account and deployment windows
level: high
---
title: Suspicious Serialized Payload in Drupal Form or AJAX Request
description: Detects HTTP requests to Drupal form, AJAX, or admin endpoints containing PHP serialized object markers, indicative of object injection or deserialization exploitation attempts against Drupal core.
references:
- https://attack.mitre.org/techniques/T1190/
- https://www.bleepingcomputer.com/news/security/drupal-patches-critical-rce-flaws-warns-exploits-may-emerge-soon/
author: Security Arsenal
date: 2026/01/15
status: experimental
logsource:
category: webserver
detection:
selection_uri:
cs-uri|contains:
- '/?q=system/ajax'
- '/system/ajax'
- '/ajax/'
- '/user/password'
selection_payload:
cs-body|contains:
- 'O:'
- 'a:2:{'
- 'form_build_id='
condition: selection_uri and selection_payload
falsepositives:
- Legitimate Drupal AJAX form submissions — baseline normal form_build_id traffic before enabling alerting; treat serialized-object markers (O:<int>) as high-fidelity
level: medium
KQL (Microsoft Sentinel / Defender)
This hunt assumes web server Syslog/CEF ingestion into Sentinel — standard for Linux web tiers — and correlates suspicious child processes with recent web shell artifacts.
// Hunt 1: Web server workers spawning shells or download tools (post-RCE behavior)
Syslog
| where TimeGenerated > ago(14d)
| where Facility =~ 'auth' or Facility =~ 'daemon' or SyslogMessage has_any ('apache2', 'php-fpm', 'httpd')
| extend Parsed = SyslogMessage
| where Parsed has_any ('/bin/sh', '/bin/bash', 'curl ', 'wget ', 'whoami', 'id;', 'nc -')
| where Parsed has_any ('apache', 'php-fpm', 'www-data')
| project TimeGenerated, Computer, ProcessName, SyslogMessage
| order by TimeGenerated desc;
// Hunt 2: Network connections from web server processes to rare external destinations
DeviceNetworkEvents
| where TimeGenerated > ago(14d)
| where InitiatingProcessFileName in~ ('apache2', 'httpd', 'php-fpm', 'php-cgi', 'nginx')
| where RemotePort in (80, 443, 4444, 5555, 8080, 8443)
| where not(RemoteIP startswith '10.' or RemoteIP startswith '192.168.' or RemoteIP startswith '172.')
| summarize ConnectionCount = count(), DistinctDestinations = dcount(RemoteIP), Destinations = make_set(RemoteIP) by DeviceName, InitiatingProcessFileName
| where ConnectionCount > 50
| order by DistinctDestinations desc;
// Hunt 3: PHP files written to Drupal files directories (web shell staging)
CommonSecurityLog
| where TimeGenerated > ago(14d)
| where Message has_all ('sites/default/files', '.php')
| project TimeGenerated, SourceHostName, Message
| order by TimeGenerated desc
Velociraptor VQL
Use this artifact to sweep suspected Drupal hosts for recently created executable files in upload directories and anomalous web-tier child processes — the two highest-fidelity post-exploitation artifacts.
-- Hunt: Drupal post-exploitation sweep — web shells in files dirs and web-tier child processes
-- Targets artifacts consistent with exploitation of the critical Drupal RCE flaws
LET webroots <= SELECT FullPath FROM glob(globs=['/var/www/**/sites/default/files/*.php', '/var/www/**/sites/*/files/*.php', '/srv/www/**/sites/default/files/*.php'])
SELECT FullPath,
Mtime,
Ctime,
Size,
Mode
FROM webroots
WHERE Mtime > now() - (14 * 24 * 60 * 60)
ORDER BY Mtime DESC
-- Enumerate suspicious children of web server / PHP-FPM processes
SELECT Pid, PPid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE Username =~ 'www-data|apache|nginx'
AND CommandLine =~ '(?i)(/bin/(ba)?sh|curl|wget|nc |ncat|python|perl|whoami|base64)'
Remediation & Verification Script
The following Bash script checks the Drupal core version, flags PHP files in writable directories, lists recently modified files in the web root, and checks for rogue administrative users — run it on every Drupal host, before and after patching.
#!/bin/bash
# Drupal critical RCE — verification and triage script
# Run as root or with sudo on each Drupal web host
WEBROOT="/var/www/html" # adjust to your Drupal document root
REPORT="/tmp/drupal_triage_$(date +%Y%m%d_%H%M).txt"
echo "=== Drupal RCE Triage Report: $(hostname) — $(date) ===" | tee "$REPORT"
# 1) Report installed Drupal core version (requires drush on PATH)
echo -e "\n[+] Drupal core version:" | tee -a "$REPORT"
if command -v drush &>/dev/null; then
(cd "$WEBROOT" && sudo -u www-data drush status --field=drupal-version 2>/dev/null) | tee -a "$REPORT"
else
grep -m1 "const VERSION" "$WEBROOT/core/lib/Drupal.php" 2>/dev/null | tee -a "$REPORT"
fi
# 2) PHP files in writable upload directories — prime web shell indicator
echo -e "\n[+] PHP files found under files/ directories (should be NONE):" | tee -a "$REPORT"
find "$WEBROOT" -path '*/files/*' \( -name '*.php' -o -name '*.phtml' -o -name '*.phar' -o -name '*.inc' \) -mtime -30 -ls 2>/dev/null | tee -a "$REPORT"
# 3) Recently modified files across the webroot (last 14 days)
echo -e "\n[+] Files modified in webroot within last 14 days:" | tee -a "$REPORT"
find "$WEBROOT" -type f -name '*.php' -mtime -14 2>/dev/null | tee -a "$REPORT"
# 4) PHP files containing classic web shell primitives
echo -e "\n[+] Files containing dangerous function combinations:" | tee -a "$REPORT"
grep -rlE "(eval\s*\(|base64_decode\s*\(|shell_exec\s*\(|passthru\s*\(|assert\s*\()" "$WEBROOT" --include='*.php' 2>/dev/null | head -50 | tee -a "$REPORT"
# 5) Check .htaccess protections exist for files directories
echo -e "\n[+] Verifying .htaccess PHP execution blocks in files dirs:" | tee -a "$REPORT"
for d in $(find "$WEBROOT" -type d -name 'files' 2>/dev/null); do
if grep -qi 'SetHandler Drupal_Security_Do_Not_Remove' "$d/.htaccess" 2>/dev/null; then
echo "OK: $d/.htaccess blocks PHP execution" | tee -a "$REPORT"
else
echo "WARNING: $d/.htaccess missing or weakened — PHP may execute here!" | tee -a "$REPORT"
fi
done
# 6) List web server child processes running right now
echo -e "\n[+] Current child processes of web server workers:" | tee -a "$REPORT"
ps --ppid $(pgrep -d, -f 'apache2|httpd|php-fpm' 2>/dev/null) -o pid,ppid,user,cmd 2>/dev/null | tee -a "$REPORT"
echo -e "\n=== Triage complete. Investigate any findings BEFORE patching; preserve evidence if compromise is suspected. ===" | tee -a "$REPORT"
Remediation
-
Patch immediately. Apply the Drupal core security releases from the official advisory at drupal.org/security. Because the flaws affect all supported versions, there is no 'we're on an unaffected branch' opt-out — every supported branch received a corresponding fixed release. Verify your exact target version against the advisory before updating, and confirm the applied version post-patch with
drush status. -
Assume compromise if you patch late. Once public exploit code lands (which Drupal itself is warning about), internet-facing unpatched sites will be scanned and hit within hours. If your patching lagged the advisory by more than a few days, run the triage script above, review web access logs for anomalous POSTs to AJAX/form endpoints, and check the Drupal
userstable for rogue administrator accounts:drush sqlq "SELECT uid, name, mail, created FROM users WHERE uid IN (SELECT entity_id FROM user__roles WHERE roles_target_id='administrator');". -
Enforce the files-directory PHP execution block. Drupal ships
.htaccessfiles undersites/default/files/that block PHP execution. Attackers frequently delete or overwrite these. If you're on nginx,.htaccessis ignored — you must enforce the equivalent at the server level:location ~* ^/sites/.*/files/.*\.php { deny all; }. Validate this today; it neuters the most common web shell deployment pattern even if exploitation succeeds. -
Reduce exposed surface. Ensure
/core/install.phpand update scripts are blocked at the web server or WAF layer, restrictadmin/paths to authenticated internal ranges where feasible, and confirm your WAF (ModSecurity with the OWASP Core Rule Set at minimum) is in blocking mode, not detection-only. -
Rotate credentials if compromise is confirmed. The database password in
settings.php, any service account credentials stored in Drupal configuration, and — critically — any credentials that were reachable from the web host must be rotated. An RCE on the web tier means every secret that host could read is burned. -
Inventory your estate. Critical Drupal advisories have a nasty habit of surfacing forgotten marketing microsites and abandoned staging instances. Run external attack surface discovery against your domains and certificate transparency logs now, not after the exploit drops.
The Bigger Lesson
Drupal's pre-emptive warning about imminent exploitation is a gift most vendors never give you. The exploit window for critical CMS RCEs is measured in hours after patch release because the patch itself is the roadmap — a trivial diff tells a skilled attacker exactly where the bug lives. Organizations that treat CMS patching as a monthly-cycle activity will lose this race every time. If Drupal is business-critical to you, your change management process needs a defined emergency patch lane with pre-authorized approval for exactly this scenario.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.