Back to reports
highPhishing

Mich0 Shell: A Turkish Operator's Unobfuscated PHP Webshell Hiding Behind Pixel-Perfect Fake 404 Pages for a Year

PublishedMarch 12, 2026
Threat Actors:ProfileAssessmentTimeline
phishingc2exploitapt

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".

PropertyValue
SHA-2561b315ddeac3883162a5d567b58b65cd47eb315aab6c59621d0047caad092ab8f
SHA-1cfd6bf31596a93a3b262bdc6323c4aabc4c8f320
MD58a1c2c7c1f68fa2b5601333c9cae33c3
File size27,054 bytes
Filenamefonts.php
Line endingsCRLF (Windows development environment)
First seen2025-03-31 (ReversingLabs)
Last observed2026-02-28 (MalwareBazaar upload)
OriginJapan (JP)
MalwareBazaar downloads102

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:

  1. Sets the HTTP response code to 404
  2. Reads $_SERVER['SERVER_SOFTWARE'] to determine if the server runs nginx or Apache
  3. Renders a pixel-perfect fake error page matching the detected server's native 404 styling
  4. Embeds a hidden password input field using white-on-white CSS: border:1px solid #fff; background-color:#fff
  5. 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.

FeatureDetail
Passwordmich0 (plaintext comparison)
Cookie namemich0login
Cookie valueok (static, never changes)
Cookie lifetime30 days
Cookie path/ (site-wide)
LogoutGET parameter cikis (Turkish: "exit")
Brute-force protectionNone
IP restrictionNone
Rate limitingNone

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:

PriorityFunctionOutput MethodCompatibility
1shell_exec()Returns string directlyMost common
2exec()Array output, joined with newlinesWidely available
3system()Output buffer captureFallback
4passthru()Output buffer captureLast 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:

ActionCapabilityPHP Functions
run_commandExecute OS commandsshell_exec/exec/system/passthru
get_directoryBrowse directoriesscandir(), is_dir(), filesize(), fileperms()
upload_fileUpload files to servermove_uploaded_file()
get_file_contentRead any filefile_get_contents()
deleteDelete files/directoriesunlink(), rmdir()
chmodChange permissionschmod() with octdec()
renameRename files/directoriesrename()
editWrite content to filesfopen(), 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

AttributeAssessment
CountryTurkey (medium confidence)
MotivationFinancial -- server access enables cryptomining, spam relay, data theft, phishing hosting, access sales
SophisticationIntermediate -- clean code, proper error handling, modern UI, but catastrophic OPSEC
Actor typeIndividual operator or small team, not an APT, not a known cybercrime group
Active sinceAt least March 2025

Full OPSEC Failure Matrix

FailureImpact
Personal Gmail hardcoded in sourceDirect attribution to real identity
Turkish-language parameter cikisConfirms operator's native language
Zero code obfuscationEvery feature immediately visible to any analyst
Hardcoded plaintext password mich0Trivially discoverable
No brute-force protectionPassword crackable in seconds
No IP whitelistingAny attacker who discovers the password gains access
Static cookie value okSession 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.

VendorDetectionAssessment
KasperskyHEUR:Backdoor.PHP.WebShell.genGeneric heuristic, 10 hits across ~1 year
ReversingLabsScript-PHP.Trojan.Heuristic25% scanner match (6/24)
FileScan-IOMALICIOUS (confidence 1.0)Full confidence
Spamhaus HBLSuspiciousHash-based
YOROI YOMILegit File (score 0.00)FALSE NEGATIVE -- missed entirely
ClamAVNot detectedNo 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

DateEventSource
2025-03-31First seen by ReversingLabsMalwareBazaar vendor intel
2025-05-31First Kaspersky detectionMalwareBazaar vendor intel
2026-02-02Last Kaspersky observationMalwareBazaar vendor intel
2026-02-28Uploaded to MalwareBazaar by AnonLabsMalwareBazaar
2026-03-09This analysisBreakglass 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

TacticTechniqueIDImplementation
PersistenceServer Software Component: Web ShellT1505.003fonts.php dropped on web server
ExecutionCommand and Scripting Interpreter: Unix ShellT1059.004shell_exec/exec/system/passthru cascade
Defense EvasionMasquerading: Match Legitimate NameT1036.005Named "fonts.php" to blend with web assets
Defense EvasionIndicator Removal: File DeletionT1070.004Delete action in file manager
Command and ControlApplication Layer Protocol: Web ProtocolsT1071.001HTTP AJAX communication via custom header
CollectionData from Local SystemT1005File read capability (get_file_content)
DiscoveryFile and Directory DiscoveryT1083Directory browser (get_directory)
ExfiltrationExfiltration Over C2 ChannelT1041File content returned via HTTP response
ImpactResource HijackingT1496Command exec enables cryptomining
Lateral MovementIngress Tool TransferT1105File upload capability
Defense EvasionFile and Directory Permissions ModificationT1222chmod 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;)

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, or servancan3131
  • Block outbound email to servancan3131[@]gmail[.]com to 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_functions in php.ini covers 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-URL header
  • 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


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

Share