This detection identifies adversaries deploying a malicious JSP Netspy webshell to establish persistent access and execute commands on compromised web servers within the Azure Sentinel environment. Proactive hunting for this behavior is critical because webshells often operate with low visibility in standard logs, allowing attackers to maintain stealthy footholds that can lead to lateral movement or data exfiltration if not promptly identified.
rule WEBSHELL_JSP_NetSpy
{
meta:
description = "JSP netspy webshell"
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/24"
modified = "2024-12-09"
hash = "94d1aaabde8ff9b4b8f394dc68caebf981c86587"
hash = "3870b31f26975a7cb424eab6521fc9bffc2af580"
id = "41f5c171-878d-579f-811d-91d74f7e3e24"
strings:
$scan1 = "scan" nocase wide ascii
$scan2 = "port" nocase wide ascii
$scan3 = "web" fullword nocase wide ascii
$scan4 = "proxy" fullword nocase wide ascii
$scan5 = "http" fullword nocase wide ascii
$scan6 = "https" fullword nocase wide ascii
$write1 = "os.write" fullword wide ascii
$write2 = "FileOutputStream" fullword wide ascii
$write3 = "PrintWriter" fullword wide ascii
$http = "java.net.HttpURLConnection" fullword wide ascii
//strings from private rule capa_jsp_safe
$cjsp_short1 = "<%" ascii wide
$cjsp_short2 = "%>" wide ascii
$cjsp_long1 = "<jsp:" ascii wide
$cjsp_long2 = /language=[\"']java[\"\']/ ascii wide
// JSF
$cjsp_long3 = "/jstl/core" ascii wide
$cjsp_long4 = "<%@p" nocase ascii wide
$cjsp_long5 = "<%@ " nocase ascii wide
$cjsp_long6 = "<% " ascii wide
$cjsp_long7 = "< %" ascii wide
//strings from private rule capa_jsp_input
// request.getParameter
$input1 = "getParameter" fullword ascii wide
// request.getHeaders
$input2 = "getHeaders" fullword ascii wide
$input3 = "getInputStream" fullword ascii wide
$input4 = "getReader" fullword ascii wide
$req1 = "request" fullword ascii wide
$req2 = "HttpServletRequest" fullword ascii wide
$req3 = "getRequest" fullword ascii wide
condition:
filesize < 30KB and (
$cjsp_short1 at 0 or
any of ( $cjsp_long* ) or
($cjsp_short1 and $cjsp_short2 in ( filesize-100..filesize )) or
(
$cjsp_short2 and (
$cjsp_short1 in ( 0..1000 ) or
$cjsp_short1 in ( filesize-1000..filesize )
)
)
)
and (
any of ( $input* ) and
any of ( $req* )
)
and 4 of ( $scan* ) and 1 of ( $write* ) and $http
}
This YARA rule can be deployed in the following contexts:
This rule contains 26 string patterns in its detection logic.
Here are 5 specific false positive scenarios for the JSP Netspy Webshell detection rule in an enterprise environment, along with recommended filters and exclusions:
Scenario: Automated Backup Script Execution via JSP Interface
.jsp file that establishes a connection to the backup repository, mimicking the network behavior of a webshell initiating a command execution session.svc_backup) or specific IP ranges dedicated to the backup infrastructure. Additionally, filter out requests where the User-Agent string contains “Veeam” or “Commvault”.Scenario: Scheduled Maintenance Job by DevOps Team
X-Forwarded-For header to identify requests initiated by Jenkins agents (Jenkins-Agent).Scenario: Legitimate Admin Portal Access for Real-Time Monitoring