Cookie-Controlled PHP Web Shells: Stealth Tradecraft on Linux Hosts
Detection stack
- AIDR
- Alert
- ETL
- Query
Summary
Threat actors are abusing HTTP cookies as a covert “activation key” for PHP web shells on Linux hosting servers. The implants remain inert until a specific cookie value is supplied, then decode and execute attacker-provided payloads. This approach helps reduce obvious indicators in routine logs while enabling persistent remote code execution. Common supporting tradecraft includes layered obfuscation, cron-based self-healing, and living-off-the-land use of standard server utilities.
Investigation
Researchers reviewed multiple compromised hosting accounts and found PHP loaders that only reconstruct capability from Base64-encoded blobs when the trigger cookie is present. Persistence was maintained through cron jobs created via hosting control panels (such as cPanel) that periodically restore the web shell if it is removed. Execution commonly flowed through php-fpm and other web workers, which spawned shell interpreters and fetched secondary payloads to extend access.
Mitigation
Require MFA for hosting control panels and administrative access paths. Constrain web-server processes so they cannot spawn shells or invoke common staging utilities like base64, curl, or wget. Monitor cron creation and modifications closely, and alert on unexpected file writes or changes within web directories. Additional hardening includes restricting jail shell access and enabling real-time endpoint protections on Linux servers.
Response
If identified, isolate the host, disable and remove malicious cron entries, delete suspicious PHP artifacts, and rotate credentials for affected hosting accounts. Preserve and review evidence, including trigger cookie values and associated command lines, then apply hardening controls to prevent re-deployment and repeat compromise.
"graph TB %% Class Definitions classDef action fill:#99ccff classDef tool fill:#ffcc99 classDef process fill:#ffeb99 classDef builtin fill:#cccccc %% Action Nodes step1_initial_access["<b>Technique</b> – T1190 Exploit Public Facing Application<br/><b>Description</b>: Vulnerability in a webu2011facing application is leveraged to upload a malicious PHP file and gain initial foothold."] class step1_initial_access action step2_persistence_webshell["<b>Technique</b> – T1505.003 Server Software Component: Web Shell<br/><b>Description</b>: The uploaded PHP file acts as a web shell providing persistent remote access."] class step2_persistence_webshell action step3_def_evasion_obfuscation["<b>Technique</b> – T1027.008 Obfuscated Files or Information: Stripped Payloads<br/><b>Description</b>: Loader code is packed and stripped to hide its true functionality."] class step3_def_evasion_obfuscation action step3b_def_evasion_api["<b>Technique</b> – T1027.007 Dynamic API Resolution<br/><b>Description</b>: Function names are reconstructed at runtime to avoid static detection."] class step3b_def_evasion_api action step4_decode["<b>Technique</b> – T1140 Deobfuscate/Decode Files or Information<br/><b>Description</b>: Base64 blobs are decoded on the server to recreate the malicious payload."] class step4_decode action step5_unix_shell["<b>Technique</b> – T1059.004 Command and Scripting Interpreter: Unix Shell<br/><b>Description</b>: The web shell spawns /bin/sh or bash to execute attacker supplied commands."] class step5_unix_shell action step6_cookie_cred["<b>Technique</b> – Credential Access via Cookie<br/><b>Description</b>: Execution is gated by specific $_COOKIE values, allowing the attacker to control when code runs."] class step6_cookie_cred action step7_permission_mod["<b>Technique</b> – T1222.002 Linux and Mac File and Directory Permissions Modification<br/><b>Description</b>: Created PHP files are given permissive modes to remain executable and resistant to removal."] class step7_permission_mod action step8_ingress_transfer["<b>Technique</b> – T1105 Ingress Tool Transfer<br/><b>Description</b>: curl or wget downloads additional tools or secondu2011stage payloads into the web root."] class step8_ingress_transfer action step9_persistence_cron["<b>Technique</b> – T1053.003 Scheduled Task/Job: Cron<br/><b>Description</b>: A useru2011level cron job periodically recreates the obfuscated loader, ensuring a selfu2011healing foothold."] class step9_persistence_cron action step10_def_evasion_cont["<b>Technique</b> – Continued Obfuscation and Limited Visibility<br/><b>Description</b>: Malicious activity is hidden behind normal web traffic and only triggers on correct cookie, reducing log evidence."] class step10_def_evasion_cont action %% Tool / Process Nodes tool_php["<b>Tool</b> – PHP Interpreter"] class tool_php tool tool_curl_wget["<b>Tool</b> – curl / wget"] class tool_curl_wget tool tool_cron["<b>Tool</b> – Cron Scheduler"] class tool_cron tool process_apache["<b>Process</b> – apache2 / phpu2011fpm"] class process_apache process %% Connections step1_initial_access –>|leads to| step2_persistence_webshell step2_persistence_webshell –>|enables| step3_def_evasion_obfuscation step3_def_evasion_obfuscation –>|uses| step3b_def_evasion_api step3b_def_evasion_api –>|prepares| step4_decode step4_decode –>|executes| step5_unix_shell step5_unix_shell –>|checks| step6_cookie_cred step6_cookie_cred –>|sets| step7_permission_mod step7_permission_mod –>|downloads via| tool_curl_wget tool_curl_wget –>|stores payload for| step8_ingress_transfer step8_ingress_transfer –>|triggers| step9_persistence_cron step9_persistence_cron –>|reinforces| step10_def_evasion_cont step10_def_evasion_cont –>|operates within| process_apache process_apache –>|runs| tool_php "
Attack Flow
Detections
Suspicious Shell via Web Server [Linux] (via process_creation)
View
Cron File Was Created (via file_event)
View
Possible Base64 Encoded Strings Manipulation (via cmdline)
View
Detection of Cookie-Controlled PHP Webshell Activity [Webserver]
View
Detection of Cookie-Controlled PHP Webshell Execution on Linux Servers [Linux File Event]
View
Detection of Cookie-Controlled PHP Webshell Execution [Linux Process Creation]
View
Simulation Execution
Prerequisite: The Telemetry & Baseline Pre‑flight Check must have passed.
Rationale: This section details the precise execution of the adversary technique (TTP) designed to trigger the detection rule. The commands and narrative MUST directly reflect the TTPs identified and aim to generate the exact telemetry expected by the detection logic. Abstract or unrelated examples will lead to misdiagnosis.
-
Attack Narrative & Commands:
An attacker who has already compromised the web server obtains a malicious PHP webshell (malicious.php). To activate it, the attacker issues an HTTP request that injects a crafted cookie. The web server’s PHP handler interprets the cookie and spawns a Bash process that executes the webshell file. For testing, we simulate the same effect locally by manually invoking Bash with a command line that includes “.php”. This produces the exact telemetry the Sigma rule monitors (shell interpreter + “.php” in the command line).- Create a dummy PHP webshell (no harmful code, just a harmless
phpinfo()for visibility). - Execute the webshell via Bash, embedding the
.phpfilename in the command line. - Verify that the process creation event appears in audit logs with the expected fields.
- Create a dummy PHP webshell (no harmful code, just a harmless
-
Regression Test Script:
#!/usr/bin/env bash set -euo pipefail # 1. Deploy a harmless PHP file (simulated webshell) WEBROOT="/tmp/webshell_test" mkdir -p "$WEBROOT" cat > "$WEBROOT/malicious.php" <<'EOF' <?php // Simulated webshell – safe payload echo "Webshell executed at " . date('c') . "n"; ?> EOF # 2. Trigger execution via a Bash interpreter (command line contains ".php") echo "[*] Executing webshell via Bash to generate detection telemetry..." /bin/bash -c "php $WEBROOT/malicious.php" # 3. Pause briefly to allow auditd to flush logs sleep 2 echo "[*] Simulation complete. Review SIEM for a match on:" echo " process.name in (bash, sh, dash, jailshell) AND process.command_line contains '.php'" -
Cleanup Commands:
#!/usr/bin/env bash set -euo pipefail WEBROOT="/tmp/webshell_test" echo "[*] Removing test webshell directory..." rm -rf "$WEBROOT" echo "[*] Cleanup complete."