Mich0 Shell: A Turkish Operator's Unobfuscated PHP Webshell Hiding Behind Pixel-Perfect Fake 404 Pages for a Year
TL;DR: A custom PHP webshell disguised as fonts.php has been actively deployed across at least 10 web servers since March 2025, evading detection by serving server-aware fake 404 error pages that match nginx or Apache styling. The operator -- attributed with medium confidence to a Turkish individual via the hardcoded email servancan3131[@]gmail[.]com and the Turkish logout parameter cikis -- committed critical OPSEC failures by shipping the shell with zero obfuscation, a plaintext password, and a personal Gmail address baked into the source. Despite being trivially readable, only 25% of AV scanners detect it, and YOROI classifies it as a legitimate file.
Discovery
On 2026-02-28, a PHP webshell was uploaded to MalwareBazaar by the user AnonLabs, recovered from a compromised Japanese web server. The file, fonts.php, is a 27,054-byte plaintext PHP script with no encoding, packing, or encryption of any kind. This is unusual -- the vast majority of webshells in active circulation use at least one layer of obfuscation (base64, gzinflate, eval chains, or commercial packers). This one ships its entire capability set in readable PHP, which paradoxically helps it evade detection engines tuned to flag obfuscated code.
The shell does not match any known webshell family: not WSO, not b374k, not c99, not r57, not China Chopper, not Weevely, not P.A.S., not FilesMan, not SUPERSHELL. Based on the hardcoded handle and authentication password, we have designated this family "Mich0 Shell".
| Property | Value |
|---|---|
| SHA-256 | 1b315ddeac3883162a5d567b58b65cd47eb315aab6c59621d0047caad092ab8f |
| SHA-1 | cfd6bf31596a93a3b262bdc6323c4aabc4c8f320 |
| MD5 | 8a1c2c7c1f68fa2b5601333c9cae33c3 |
| File size | 27,054 bytes |
| Filename | fonts.php |
| Line endings | CRLF (Windows development environment) |
| First seen | 2025-03-31 (ReversingLabs) |
| Last observed | 2026-02-28 (MalwareBazaar upload) |
| Origin | Japan (JP) |
| MalwareBazaar downloads | 102 |
The Fake 404: Server-Aware Evasion That Actually Works
The shell's primary evasion mechanism is elegant in its simplicity. When an unauthenticated visitor -- crawler, scanner, or curious researcher -- accesses fonts.php, the shell does the following:
- Sets the HTTP response code to 404
- Reads
$_SERVER['SERVER_SOFTWARE']to determine if the server runs nginx or Apache - Renders a pixel-perfect fake error page matching the detected server's native 404 styling
- Embeds a hidden password input field using white-on-white CSS:
border:1px solid #fff; background-color:#fff - Calls
die()to prevent any further output
The result: search engines see a 404 and skip the page. Automated scanners checking for 200 OK responses miss it entirely. Security researchers casually browsing see a convincing error page with no visible interactive elements. Only the operator knows to click the blank area and type the password mich0 into the invisible input field.
This technique defeats three layers of detection simultaneously:
- HTTP status code scanners -- the response is genuinely a 404 at the protocol level
- Visual inspection -- the page looks identical to a real server error
- Content scanners -- the hidden input is invisible unless you read the source
Attack Chain
Initial Access Persistence Evasion Capability
| | | |
[Web server [fonts.php dropped [Fake 404 mimics [Command exec via
compromise via in web root or real server error shell_exec/exec/
unknown vector] fonts/ directory] page (nginx/Apache)] system/passthru]
| | | |
v v v v
[Attacker gains [Cookie persists 30 [Hidden password [Full file manager:
write access to days -- single auth input invisible to browse/upload/edit/
web directory] per month needed] casual visitors] delete/chmod/rename]
| |
v v
[mail() sends access [Credential harvesting,
notification to config theft, lateral
operator's Gmail] movement prep]
The initial access vector is unknown -- no exploitation artifacts were recovered. Given the victim profile (PHP web servers, likely CMS-based), probable vectors include vulnerable WordPress/Joomla installations, unpatched PHP applications, or compromised FTP/SSH credentials.
Authentication: Simple, Persistent, Unprotected
The authentication mechanism is minimalist to the point of recklessness.
| Feature | Detail |
|---|---|
| Password | mich0 (plaintext comparison) |
| Cookie name | mich0login |
| Cookie value | ok (static, never changes) |
| Cookie lifetime | 30 days |
| Cookie path | / (site-wide) |
| Logout | GET parameter cikis (Turkish: "exit") |
| Brute-force protection | None |
| IP restriction | None |
| Rate limiting | None |
The static cookie value ok means session hijacking is trivial -- anyone who sets mich0login=ok in their browser gains full access without knowing the password. The 30-day persistence means the operator only needs to authenticate once per month per compromised server.
Command Execution Engine
The run_command() function is the shell's most dangerous capability. It cascades through four PHP execution methods, testing each against the server's disable_functions configuration:
| Priority | Function | Output Method | Compatibility |
|---|---|---|---|
| 1 | shell_exec() | Returns string directly | Most common |
| 2 | exec() | Array output, joined with newlines | Widely available |
| 3 | system() | Output buffer capture | Fallback |
| 4 | passthru() | Output buffer capture | Last resort |
Each method is individually tested via ini_get('disable_functions') before invocation. This cascade design means the shell functions on hardened servers where some -- but not all -- execution functions are disabled. Only a complete lockdown of all four functions defeats it.
File Manager: Full CRUD via AJAX API
All file operations route through a custom HTTP header (X-P-AJAX-URL: 1) and use POST-based AJAX with an action parameter. The shell implements a complete filesystem CRUD interface:
| Action | Capability | PHP Functions |
|---|---|---|
run_command | Execute OS commands | shell_exec/exec/system/passthru |
get_directory | Browse directories | scandir(), is_dir(), filesize(), fileperms() |
upload_file | Upload files to server | move_uploaded_file() |
get_file_content | Read any file | file_get_contents() |
delete | Delete files/directories | unlink(), rmdir() |
chmod | Change permissions | chmod() with octdec() |
rename | Rename files/directories | rename() |
edit | Write content to files | fopen(), fwrite() |
The interface itself is built with TailwindCSS and jQuery 3.6.0, both loaded from CDN -- giving it a modern, professional appearance that looks more like a legitimate admin panel than a webshell. Permission color-coding (green for writable, blue for readable, red for inaccessible) provides at-a-glance situational awareness for the operator.
Operator Notification: A Primitive C2
Every authenticated access triggers a mail() call:
Subject: Access Notification
To: servancan3131@gmail.com
Body: Your management interface at [URL] was accessed by [IP].
This serves as a passive command-and-control mechanism. The operator receives real-time visibility into:
- Which shells are being accessed (and therefore which victims are still compromised)
- The exact URLs where shells are installed (reveals victim infrastructure)
- Who is accessing them (the operator's own IP, or potentially security researchers probing the shell)
The @ error suppression on mail() ensures silent failure if the server cannot send email -- no error messages leak to the browser.
Threat Actor Attribution
The OPSEC Failures
The operator made a series of decisions that, taken together, provide a medium-confidence attribution to a Turkish individual.
Evidence 1: The email servancan3131[@]gmail[.]com
"Servan" is a Turkish/Kurdish given name. "Can" is one of the most common Turkish surnames and middle names, meaning "soul" or "life." The pattern firstname+lastname+digits is standard for Turkish online handle construction. "3131" is a significant number in Turkish context -- 0312/0313 are Ankara area codes, and the sequence appears frequently in Turkish handles.
Evidence 2: The logout parameter cikis
This is the Turkish word for "exit" or "logout." It is not a transliteration, not a common programming term, and not an English word. It is a deliberate Turkish-language choice embedded in the code logic -- the kind of thing a developer does instinctively when naming a function in their native language.
Evidence 3: CRLF line endings
The shell was developed on a Windows machine. While not attribution-specific, this eliminates the possibility that the operator is working from a Linux server or mobile device.
Actor Profile
| Attribute | Assessment |
|---|---|
| Country | Turkey (medium confidence) |
| Motivation | Financial -- server access enables cryptomining, spam relay, data theft, phishing hosting, access sales |
| Sophistication | Intermediate -- clean code, proper error handling, modern UI, but catastrophic OPSEC |
| Actor type | Individual operator or small team, not an APT, not a known cybercrime group |
| Active since | At least March 2025 |
Full OPSEC Failure Matrix
| Failure | Impact |
|---|---|
| Personal Gmail hardcoded in source | Direct attribution to real identity |
Turkish-language parameter cikis | Confirms operator's native language |
| Zero code obfuscation | Every feature immediately visible to any analyst |
Hardcoded plaintext password mich0 | Trivially discoverable |
| No brute-force protection | Password crackable in seconds |
| No IP whitelisting | Any attacker who discovers the password gains access |
Static cookie value ok | Session hijacking without credentials |
| CDN dependencies (TailwindCSS, jQuery) | Panel non-functional offline; CDN logs could track access |
Vendor Detection: The Paradox of Plaintext
The detection landscape for this shell reveals a counterintuitive gap.
| Vendor | Detection | Assessment |
|---|---|---|
| Kaspersky | HEUR:Backdoor.PHP.WebShell.gen | Generic heuristic, 10 hits across ~1 year |
| ReversingLabs | Script-PHP.Trojan.Heuristic | 25% scanner match (6/24) |
| FileScan-IO | MALICIOUS (confidence 1.0) | Full confidence |
| Spamhaus HBL | Suspicious | Hash-based |
| YOROI YOMI | Legit File (score 0.00) | FALSE NEGATIVE -- missed entirely |
| ClamAV | Not detected | No signature |
Only 25% of scanners flag this file. YOROI YOMI classifies it as a legitimate file with a confidence score of 0.00. ClamAV has no signature at all. The irony: the lack of obfuscation actively hurts detection. Most AV engines are tuned to flag encoded, packed, or obfuscated PHP. A plaintext webshell with clean formatting and TailwindCSS imports looks, to heuristic engines, like a normal web application.
Activity Timeline
| Date | Event | Source |
|---|---|---|
| 2025-03-31 | First seen by ReversingLabs | MalwareBazaar vendor intel |
| 2025-05-31 | First Kaspersky detection | MalwareBazaar vendor intel |
| 2026-02-02 | Last Kaspersky observation | MalwareBazaar vendor intel |
| 2026-02-28 | Uploaded to MalwareBazaar by AnonLabs | MalwareBazaar |
| 2026-03-09 | This analysis | Breakglass Intelligence |
The gap between ReversingLabs' first observation (March 2025) and Kaspersky's first detection (May 2025) suggests a 2-month window where the shell was active with zero vendor coverage. Kaspersky's 10 hits over the following 9 months indicate steady, low-volume deployment -- consistent with an individual operator managing a modest portfolio of compromised servers rather than a spray-and-pray campaign.
MITRE ATT&CK Mapping
| Tactic | Technique | ID | Implementation |
|---|---|---|---|
| Persistence | Server Software Component: Web Shell | T1505.003 | fonts.php dropped on web server |
| Execution | Command and Scripting Interpreter: Unix Shell | T1059.004 | shell_exec/exec/system/passthru cascade |
| Defense Evasion | Masquerading: Match Legitimate Name | T1036.005 | Named "fonts.php" to blend with web assets |
| Defense Evasion | Indicator Removal: File Deletion | T1070.004 | Delete action in file manager |
| Command and Control | Application Layer Protocol: Web Protocols | T1071.001 | HTTP AJAX communication via custom header |
| Collection | Data from Local System | T1005 | File read capability (get_file_content) |
| Discovery | File and Directory Discovery | T1083 | Directory browser (get_directory) |
| Exfiltration | Exfiltration Over C2 Channel | T1041 | File content returned via HTTP response |
| Impact | Resource Hijacking | T1496 | Command exec enables cryptomining |
| Lateral Movement | Ingress Tool Transfer | T1105 | File upload capability |
| Defense Evasion | File and Directory Permissions Modification | T1222 | chmod capability |
Indicators of Compromise
File Indicators
SHA-256: 1b315ddeac3883162a5d567b58b65cd47eb315aab6c59621d0047caad092ab8f
SHA-1: cfd6bf31596a93a3b262bdc6323c4aabc4c8f320
MD5: 8a1c2c7c1f68fa2b5601333c9cae33c3
SSDEEP: 192:MnCRQg8UrJr5p7ZzDr4pV5aSzKmhRWYp4iQ/SKI6DX7mDoIf/Rv4enC4OBukiRw0:MsDVF7sp7vpdKI6DXjenPvkd089kW26q
TLSH: T196C28204B8C461B582B3B3B57B9BB81CF86A42AB930686007D8C56C65FB4D1497D3FF6
Network and Behavioral Indicators
HTTP Header: X-P-AJAX-URL: 1
Cookie: mich0login=ok
POST parameter: pass=mich0
POST parameter: action=run_command
POST parameter: action=get_directory
POST parameter: action=upload_file
POST parameter: action=get_file_content
GET parameter: cikis
Email: servancan3131[@]gmail[.]com
Email subject: Access Notification
HTML title: File Management System (authenticated)
HTML title: 404 Not Found (unauthenticated)
CDN: cdn[.]tailwindcss[.]com
CDN: code[.]jquery[.]com/jquery-3.6.0.min.js
Web Log Signature
A typical Mich0 Shell access sequence produces a distinctive pattern in server logs:
[timestamp] 1.2.3.4 - GET /fonts.php HTTP/1.1 404 [size] # Initial visit, fake 404
[timestamp] 1.2.3.4 - POST /fonts.php HTTP/1.1 302 [size] # Login with password
[timestamp] 1.2.3.4 - GET /fonts.php HTTP/1.1 200 [size] # Authenticated, panel loads
[timestamp] 1.2.3.4 - POST /fonts.php HTTP/1.1 200 [size] # AJAX file operations
The 404-to-302-to-200 transition for the same URI from the same IP within seconds is anomalous and should be flagged by log analysis tools.
Detection Opportunities
Filesystem Hunting
# Search for exact content signatures
grep -rl "mich0login" /var/www/ /home/*/public_html/ 2>/dev/null
grep -rl "X-P-AJAX-URL" /var/www/ /home/*/public_html/ 2>/dev/null
grep -rl "servancan3131" /var/www/ /home/*/public_html/ 2>/dev/null
# Search for fonts.php with execution functions
find /var/www/ -name "fonts.php" -exec grep -l "shell_exec\|passthru\|system(" {} \;
# Generic: PHP files with fake 404 + password form pattern
grep -rl "http_response_code(404)" /var/www/ 2>/dev/null | xargs grep -l "type=password"
Web Log Analysis
# POST requests to fonts.php (webshells are typically POST-heavy)
grep "POST.*fonts\.php" /var/log/nginx/access.log /var/log/apache2/access.log 2>/dev/null
# X-P-AJAX-URL header in logs (if custom header logging is enabled)
grep "X-P-AJAX-URL" /var/log/nginx/access.log 2>/dev/null
# The 404-to-200 transition anomaly
grep "fonts\.php" /var/log/nginx/access.log | grep -E "(404|200)"
PHP Hardening
; Disable all four execution functions to fully neutralize the shell
disable_functions = shell_exec,exec,system,passthru,popen,proc_open,pcntl_exec
YARA Rules
rule Webshell_Mich0_Exact : webshell backdoor php
{
meta:
description = "Detects the exact fonts.php webshell variant with mich0 authentication"
author = "Breakglass Intelligence"
date = "2026-03-09"
hash = "1b315ddeac3883162a5d567b58b65cd47eb315aab6c59621d0047caad092ab8f"
tlp = "WHITE"
severity = "critical"
strings:
$auth_cookie = "mich0login" ascii
$admin_email = "servancan3131@gmail.com" ascii
$ajax_header = "HTTP_X_P_AJAX_URL" ascii
$logout_turkish = "cikis" ascii
$pass_check = "pass" ascii
condition:
filesize < 100KB and all of them
}
rule Webshell_Mich0_Behavioral : webshell backdoor php
{
meta:
description = "Behavioral detection: fake 404 + file manager + command exec cascade"
author = "Breakglass Intelligence"
date = "2026-03-09"
severity = "high"
strings:
$fake404_code = "http_response_code(404)" ascii
$hidden_input = "type=password name=pass" ascii
$server_detect = "SERVER_SOFTWARE" ascii
$exec1 = "shell_exec" ascii
$exec2 = "passthru" ascii
$exec3 = "system(" ascii
$disable = "disable_functions" ascii
$ajax1 = "run_command" ascii
$ajax2 = "get_directory" ascii
$ajax3 = "upload_file" ascii
$ajax4 = "get_file_content" ascii
condition:
filesize < 100KB and
$fake404_code and $hidden_input and
2 of ($exec1, $exec2, $exec3) and $disable and
3 of ($ajax1, $ajax2, $ajax3, $ajax4)
}
rule Webshell_Fake404_Generic : webshell evasion php
{
meta:
description = "Generic: PHP files serving fake 404 with hidden auth forms"
author = "Breakglass Intelligence"
date = "2026-03-09"
severity = "high"
strings:
$http404 = "http_response_code(404)" ascii
$hidden_form = "type=password" ascii
$white_border = "border:1px solid #fff" ascii
$white_bg = "background-color:#fff" ascii
$server_sw = "SERVER_SOFTWARE" ascii
$die = "die(" ascii
condition:
filesize < 100KB and
$http404 and $hidden_form and
($white_border or $white_bg) and
$server_sw and $die
}
Suricata Rules
# Mich0 Shell -- Custom AJAX header
alert http any any -> any any (msg:"MICH0 WEBSHELL AJAX Header X-P-AJAX-URL"; \
flow:to_server,established; http.header; content:"X-P-AJAX-URL"; nocase; \
classtype:web-application-attack; sid:2026030901; rev:1;)
# Mich0 Shell -- Authentication attempt
alert http any any -> any any (msg:"MICH0 WEBSHELL Auth Attempt pass=mich0"; \
flow:to_server,established; http.method; content:"POST"; http.uri; content:".php"; \
http.request_body; content:"pass=mich0"; nocase; \
classtype:web-application-attack; sid:2026030902; rev:1;)
# Mich0 Shell -- Remote command execution
alert http any any -> any any (msg:"MICH0 WEBSHELL Remote Command Execution"; \
flow:to_server,established; http.method; content:"POST"; http.header; \
content:"X-P-AJAX-URL"; http.request_body; content:"action=run_command"; \
classtype:web-application-attack; sid:2026030903; rev:1; priority:1;)
# Mich0 Shell -- Auth cookie in transit
alert http any any -> any any (msg:"MICH0 WEBSHELL Auth Cookie mich0login=ok"; \
flow:to_server,established; http.cookie; content:"mich0login=ok"; \
classtype:web-application-attack; sid:2026030907; rev:1;)
# Generic -- PHP file returning 404 with hidden form elements
alert http any any -> any any (msg:"GENERIC PHP Fake 404 With Hidden Form"; \
flow:to_client,established; http.stat_code; content:"404"; \
http.response_body; content:"<form"; content:"<input"; \
classtype:web-application-attack; sid:2026030910; rev:1;)
Recommended Actions
Immediate (24-48 hours):
- Search all web servers for the SHA-256 hash listed above
- Search for any PHP file containing
mich0login,X-P-AJAX-URL, orservancan3131 - Block outbound email to
servancan3131[@]gmail[.]comto prevent operator notification - Deploy the YARA rules above on endpoint security solutions
Short-term (1-2 weeks):
- Audit all PHP files on web servers for
http_response_code(404)combined with form elements - Review web logs for POST requests to suspicious PHP filenames (
fonts.php,style.php,config.php) - Ensure
disable_functionsinphp.inicovers shell_exec, exec, system, passthru, popen, proc_open - Implement file integrity monitoring on web document roots
Medium-term (1-3 months):
- Deploy WAF rules to block known webshell patterns, including the
X-P-AJAX-URLheader - Implement Content Security Policy headers that would break the CDN-dependent panel
- Consider read-only filesystem mounts for web roots where possible
- Establish regular PHP file audits for anomalous code patterns
References
- MalwareBazaar Sample
- CERT-PL MWDB
- FileScan-IO Analysis
- Kaspersky OpenTIP
- VirusTotal
- MITRE ATT&CK T1505.003 -- Web Shell
Published by Breakglass Intelligence. Investigation conducted 2026-03-09. 10 Kaspersky hits over 11 months. 25% AV detection rate. Operator OPSEC: catastrophic. Classification: TLP:WHITE