This detection identifies potential remote code execution attacks where adversaries leverage vulnerable ASP webshells to execute arbitrary commands via unsanitized user inputs using eval or exec functions. Proactively hunting for this behavior in Azure Sentinel is critical because these generic webshell patterns often indicate the initial foothold of a broader compromise, allowing the SOC team to rapidly isolate affected assets before lateral movement occurs.
rule WEBSHELL_ASP_Generic_Eval_On_Input
{
meta:
description = "Generic ASP webshell which uses any eval/exec function directly on user input"
license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE"
author = "Arnim Rupp (https://github.com/ruppde)"
reference = "Internal Research"
score = 75
date = "2021/01/07"
modified = "2023-04-05"
hash = "d6b96d844ac395358ee38d4524105d331af42ede"
hash = "9be2088d5c3bfad9e8dfa2d7d7ba7834030c7407"
hash = "a1df4cfb978567c4d1c353e988915c25c19a0e4a"
hash = "069ea990d32fc980939fffdf1aed77384bf7806bc57c0a7faaff33bd1a3447f6"
id = "0904cefb-6e0f-5e5f-9986-cf83d409ce46"
strings:
$payload_and_input0 = /\beval_r\s{0,20}\(Request\(/ nocase wide ascii
$payload_and_input1 = /\beval[\s\(]{1,20}request[.\(\[]/ nocase wide ascii
$payload_and_input2 = /\bexecute[\s\(]{1,20}request\(/ nocase wide ascii
$payload_and_input4 = /\bExecuteGlobal\s{1,20}request\(/ nocase wide ascii
//strings from private rule capa_asp
$tagasp_short1 = /<%[^"]/ wide ascii
// also looking for %> to reduce fp (yeah, short atom but seldom since special chars)
$tagasp_short2 = "%>" wide ascii
// classids for scripting host etc
$tagasp_classid1 = "72C24DD5-D70A-438B-8A42-98424B88AFB8" nocase wide ascii
$tagasp_classid2 = "F935DC22-1CF0-11D0-ADB9-00C04FD58A0B" nocase wide ascii
$tagasp_classid3 = "093FF999-1EA0-4079-9525-9614C3504B74" nocase wide ascii
$tagasp_classid4 = "F935DC26-1CF0-11D0-ADB9-00C04FD58A0B" nocase wide ascii
$tagasp_classid5 = "0D43FE01-F093-11CF-8940-00A0C9054228" nocase wide ascii
$tagasp_long10 = "<%@ " wide ascii
// <% eval
$tagasp_long11 = /<% \w/ nocase wide ascii
$tagasp_long12 = "<%ex" nocase wide ascii
$tagasp_long13 = "<%ev" nocase wide ascii
// <%@ LANGUAGE = VBScript.encode%>
// <%@ Language = "JScript" %>
// <%@ WebHandler Language="C#" class="Handler" %>
// <%@ WebService Language="C#" Class="Service" %>
// <%@Page Language="Jscript"%>
// <%@ Page Language = Jscript %>
// <%@PAGE LANGUAGE=JSCRIPT%>
// <%@ Page Language="Jscript" validateRequest="false" %>
// <%@ Page Language = Jscript %>
// <%@ Page Language="C#" %>
// <%@ Page Language="VB" ContentType="text/html" validaterequest="false" AspCompat="true" Debug="true" %>
// <script runat="server" language="JScript">
// <SCRIPT RUNAT=SERVER LANGUAGE=JSCRIPT>
// <SCRIPT RUNAT=SERVER LANGUAGE=JSCRIPT>
// <msxsl:script language="JScript" ...
$tagasp_long20 = /<(%|script|msxsl:script).{0,60}language="?(vb|jscript|c#)/ nocase wide ascii
$tagasp_long32 = /<script\s{1,30}runat=/ wide ascii
$tagasp_long33 = /<SCRIPT\s{1,30}RUNAT=/ wide ascii
// avoid hitting php
$php1 = "<?php"
$php2 = "<?="
// avoid hitting jsp
$jsp1 = "=\"java." wide ascii
$jsp2 = "=\"javax." wide ascii
$jsp3 = "java.lang." wide ascii
$jsp4 = "public" fullword wide ascii
$jsp5 = "throws" fullword wide ascii
$jsp6 = "getValue" fullword wide ascii
$jsp7 = "getBytes" fullword wide ascii
$perl1 = "PerlScript" fullword
condition:
( filesize < 1100KB and (
(
any of ( $tagasp_long* ) or
// TODO : yara_push_private_rules.py doesn't do private rules in private rules yet
any of ( $tagasp_classid* ) or
(
$tagasp_short1 and
$tagasp_short2 in ( filesize-100..filesize )
) or (
$tagasp_short2 and (
$tagasp_short1 in ( 0..1000 ) or
$tagasp_short1 in ( filesize-1000..filesize )
)
)
) and not (
(
any of ( $perl* ) or
$php1 at 0 or
$php2 at 0
) or (
( #jsp1 + #jsp2 + #jsp3 ) > 0 and ( #jsp4 + #jsp5 + #jsp6 + #jsp7 ) > 0
)
)
)
and any of ( $payload_and_input* ) ) or
( filesize < 100 and any of ( $payload_and_input* ) )
}
This YARA rule can be deployed in the following contexts:
This rule contains 28 string patterns in its detection logic.
Here are 4 specific false positive scenarios for the “Generic ASP webshell using eval/exec on user input” detection rule, along with recommended filters or exclusions:
Scheduled Reporting Job via PowerShell
Invoke-Report.ps1) that dynamically constructs SQL queries based on parameters passed from an external scheduling tool (e.g., System Center Orchestrator). The script uses Invoke-Expression or eval() to execute the constructed query string, which contains user-provided date ranges and department names.Orchestrator.exe or TaskScheduler.exe AND the command line arguments contain specific keywords like --report-mode or match a known regex for the scheduled job name (e.g., ^.*Invoke-Report.ps1.*).Internal Developer Portal Debugging Tool
eval() function to parse and execute the incoming JSON string directly within the browser session context before storing it in the database.IIS AppPool\DevOpsDashboard) or exclude traffic originating from the internal subnet range dedicated to the development environment (e.g., 10.20.45.0/24).Dynamic Configuration Management via Admin Console
exec() to validate syntax before applying