From a721f2469f0b4a54aad48815f399db271f4c0c3a Mon Sep 17 00:00:00 2001 From: Arnim Rupp <46819580+ruppde@users.noreply.github.com> Date: Sun, 18 Jun 2023 09:45:42 +0200 Subject: [PATCH] Add more webshell YARA rules From https://github.com/ruppde/yara_rules#webshells --- core.webshell_detection.yara | 6622 ++++++++++++++++++++++++++++++++++ 1 file changed, 6622 insertions(+) diff --git a/core.webshell_detection.yara b/core.webshell_detection.yara index b82ebac..fb85f81 100644 --- a/core.webshell_detection.yara +++ b/core.webshell_detection.yara @@ -168,3 +168,6625 @@ rule obfuscatedFunctionality condition: chr_obfuscation } + + +// Webshell rules by Arnim Rupp (https://github.com/ruppde), Version 2 +import "math" + +/* +Rationale behind the rules: +1. a webshell must always execute some kind of payload (in $payload*). the payload is either: +-- direct php function like exec, file write, sql, ... +-- indirect via eval, self defined functions, callbacks, reflection, ... +2. a webshell must always have some way to get the attackers input, e.g. for PHP in $_GET, php://input or $_SERVER (HTTP for headers). + +The input may be hidden in obfuscated code, so we look for either: +a) payload + input +b) eval-style-payloads + obfuscation +c) includers (webshell is split in 2+ files) +d) unique strings, if the coder doesn't even intend to hide + +Additional conditions will be added to reduce false positves. Check all findings for unintentional webshells aka vulnerabilities ;) + +The rules named "suspicious_" are commented by default. uncomment them to find more potentially malicious files at the price of more false positives. if that finds too many results to manually check, you can compare the hashes to virustotal with e.g. https://github.com/Neo23x0/munin + +Some samples in the collection were UTF-16 and at least PHP and Java support it, so I use "wide ascii" for all strings. The performance impact is 1%. See also https://thibaud-robin.fr/articles/bypass-filter-upload/ + +Rules tested on the following webshell repos and collections: + https://github.com/sensepost/reGeorg + https://github.com/WhiteWinterWolf/wwwolf-php-webshell + https://github.com/k8gege/Ladon + https://github.com/x-o-r-r-o/PHP-Webshells-Collection + https://github.com/mIcHyAmRaNe/wso-webshell + https://github.com/LandGrey/webshell-detect-bypass + https://github.com/threedr3am/JSP-Webshells + https://github.com/02bx/webshell-venom + https://github.com/pureqh/webshell + https://github.com/secwiki/webshell-2 + https://github.com/zhaojh329/rtty + https://github.com/modux/ShortShells + https://github.com/epinna/weevely3 + https://github.com/chrisallenlane/novahot + https://github.com/malwares/WebShell + https://github.com/tanjiti/webshellSample + https://github.com/L-codes/Neo-reGeorg + https://github.com/bayufedra/Tiny-PHP-Webshell + https://github.com/b374k/b374k + https://github.com/wireghoul/htshells + https://github.com/securityriskadvisors/cmd.jsp + https://github.com/WangYihang/Webshell-Sniper + https://github.com/Macr0phag3/WebShells + https://github.com/s0md3v/nano + https://github.com/JohnTroony/php-webshells + https://github.com/linuxsec/indoxploit-shell + https://github.com/hayasec/reGeorg-Weblogic + https://github.com/nil0x42/phpsploit + https://github.com/mperlet/pomsky + https://github.com/FunnyWolf/pystinger + https://github.com/tanjiti/webshellsample + https://github.com/lcatro/php-webshell-bypass-waf + https://github.com/zhzyker/exphub + https://github.com/dotcppfile/daws + https://github.com/lcatro/PHP-WebShell-Bypass-WAF + https://github.com/ysrc/webshell-sample + https://github.com/JoyChou93/webshell + https://github.com/k4mpr3t/b4tm4n + https://github.com/mas1337/webshell + https://github.com/tengzhangchao/pycmd + https://github.com/bartblaze/PHP-backdoors + https://github.com/antonioCoco/SharPyShell + https://github.com/xl7dev/WebShell + https://github.com/BlackArch/webshells + https://github.com/sqlmapproject/sqlmap + https://github.com/Smaash/quasibot + https://github.com/tennc/webshell + +Webshells in these repos after fdupes run: 4722 +Old signature-base rules found: 1315 +This rules found: 3286 +False positives in 8gb of common webapps plus yara-ci: 2 + +*/ + +rule webshell_php_generic +{ + meta: + description = "php webshell having some kind of input and some kind of payload. restricted to small files or big ones inclusing suspicious strings" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + date = "2021/01/14" + modified = "2023-04-05" + hash = "bee1b76b1455105d4bfe2f45191071cf05e83a309ae9defcf759248ca9bceddd" + hash = "6bf351900a408120bee3fc6ea39905c6a35fe6efcf35d0a783ee92062e63a854" + hash = "e3b4e5ec29628791f836e15500f6fdea19beaf3e8d9981c50714656c50d3b365" + hash = "00813155bf7f5eb441e1619616a5f6b21ae31afc99caa000c4aafd54b46c3597" + hash = "e31788042d9cdeffcb279533b5a7359b3beb1144f39bacdd3acdef6e9b4aff25" + hash = "36b91575a08cf40d4782e5aebcec2894144f1e236a102edda2416bc75cbac8dd" + hash = "a34154af7c0d7157285cfa498734cfb77662edadb1a10892eb7f7e2fb5e2486c" + hash = "791a882af2cea0aa8b8379791b401bebc235296858266ddb7f881c8923b7ea61" + hash = "9a8ab3c225076a26309230d7eac7681f85b271d2db22bf5a190adbf66faca2e6" + hash = "0d3ee83adc9ebf8fb1a8c449eed5547ee5e67e9a416cce25592e80963198ae23" + hash = "3d8708609562a27634df5094713154d8ca784dbe89738e63951e12184ff07ad6" + hash = "70d64d987f0d9ab46514abcc868505d95dbf458387f858b0d7580e4ee8573786" + hash = "259b3828694b4d256764d7d01b0f0f36ca0526d5ee75e134c6a754d2ab0d1caa" + hash = "04d139b48d59fa2ef24fb9347b74fa317cb05bd8b7389aeb0a4d458c49ea7540" + hash = "58d0e2ff61301fe0c176b51430850239d3278c7caf56310d202e0cdbdde9ac3f" + hash = "731f36a08b0e63c63b3a2a457667dfc34aa7ff3a2aee24e60a8d16b83ad44ce2" + hash = "e4ffd4ec67762fe00bb8bd9fbff78cffefdb96c16fe7551b5505d319a90fa18f" + hash = "fa00ee25bfb3908808a7c6e8b2423c681d7c52de2deb30cbaea2ee09a635b7d4" + hash = "98c1937b9606b1e8e0eebcb116a784c9d2d3db0039b21c45cba399e86c92c2fa" + hash = "e9423ad8e51895db0e8422750c61ef4897b3be4292b36dba67d42de99e714bff" + hash = "7a16311a371f03b29d5220484e7ecbe841cfaead4e73c17aa6a9c23b5d94544d" + hash = "7ca5dec0515dd6f401cb5a52c313f41f5437fc43eb62ea4bcc415a14212d09e9" + hash = "3de8c04bfdb24185a07f198464fcdd56bb643e1d08199a26acee51435ff0a99f" + hash = "63297f8c1d4e88415bc094bc5546124c9ed8d57aca3a09e36ae18f5f054ad172" + hash = "a09dcf52da767815f29f66cb7b03f3d8c102da5cf7b69567928961c389eac11f" + hash = "d9ae762b011216e520ebe4b7abcac615c61318a8195601526cfa11bbc719a8f1" + hash = "dd5d8a9b4bb406e0b8f868165a1714fe54ffb18e621582210f96f6e5ae850b33" + + strings: + $wfp_tiny1 = "escapeshellarg" fullword + $wfp_tiny2 = "addslashes" fullword + + //strings from private rule php_false_positive_tiny + // try to use only strings which would be flagged by themselves as suspicious by other rules, e.g. eval + //$gfp_tiny1 = "addslashes" fullword + //$gfp_tiny2 = "escapeshellarg" fullword + $gfp_tiny3 = "include \"./common.php\";" // xcache + $gfp_tiny4 = "assert('FALSE');" + $gfp_tiny5 = "assert(false);" + $gfp_tiny6 = "assert(FALSE);" + $gfp_tiny7 = "assert('array_key_exists(" + $gfp_tiny8 = "echo shell_exec($aspellcommand . ' 2>&1');" + $gfp_tiny9 = "throw new Exception('Could not find authentication source with id ' . $sourceId);" + $gfp_tiny10= "return isset( $_POST[ $key ] ) ? $_POST[ $key ] : ( isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $default );" + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = "" wide ascii + $gen_bit_sus45 = "
" wide ascii + $gen_bit_sus46 = "shell_" wide ascii + //fp: $gen_bit_sus47 = "Shell" fullword wide ascii + $gen_bit_sus50 = "bypass" wide ascii + $gen_bit_sus52 = " ^ $" wide ascii + $gen_bit_sus53 = ".ssh/authorized_keys" wide ascii + $gen_bit_sus55 = /\w'\.'\w/ wide ascii + $gen_bit_sus56 = /\w\"\.\"\w/ wide ascii + $gen_bit_sus57 = "dumper" wide ascii + $gen_bit_sus59 = "'cmd'" wide ascii + $gen_bit_sus60 = "\"execute\"" wide ascii + $gen_bit_sus61 = "/bin/sh" wide ascii + $gen_bit_sus62 = "Cyber" wide ascii + $gen_bit_sus63 = "portscan" fullword wide ascii + //$gen_bit_sus64 = "\"command\"" fullword wide ascii + //$gen_bit_sus65 = "'command'" fullword wide ascii + $gen_bit_sus66 = "whoami" fullword wide ascii + $gen_bit_sus67 = "$password='" fullword wide ascii + $gen_bit_sus68 = "$password=\"" fullword wide ascii + $gen_bit_sus69 = "$cmd" fullword wide ascii + $gen_bit_sus70 = "\"?>\"." fullword wide ascii + $gen_bit_sus71 = "Hacking" fullword wide ascii + $gen_bit_sus72 = "hacking" fullword wide ascii + $gen_bit_sus73 = ".htpasswd" wide ascii + $gen_bit_sus74 = /\btouch\(\$[^,]{1,30},/ wide ascii + $gen_bit_sus75 = "uploaded" fullword wide ascii + + // very suspicious strings, one is enough + $gen_much_sus7 = "Web Shell" nocase + $gen_much_sus8 = "WebShell" nocase + $gen_much_sus3 = "hidded shell" + $gen_much_sus4 = "WScript.Shell.1" nocase + $gen_much_sus5 = "AspExec" + $gen_much_sus14 = "\\pcAnywhere\\" nocase + $gen_much_sus15 = "antivirus" nocase + $gen_much_sus16 = "McAfee" nocase + $gen_much_sus17 = "nishang" + $gen_much_sus18 = "\"unsafe" fullword wide ascii + $gen_much_sus19 = "'unsafe" fullword wide ascii + $gen_much_sus24 = "exploit" fullword wide ascii + $gen_much_sus25 = "Exploit" fullword wide ascii + $gen_much_sus26 = "TVqQAAMAAA" wide ascii + $gen_much_sus30 = "Hacker" wide ascii + $gen_much_sus31 = "HACKED" fullword wide ascii + $gen_much_sus32 = "hacked" fullword wide ascii + $gen_much_sus33 = "hacker" wide ascii + $gen_much_sus34 = "grayhat" nocase wide ascii + $gen_much_sus35 = "Microsoft FrontPage" wide ascii + $gen_much_sus36 = "Rootkit" wide ascii + $gen_much_sus37 = "rootkit" wide ascii + $gen_much_sus38 = "/*-/*-*/" wide ascii + $gen_much_sus39 = "u\"+\"n\"+\"s" wide ascii + $gen_much_sus40 = "\"e\"+\"v" wide ascii + $gen_much_sus41 = "a\"+\"l\"" wide ascii + $gen_much_sus42 = "\"+\"(\"+\"" wide ascii + $gen_much_sus43 = "q\"+\"u\"" wide ascii + $gen_much_sus44 = "\"u\"+\"e" wide ascii + $gen_much_sus45 = "/*//*/" wide ascii + $gen_much_sus46 = "(\"/*/\"" wide ascii + $gen_much_sus47 = "eval(eval(" wide ascii + // self remove + $gen_much_sus48 = "unlink(__FILE__)" wide ascii + $gen_much_sus49 = "Shell.Users" wide ascii + $gen_much_sus50 = "PasswordType=Regular" wide ascii + $gen_much_sus51 = "-Expire=0" wide ascii + $gen_much_sus60 = "_=$$_" wide ascii + $gen_much_sus61 = "_=$$_" wide ascii + $gen_much_sus62 = "++;$" wide ascii + $gen_much_sus63 = "++; $" wide ascii + $gen_much_sus64 = "_.=$_" wide ascii + $gen_much_sus70 = "-perm -04000" wide ascii + $gen_much_sus71 = "-perm -02000" wide ascii + $gen_much_sus72 = "grep -li password" wide ascii + $gen_much_sus73 = "-name config.inc.php" wide ascii + // touch without parameters sets the time to now, not malicious and gives fp + $gen_much_sus75 = "password crack" wide ascii + $gen_much_sus76 = "mysqlDll.dll" wide ascii + $gen_much_sus77 = "net user" wide ascii + $gen_much_sus80 = "fopen(\".htaccess\",\"w" wide ascii + $gen_much_sus81 = /strrev\(['"]/ wide ascii + $gen_much_sus82 = "PHPShell" fullword wide ascii + $gen_much_sus821= "PHP Shell" fullword wide ascii + $gen_much_sus83 = "phpshell" fullword wide ascii + $gen_much_sus84 = "PHPshell" fullword wide ascii + $gen_much_sus87 = "deface" wide ascii + $gen_much_sus88 = "Deface" wide ascii + $gen_much_sus89 = "backdoor" wide ascii + $gen_much_sus90 = "r00t" fullword wide ascii + $gen_much_sus91 = "xp_cmdshell" fullword wide ascii + $gen_much_sus92 = "str_rot13" fullword wide ascii + + $gif = { 47 49 46 38 } + + + //strings from private rule capa_php_payload_multiple + // \([^)] to avoid matching on e.g. eval() in comments + $cmpayload1 = /\beval[\t ]*\([^)]/ nocase wide ascii + $cmpayload2 = /\bexec[\t ]*\([^)]/ nocase wide ascii + $cmpayload3 = /\bshell_exec[\t ]*\([^)]/ nocase wide ascii + $cmpayload4 = /\bpassthru[\t ]*\([^)]/ nocase wide ascii + $cmpayload5 = /\bsystem[\t ]*\([^)]/ nocase wide ascii + $cmpayload6 = /\bpopen[\t ]*\([^)]/ nocase wide ascii + $cmpayload7 = /\bproc_open[\t ]*\([^)]/ nocase wide ascii + $cmpayload8 = /\bpcntl_exec[\t ]*\([^)]/ nocase wide ascii + $cmpayload9 = /\bassert[\t ]*\([^)0]/ nocase wide ascii + $cmpayload10 = /\bpreg_replace[\t ]*\([^\)]{1,100}\/e/ nocase wide ascii + $cmpayload11 = /\bpreg_filter[\t ]*\([^\)]{1,100}\/e/ nocase wide ascii + $cmpayload12 = /\bmb_ereg_replace[\t ]*\([^\)]{1,100}'e'/ nocase wide ascii + $cmpayload20 = /\bcreate_function[\t ]*\([^)]/ nocase wide ascii + $cmpayload21 = /\bReflectionFunction[\t ]*\([^)]/ nocase wide ascii + + $fp1 = "# Some examples from obfuscated malware:" ascii + condition: + //any of them or + not ( + any of ( $gfp_tiny* ) + or 1 of ($fp*) + ) + and ( + ( + ( + $php_short in (0..100) or + $php_short in (filesize-1000..filesize) + ) + and not any of ( $no_* ) + ) + or any of ( $php_new* ) + ) + and ( + any of ( $inp* ) + ) + and ( + any of ( $cpayload* ) or + all of ( $m_cpayload_preg_filter* ) + ) + and + ( ( filesize < 1000 and not any of ( $wfp_tiny* ) ) or + ( ( + $gif at 0 or + ( + filesize < 4KB and + ( + 1 of ( $gen_much_sus* ) or + 2 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 20KB and + ( + 2 of ( $gen_much_sus* ) or + 3 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 50KB and + ( + 2 of ( $gen_much_sus* ) or + 4 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 100KB and + ( + 2 of ( $gen_much_sus* ) or + 6 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 150KB and + ( + 3 of ( $gen_much_sus* ) or + 7 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 500KB and + ( + 4 of ( $gen_much_sus* ) or + 8 of ( $gen_bit_sus* ) + ) + ) + ) + and + ( filesize > 5KB or not any of ( $wfp_tiny* ) ) ) or + ( filesize < 500KB and ( + 4 of ( $cmpayload* ) + ) + ) ) +} + +rule webshell_php_generic_callback +{ + meta: + description = "php webshell having some kind of input and using a callback to execute the payload. restricted to small files or would give lots of false positives" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + date = "2021/01/14" + modified = "2023-04-05" + score = 60 + hash = "e98889690101b59260e871c49263314526f2093f" + hash = "63297f8c1d4e88415bc094bc5546124c9ed8d57aca3a09e36ae18f5f054ad172" + hash = "81388c8cc99353cdb42572bb88df7d3bd70eefc748c2fa4224b6074aa8d7e6a2" + hash = "27d3bfabc283d851b0785199da8b1b0384afcb996fa9217687274dd56a7b5f49" + hash = "ee256d7cc3ceb2bf3a1934d553cdd36e3fbde62a02b20a1b748a74e85d4dbd33" + hash = "4adc6c5373c4db7b8ed1e7e6df10a3b2ce5e128818bb4162d502056677c6f54a" + hash = "1fe4c60ea3f32819a98b1725581ac912d0f90d497e63ad81ccf258aeec59fee3" + hash = "2967f38c26b131f00276bcc21227e54ee6a71881da1d27ec5157d83c4c9d4f51" + hash = "1ba02fb573a06d5274e30b2b05573305294497769414e964a097acb5c352fb92" + hash = "f4fe8e3b2c39090ca971a8e61194fdb83d76fadbbace4c5eb15e333df61ce2a4" + hash = "badda1053e169fea055f5edceae962e500842ad15a5d31968a0a89cf28d89e91" + hash = "0a29cf1716e67a7932e604c5d3df4b7f372561200c007f00131eef36f9a4a6a2" + hash = "51c2c8b94c4b8cce806735bcf6e5aa3f168f0f7addce47b699b9a4e31dc71b47" + hash = "de1ef827bcd3100a259f29730cb06f7878220a7c02cee0ebfc9090753d2237a8" + + strings: + + //strings from private rule php_false_positive + // try to use only strings which would be flagged by themselves as suspicious by other rules, e.g. eval + // a good choice is a string with good atom quality = ideally 4 unusual characters next to each other + $gfp1 = "eval(\"return [$serialised_parameter" // elgg + $gfp2 = "$this->assert(strpos($styles, $" + $gfp3 = "$module = new $_GET['module']($_GET['scope']);" + $gfp4 = "$plugin->$_POST['action']($_POST['id']);" + $gfp5 = "$_POST[partition_by]($_POST[" + $gfp6 = "$object = new $_REQUEST['type']($_REQUEST['id']);" + $gfp7 = "The above example code can be easily exploited by passing in a string such as" // ... ;) + $gfp8 = "Smarty_Internal_Debug::start_render($_template);" + $gfp9 = "?p4yl04d=UNION%20SELECT%20'%20system($_GET['command']);%20?>',2,3%20INTO%20OUTFILE%20'/var/www/w3bsh3ll.php" + $gfp10 = "[][}{;|]\\|\\\\[+=]\\|=>?" + $gfp11 = "(eval (getenv \"EPROLOG\")))" + $gfp12 = "ZmlsZV9nZXRfY29udGVudHMoJ2h0dHA6Ly9saWNlbnNlLm9wZW5jYXJ0LWFwaS5jb20vbGljZW5zZS5waHA/b3JkZXJ" + + //strings from private rule php_false_positive_tiny + // try to use only strings which would be flagged by themselves as suspicious by other rules, e.g. eval + //$gfp_tiny1 = "addslashes" fullword + //$gfp_tiny2 = "escapeshellarg" fullword + $gfp_tiny3 = "include \"./common.php\";" // xcache + $gfp_tiny4 = "assert('FALSE');" + $gfp_tiny5 = "assert(false);" + $gfp_tiny6 = "assert(FALSE);" + $gfp_tiny7 = "assert('array_key_exists(" + $gfp_tiny8 = "echo shell_exec($aspellcommand . ' 2>&1');" + $gfp_tiny9 = "throw new Exception('Could not find authentication source with id ' . $sourceId);" + $gfp_tiny10= "return isset( $_POST[ $key ] ) ? $_POST[ $key ] : ( isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $default );" + + //strings from private rule capa_php_input + $inp1 = "php://input" wide ascii + $inp2 = /_GET\s?\[/ wide ascii + // for passing $_GET to a function + $inp3 = /\(\s?\$_GET\s?\)/ wide ascii + $inp4 = /_POST\s?\[/ wide ascii + $inp5 = /\(\s?\$_POST\s?\)/ wide ascii + $inp6 = /_REQUEST\s?\[/ wide ascii + $inp7 = /\(\s?\$_REQUEST\s?\)/ wide ascii + // PHP automatically adds all the request headers into the $_SERVER global array, prefixing each header name by the "HTTP_" string, so e.g. @eval($_SERVER['HTTP_CMD']) will run any code in the HTTP header CMD + $inp15 = "_SERVER['HTTP_" wide ascii + $inp16 = "_SERVER[\"HTTP_" wide ascii + $inp17 = /getenv[\t ]{0,20}\([\t ]{0,20}['"]HTTP_/ wide ascii + $inp18 = "array_values($_SERVER)" wide ascii + $inp19 = /file_get_contents\("https?:\/\// wide ascii + + // TODO: arraywalk \n /* + //strings from private rule capa_php_callback + // the end is 1. ( followed by anything but a direct closing ) 2. /* for the start of an obfuscation comment + $callback1 = /\bob_start[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback2 = /\barray_diff_uassoc[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback3 = /\barray_diff_ukey[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback4 = /\barray_filter[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback5 = /\barray_intersect_uassoc[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback6 = /\barray_intersect_ukey[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback7 = /\barray_map[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback8 = /\barray_reduce[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback9 = /\barray_udiff_assoc[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback10 = /\barray_udiff_uassoc[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback11 = /\barray_udiff[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback12 = /\barray_uintersect_assoc[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback13 = /\barray_uintersect_uassoc[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback14 = /\barray_uintersect[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback15 = /\barray_walk_recursive[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback16 = /\barray_walk[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback17 = /\bassert_options[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback18 = /\buasort[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback19 = /\buksort[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback20 = /\busort[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback21 = /\bpreg_replace_callback[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback22 = /\bspl_autoload_register[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback23 = /\biterator_apply[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback24 = /\bcall_user_func[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback25 = /\bcall_user_func_array[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback26 = /\bregister_shutdown_function[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback27 = /\bregister_tick_function[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback28 = /\bset_error_handler[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback29 = /\bset_exception_handler[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback30 = /\bsession_set_save_handler[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback31 = /\bsqlite_create_aggregate[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback32 = /\bsqlite_create_function[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $callback33 = /\bmb_ereg_replace_callback[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + + $m_callback1 = /\bfilter_var[\n\t ]*(\([^)]|\/\*)/ nocase wide ascii + $m_callback2 = "FILTER_CALLBACK" fullword wide ascii + + $cfp1 = /ob_start\(['\"]ob_gzhandler/ nocase wide ascii + $cfp2 = "IWPML_Backend_Action_Loader" ascii wide + $cfp3 = "" wide ascii + $gen_bit_sus45 = "" wide ascii + $gen_bit_sus46 = "shell_" wide ascii + //fp: $gen_bit_sus47 = "Shell" fullword wide ascii + $gen_bit_sus50 = "bypass" wide ascii + $gen_bit_sus52 = " ^ $" wide ascii + $gen_bit_sus53 = ".ssh/authorized_keys" wide ascii + $gen_bit_sus55 = /\w'\.'\w/ wide ascii + $gen_bit_sus56 = /\w\"\.\"\w/ wide ascii + $gen_bit_sus57 = "dumper" wide ascii + $gen_bit_sus59 = "'cmd'" wide ascii + $gen_bit_sus60 = "\"execute\"" wide ascii + $gen_bit_sus61 = "/bin/sh" wide ascii + $gen_bit_sus62 = "Cyber" wide ascii + $gen_bit_sus63 = "portscan" fullword wide ascii + //$gen_bit_sus64 = "\"command\"" fullword wide ascii + //$gen_bit_sus65 = "'command'" fullword wide ascii + $gen_bit_sus66 = "whoami" fullword wide ascii + $gen_bit_sus67 = "$password='" fullword wide ascii + $gen_bit_sus68 = "$password=\"" fullword wide ascii + $gen_bit_sus69 = "$cmd" fullword wide ascii + $gen_bit_sus70 = "\"?>\"." fullword wide ascii + $gen_bit_sus71 = "Hacking" fullword wide ascii + $gen_bit_sus72 = "hacking" fullword wide ascii + $gen_bit_sus73 = ".htpasswd" wide ascii + $gen_bit_sus74 = /\btouch\(\$[^,]{1,30},/ wide ascii + + // very suspicious strings, one is enough + $gen_much_sus7 = "Web Shell" nocase + $gen_much_sus8 = "WebShell" nocase + $gen_much_sus3 = "hidded shell" + $gen_much_sus4 = "WScript.Shell.1" nocase + $gen_much_sus5 = "AspExec" + $gen_much_sus14 = "\\pcAnywhere\\" nocase + $gen_much_sus15 = "antivirus" nocase + $gen_much_sus16 = "McAfee" nocase + $gen_much_sus17 = "nishang" + $gen_much_sus18 = "\"unsafe" fullword wide ascii + $gen_much_sus19 = "'unsafe" fullword wide ascii + $gen_much_sus24 = "exploit" fullword wide ascii + $gen_much_sus25 = "Exploit" fullword wide ascii + $gen_much_sus26 = "TVqQAAMAAA" wide ascii + $gen_much_sus30 = "Hacker" wide ascii + $gen_much_sus31 = "HACKED" fullword wide ascii + $gen_much_sus32 = "hacked" fullword wide ascii + $gen_much_sus33 = "hacker" wide ascii + $gen_much_sus34 = "grayhat" nocase wide ascii + $gen_much_sus35 = "Microsoft FrontPage" wide ascii + $gen_much_sus36 = "Rootkit" wide ascii + $gen_much_sus37 = "rootkit" wide ascii + $gen_much_sus38 = "/*-/*-*/" wide ascii + $gen_much_sus39 = "u\"+\"n\"+\"s" wide ascii + $gen_much_sus40 = "\"e\"+\"v" wide ascii + $gen_much_sus41 = "a\"+\"l\"" wide ascii + $gen_much_sus42 = "\"+\"(\"+\"" wide ascii + $gen_much_sus43 = "q\"+\"u\"" wide ascii + $gen_much_sus44 = "\"u\"+\"e" wide ascii + $gen_much_sus45 = "/*//*/" wide ascii + $gen_much_sus46 = "(\"/*/\"" wide ascii + $gen_much_sus47 = "eval(eval(" wide ascii + // self remove + $gen_much_sus48 = "unlink(__FILE__)" wide ascii + $gen_much_sus49 = "Shell.Users" wide ascii + $gen_much_sus50 = "PasswordType=Regular" wide ascii + $gen_much_sus51 = "-Expire=0" wide ascii + $gen_much_sus60 = "_=$$_" wide ascii + $gen_much_sus61 = "_=$$_" wide ascii + $gen_much_sus62 = "++;$" wide ascii + $gen_much_sus63 = "++; $" wide ascii + $gen_much_sus64 = "_.=$_" wide ascii + $gen_much_sus70 = "-perm -04000" wide ascii + $gen_much_sus71 = "-perm -02000" wide ascii + $gen_much_sus72 = "grep -li password" wide ascii + $gen_much_sus73 = "-name config.inc.php" wide ascii + // touch without parameters sets the time to now, not malicious and gives fp + $gen_much_sus75 = "password crack" wide ascii + $gen_much_sus76 = "mysqlDll.dll" wide ascii + $gen_much_sus77 = "net user" wide ascii + $gen_much_sus80 = "fopen(\".htaccess\",\"w" wide ascii + $gen_much_sus81 = /strrev\(['"]/ wide ascii + $gen_much_sus82 = "PHPShell" fullword wide ascii + $gen_much_sus821= "PHP Shell" fullword wide ascii + $gen_much_sus83 = "phpshell" fullword wide ascii + $gen_much_sus84 = "PHPshell" fullword wide ascii + $gen_much_sus87 = "deface" wide ascii + $gen_much_sus88 = "Deface" wide ascii + $gen_much_sus89 = "backdoor" wide ascii + $gen_much_sus90 = "r00t" fullword wide ascii + $gen_much_sus91 = "xp_cmdshell" fullword wide ascii + $gen_much_sus92 = "base64_decode(base64_decode(" fullword wide ascii + $gen_much_sus93 = "eval(\"/*" wide ascii + + $gif = { 47 49 46 38 } + + + condition: + //any of them or + not ( + any of ( $gfp* ) + ) + and not ( + any of ( $gfp_tiny* ) + ) + and ( + any of ( $inp* ) + ) + and ( + not any of ( $cfp* ) and + ( + any of ( $callback* ) or + all of ( $m_callback* ) + ) + ) + and + ( filesize < 1000 or ( + $gif at 0 or + ( + filesize < 4KB and + ( + 1 of ( $gen_much_sus* ) or + 2 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 20KB and + ( + 2 of ( $gen_much_sus* ) or + 3 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 50KB and + ( + 2 of ( $gen_much_sus* ) or + 4 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 100KB and + ( + 2 of ( $gen_much_sus* ) or + 6 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 150KB and + ( + 3 of ( $gen_much_sus* ) or + 7 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 500KB and + ( + 4 of ( $gen_much_sus* ) or + 8 of ( $gen_bit_sus* ) + ) + ) + ) + ) +} + +rule WEBSHELL_php_base64_encoded_payloads : FILE { + meta: + description = "php webshell containing base64 encoded payload" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + date = "2021/01/07" + modified = "2023-04-05" + hash = "88d0d4696c9cb2d37d16e330e236cb37cfaec4cd" + hash = "e3b4e5ec29628791f836e15500f6fdea19beaf3e8d9981c50714656c50d3b365" + hash = "e726cd071915534761822805724c6c6bfe0fcac604a86f09437f03f301512dc5" + hash = "39b8871928d00c7de8d950d25bff4cb19bf9bd35942f7fee6e0f397ff42fbaee" + hash = "8cc9802769ede56f1139abeaa0735526f781dff3b6c6334795d1d0f19161d076" + hash = "4cda0c798908b61ae7f4146c6218d7b7de14cbcd7c839edbdeb547b5ae404cd4" + hash = "afd9c9b0df0b2ca119914ea0008fad94de3bd93c6919f226b793464d4441bdf4" + hash = "b2048dc30fc7681094a0306a81f4a4cc34f0b35ccce1258c20f4940300397819" + hash = "da6af9a4a60e3a484764010fbf1a547c2c0a2791e03fc11618b8fc2605dceb04" + hash = "222cd9b208bd24955bcf4f9976f9c14c1d25e29d361d9dcd603d57f1ea2b0aee" + hash = "98c1937b9606b1e8e0eebcb116a784c9d2d3db0039b21c45cba399e86c92c2fa" + hash = "6b6cd1ef7e78e37cbcca94bfb5f49f763ba2f63ed8b33bc4d7f9e5314c87f646" + hash = "51c2c8b94c4b8cce806735bcf6e5aa3f168f0f7addce47b699b9a4e31dc71b47" + hash = "7a16311a371f03b29d5220484e7ecbe841cfaead4e73c17aa6a9c23b5d94544d" + hash = "e2b1dfcfaa61e92526a3a444be6c65330a8db4e692543a421e19711760f6ffe2" + + strings: + $decode1 = "base64_decode" fullword nocase wide ascii + $decode2 = "openssl_decrypt" fullword nocase wide ascii + // exec + $one1 = "leGVj" + $one2 = "V4ZW" + $one3 = "ZXhlY" + $one4 = "UAeABlAGMA" + $one5 = "lAHgAZQBjA" + $one6 = "ZQB4AGUAYw" + // shell_exec + $two1 = "zaGVsbF9leGVj" + $two2 = "NoZWxsX2V4ZW" + $two3 = "c2hlbGxfZXhlY" + $two4 = "MAaABlAGwAbABfAGUAeABlAGMA" + $two5 = "zAGgAZQBsAGwAXwBlAHgAZQBjA" + $two6 = "cwBoAGUAbABsAF8AZQB4AGUAYw" + // passthru + $three1 = "wYXNzdGhyd" + $three2 = "Bhc3N0aHJ1" + $three3 = "cGFzc3Rocn" + $three4 = "AAYQBzAHMAdABoAHIAdQ" + $three5 = "wAGEAcwBzAHQAaAByAHUA" + $three6 = "cABhAHMAcwB0AGgAcgB1A" + // system + $four1 = "zeXN0ZW" + $four2 = "N5c3Rlb" + $four3 = "c3lzdGVt" + $four4 = "MAeQBzAHQAZQBtA" + $four5 = "zAHkAcwB0AGUAbQ" + $four6 = "cwB5AHMAdABlAG0A" + // popen + $five1 = "wb3Blb" + $five2 = "BvcGVu" + $five3 = "cG9wZW" + $five4 = "AAbwBwAGUAbg" + $five5 = "wAG8AcABlAG4A" + $five6 = "cABvAHAAZQBuA" + // proc_open + $six1 = "wcm9jX29wZW" + $six2 = "Byb2Nfb3Blb" + $six3 = "cHJvY19vcGVu" + $six4 = "AAcgBvAGMAXwBvAHAAZQBuA" + $six5 = "wAHIAbwBjAF8AbwBwAGUAbg" + $six6 = "cAByAG8AYwBfAG8AcABlAG4A" + // pcntl_exec + $seven1 = "wY250bF9leGVj" + $seven2 = "BjbnRsX2V4ZW" + $seven3 = "cGNudGxfZXhlY" + $seven4 = "AAYwBuAHQAbABfAGUAeABlAGMA" + $seven5 = "wAGMAbgB0AGwAXwBlAHgAZQBjA" + $seven6 = "cABjAG4AdABsAF8AZQB4AGUAYw" + // eval + $eight1 = "ldmFs" + $eight2 = "V2YW" + $eight3 = "ZXZhb" + $eight4 = "UAdgBhAGwA" + $eight5 = "lAHYAYQBsA" + $eight6 = "ZQB2AGEAbA" + // assert + $nine1 = "hc3Nlcn" + $nine2 = "Fzc2Vyd" + $nine3 = "YXNzZXJ0" + $nine4 = "EAcwBzAGUAcgB0A" + $nine5 = "hAHMAcwBlAHIAdA" + $nine6 = "YQBzAHMAZQByAHQA" + + // false positives + + // execu + $execu1 = "leGVjd" + $execu2 = "V4ZWN1" + $execu3 = "ZXhlY3" + + // esystem like e.g. filesystem + $esystem1 = "lc3lzdGVt" + $esystem2 = "VzeXN0ZW" + $esystem3 = "ZXN5c3Rlb" + + // opening + $opening1 = "vcGVuaW5n" + $opening2 = "9wZW5pbm" + $opening3 = "b3BlbmluZ" + + // false positives + $fp1 = { D0 CF 11 E0 A1 B1 1A E1 } + // api.telegram + $fp2 = "YXBpLnRlbGVncmFtLm9" + // Log files + $fp3 = " GET /" + $fp4 = " POST /" + + $fpa1 = "/cn=Recipients" + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = "assert(strpos($styles, $" + $gfp3 = "$module = new $_GET['module']($_GET['scope']);" + $gfp4 = "$plugin->$_POST['action']($_POST['id']);" + $gfp5 = "$_POST[partition_by]($_POST[" + $gfp6 = "$object = new $_REQUEST['type']($_REQUEST['id']);" + $gfp7 = "The above example code can be easily exploited by passing in a string such as" // ... ;) + $gfp8 = "Smarty_Internal_Debug::start_render($_template);" + $gfp9 = "?p4yl04d=UNION%20SELECT%20'%20system($_GET['command']);%20?>',2,3%20INTO%20OUTFILE%20'/var/www/w3bsh3ll.php" + $gfp10 = "[][}{;|]\\|\\\\[+=]\\|=>?" + $gfp11 = "(eval (getenv \"EPROLOG\")))" + $gfp12 = "ZmlsZV9nZXRfY29udGVudHMoJ2h0dHA6Ly9saWNlbnNlLm9wZW5jYXJ0LWFwaS5jb20vbGljZW5zZS5waHA/b3JkZXJ" + // Log files + $gfp_3 = " GET /" + $gfp_4 = " POST /" + condition: + filesize < 300KB and not ( + any of ( $gfp* ) + ) + and $geval +} + +rule webshell_php_double_eval_tiny +{ + meta: + description = "PHP webshell which probably hides the input inside an eval()ed obfuscated string" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + hash = "aabfd179aaf716929c8b820eefa3c1f613f8dcac" + date = "2021-01-11" + modified = "2023-04-05" + score = 50 + hash = "f66fb918751acc7b88a17272a044b5242797976c73a6e54ac6b04b02f61e9761" + hash = "6b2f0a3bd80019dea536ddbf92df36ab897dd295840cb15bb7b159d0ee2106ff" + + + strings: + $payload = /(\beval[\t ]*\([^)]|\bassert[\t ]*\([^)])/ nocase wide ascii + $fp1 = "clone" fullword wide ascii + $fp2 = "* @assert" ascii + $fp3 = "*@assert" ascii + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = " 70 and filesize < 300 and ( + ( + ( + $php_short in (0..100) or + $php_short in (filesize-1000..filesize) + ) + and not any of ( $no_* ) + ) + or any of ( $php_new* ) + ) + and #payload >= 2 and not any of ( $fp* ) +} + +rule webshell_php_obfuscated +{ + meta: + description = "PHP webshell obfuscated" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + date = "2021/01/12" + modified = "2023-04-05" + hash = "eec9ac58a1e763f5ea0f7fa249f1fe752047fa60" + hash = "181a71c99a4ae13ebd5c94bfc41f9ec534acf61cd33ef5bce5fb2a6f48b65bf4" + hash = "76d4e67e13c21662c4b30aab701ce9cdecc8698696979e504c288f20de92aee7" + hash = "1d0643927f04cb1133f00aa6c5fa84aaf88e5cf14d7df8291615b402e8ab6dc2" + strings: + + //strings from private rule php_false_positive + // try to use only strings which would be flagged by themselves as suspicious by other rules, e.g. eval + // a good choice is a string with good atom quality = ideally 4 unusual characters next to each other + $gfp1 = "eval(\"return [$serialised_parameter" // elgg + $gfp2 = "$this->assert(strpos($styles, $" + $gfp3 = "$module = new $_GET['module']($_GET['scope']);" + $gfp4 = "$plugin->$_POST['action']($_POST['id']);" + $gfp5 = "$_POST[partition_by]($_POST[" + $gfp6 = "$object = new $_REQUEST['type']($_REQUEST['id']);" + $gfp7 = "The above example code can be easily exploited by passing in a string such as" // ... ;) + $gfp8 = "Smarty_Internal_Debug::start_render($_template);" + $gfp9 = "?p4yl04d=UNION%20SELECT%20'%20system($_GET['command']);%20?>',2,3%20INTO%20OUTFILE%20'/var/www/w3bsh3ll.php" + $gfp10 = "[][}{;|]\\|\\\\[+=]\\|=>?" + $gfp11 = "(eval (getenv \"EPROLOG\")))" + $gfp12 = "ZmlsZV9nZXRfY29udGVudHMoJ2h0dHA6Ly9saWNlbnNlLm9wZW5jYXJ0LWFwaS5jb20vbGljZW5zZS5waHA/b3JkZXJ" + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = " 50 or + #o3 > 10 or + ( #o4+#o5+#o6+#o7+#o8+#o9 ) > 20 + ) + ) or ( + filesize < 200KB and + ( + ( #o1+#o2 ) > 200 or + #o3 > 30 or + ( #o4+#o5+#o6+#o7+#o8+#o9 ) > 30 + ) + + ) + ) + + + ) + and ( + any of ( $cpayload* ) or + all of ( $m_cpayload_preg_filter* ) + ) + +} + +rule webshell_php_obfuscated_encoding +{ + meta: + description = "PHP webshell obfuscated by encoding" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + date = "2021/04/18" + modified = "2023-04-05" + score = 70 + hash = "119fc058c9c5285498a47aa271ac9a27f6ada1bf4d854ccd4b01db993d61fc52" + hash = "d5ca3e4505ea122019ea263d6433221030b3f64460d3ce2c7d0d63ed91162175" + hash = "8a1e2d72c82f6a846ec066d249bfa0aaf392c65149d39b7b15ba19f9adc3b339" + + + strings: + // one without plain e, one without plain v, to avoid hitting on plain "eval(" + $enc_eval1 = /(e|\\x65|\\101)(\\x76|\\118)(a|\\x61|\\97)(l|\\x6c|\\108)(\(|\\x28|\\40)/ wide ascii nocase + $enc_eval2 = /(\\x65|\\101)(v|\\x76|\\118)(a|\\x61|\\97)(l|\\x6c|\\108)(\(|\\x28|\\40)/ wide ascii nocase + // one without plain a, one without plain s, to avoid hitting on plain "assert(" + $enc_assert1 = /(a|\\97|\\x61)(\\115|\\x73)(s|\\115|\\x73)(e|\\101|\\x65)(r|\\114|\\x72)(t|\\116|\\x74)(\(|\\x28|\\40)/ wide ascii nocase + $enc_assert2 = /(\\97|\\x61)(s|\\115|\\x73)(s|\\115|\\x73)(e|\\101|\\x65)(r|\\114|\\x72)(t|\\116|\\x74)(\(|\\x28|\\40)/ wide ascii nocase + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = "assert(strpos($styles, $" + $gfp3 = "$module = new $_GET['module']($_GET['scope']);" + $gfp4 = "$plugin->$_POST['action']($_POST['id']);" + $gfp5 = "$_POST[partition_by]($_POST[" + $gfp6 = "$object = new $_REQUEST['type']($_REQUEST['id']);" + $gfp7 = "The above example code can be easily exploited by passing in a string such as" // ... ;) + $gfp8 = "Smarty_Internal_Debug::start_render($_template);" + $gfp9 = "?p4yl04d=UNION%20SELECT%20'%20system($_GET['command']);%20?>',2,3%20INTO%20OUTFILE%20'/var/www/w3bsh3ll.php" + $gfp10 = "[][}{;|]\\|\\\\[+=]\\|=>?" + $gfp11 = "(eval (getenv \"EPROLOG\")))" + $gfp12 = "ZmlsZV9nZXRfY29udGVudHMoJ2h0dHA6Ly9saWNlbnNlLm9wZW5jYXJ0LWFwaS5jb20vbGljZW5zZS5waHA/b3JkZXJ" + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = " 2 or #obf3 > 10 ) +} + +rule webshell_php_obfuscated_str_replace +{ + meta: + description = "PHP webshell which eval()s obfuscated string" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + date = "2021/01/12" + modified = "2023-04-05" + hash = "691305753e26884d0f930cda0fe5231c6437de94" + hash = "7efd463aeb5bf0120dc5f963b62463211bd9e678" + hash = "fb655ddb90892e522ae1aaaf6cd8bde27a7f49ef" + hash = "d1863aeca1a479462648d975773f795bb33a7af2" + hash = "4d31d94b88e2bbd255cf501e178944425d40ee97" + hash = "e1a2af3477d62a58f9e6431f5a4a123fb897ea80" + + strings: + $payload1 = "str_replace" fullword wide ascii + $payload2 = "function" fullword wide ascii + $goto = "goto" fullword wide ascii + //$hex = "\\x" + $chr1 = "\\61" wide ascii + $chr2 = "\\112" wide ascii + $chr3 = "\\120" wide ascii + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = " 1 and + ( #chr1 > 10 or #chr2 > 10 or #chr3 > 10 ) +} + +rule webshell_php_obfuscated_fopo +{ + meta: + description = "PHP webshell which eval()s obfuscated string" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + hash = "fbcff8ea5ce04fc91c05384e847f2c316e013207" + hash = "6da57ad8be1c587bb5cc8a1413f07d10fb314b72" + hash = "a698441f817a9a72908a0d93a34133469f33a7b34972af3e351bdccae0737d99" + date = "2021/01/12" + modified = "2023-04-05" + + strings: + $payload = /(\beval[\t ]*\([^)]|\bassert[\t ]*\([^)])/ nocase wide ascii + // ;@eval( + $one1 = "7QGV2YWwo" wide ascii + $one2 = "tAZXZhbC" wide ascii + $one3 = "O0BldmFsK" wide ascii + $one4 = "sAQABlAHYAYQBsACgA" wide ascii + $one5 = "7AEAAZQB2AGEAbAAoA" wide ascii + $one6 = "OwBAAGUAdgBhAGwAKA" wide ascii + // ;@assert( + $two1 = "7QGFzc2VydC" wide ascii + $two2 = "tAYXNzZXJ0K" wide ascii + $two3 = "O0Bhc3NlcnQo" wide ascii + $two4 = "sAQABhAHMAcwBlAHIAdAAoA" wide ascii + $two5 = "7AEAAYQBzAHMAZQByAHQAKA" wide ascii + $two6 = "OwBAAGEAcwBzAGUAcgB0ACgA" wide ascii + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = "".)?gzinflate\s?\(\s?base64_decode\s?\(/ wide ascii nocase + $payload4 = /eval\s?\(\s?("\?>".)?gzuncompress\s?\(\s?(base64_decode|gzuncompress)/ wide ascii nocase + $payload6 = /eval\s?\(\s?("\?>".)?gzdecode\s?\(\s?base64_decode\s?\(/ wide ascii nocase + $payload7 = /eval\s?\(\s?base64_decode\s?\(/ wide ascii nocase + $payload8 = /eval\s?\(\s?pack\s?\(/ wide ascii nocase + + // api.telegram + $fp1 = "YXBpLnRlbGVncmFtLm9" + + //strings from private rule php_false_positive + // try to use only strings which would be flagged by themselves as suspicious by other rules, e.g. eval + // a good choice is a string with good atom quality = ideally 4 unusual characters next to each other + $gfp1 = "eval(\"return [$serialised_parameter" // elgg + $gfp2 = "$this->assert(strpos($styles, $" + $gfp3 = "$module = new $_GET['module']($_GET['scope']);" + $gfp4 = "$plugin->$_POST['action']($_POST['id']);" + $gfp5 = "$_POST[partition_by]($_POST[" + $gfp6 = "$object = new $_REQUEST['type']($_REQUEST['id']);" + $gfp7 = "The above example code can be easily exploited by passing in a string such as" // ... ;) + $gfp8 = "Smarty_Internal_Debug::start_render($_template);" + $gfp9 = "?p4yl04d=UNION%20SELECT%20'%20system($_GET['command']);%20?>',2,3%20INTO%20OUTFILE%20'/var/www/w3bsh3ll.php" + $gfp10 = "[][}{;|]\\|\\\\[+=]\\|=>?" + $gfp11 = "(eval (getenv \"EPROLOG\")))" + $gfp12 = "ZmlsZV9nZXRfY29udGVudHMoJ2h0dHA6Ly9saWNlbnNlLm9wZW5jYXJ0LWFwaS5jb20vbGljZW5zZS5waHA/b3JkZXJ" + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = "" wide ascii + $gen_bit_sus45 = "" wide ascii + $gen_bit_sus46 = "shell_" wide ascii + //fp: $gen_bit_sus47 = "Shell" fullword wide ascii + $gen_bit_sus50 = "bypass" wide ascii + $gen_bit_sus52 = " ^ $" wide ascii + $gen_bit_sus53 = ".ssh/authorized_keys" wide ascii + $gen_bit_sus55 = /\w'\.'\w/ wide ascii + $gen_bit_sus56 = /\w\"\.\"\w/ wide ascii + $gen_bit_sus57 = "dumper" wide ascii + $gen_bit_sus59 = "'cmd'" wide ascii + $gen_bit_sus60 = "\"execute\"" wide ascii + $gen_bit_sus61 = "/bin/sh" wide ascii + $gen_bit_sus62 = "Cyber" wide ascii + $gen_bit_sus63 = "portscan" fullword wide ascii + //$gen_bit_sus64 = "\"command\"" fullword wide ascii + //$gen_bit_sus65 = "'command'" fullword wide ascii + $gen_bit_sus66 = "whoami" fullword wide ascii + $gen_bit_sus67 = "$password='" fullword wide ascii + $gen_bit_sus68 = "$password=\"" fullword wide ascii + $gen_bit_sus69 = "$cmd" fullword wide ascii + $gen_bit_sus70 = "\"?>\"." fullword wide ascii + $gen_bit_sus71 = "Hacking" fullword wide ascii + $gen_bit_sus72 = "hacking" fullword wide ascii + $gen_bit_sus73 = ".htpasswd" wide ascii + $gen_bit_sus74 = /\btouch\(\$[^,]{1,30},/ wide ascii + + // very suspicious strings, one is enough + $gen_much_sus7 = "Web Shell" nocase + $gen_much_sus8 = "WebShell" nocase + $gen_much_sus3 = "hidded shell" + $gen_much_sus4 = "WScript.Shell.1" nocase + $gen_much_sus5 = "AspExec" + $gen_much_sus14 = "\\pcAnywhere\\" nocase + $gen_much_sus15 = "antivirus" nocase + $gen_much_sus16 = "McAfee" nocase + $gen_much_sus17 = "nishang" + $gen_much_sus18 = "\"unsafe" fullword wide ascii + $gen_much_sus19 = "'unsafe" fullword wide ascii + $gen_much_sus24 = "exploit" fullword wide ascii + $gen_much_sus25 = "Exploit" fullword wide ascii + $gen_much_sus26 = "TVqQAAMAAA" wide ascii + $gen_much_sus30 = "Hacker" wide ascii + $gen_much_sus31 = "HACKED" fullword wide ascii + $gen_much_sus32 = "hacked" fullword wide ascii + $gen_much_sus33 = "hacker" wide ascii + $gen_much_sus34 = "grayhat" nocase wide ascii + $gen_much_sus35 = "Microsoft FrontPage" wide ascii + $gen_much_sus36 = "Rootkit" wide ascii + $gen_much_sus37 = "rootkit" wide ascii + $gen_much_sus38 = "/*-/*-*/" wide ascii + $gen_much_sus39 = "u\"+\"n\"+\"s" wide ascii + $gen_much_sus40 = "\"e\"+\"v" wide ascii + $gen_much_sus41 = "a\"+\"l\"" wide ascii + $gen_much_sus42 = "\"+\"(\"+\"" wide ascii + $gen_much_sus43 = "q\"+\"u\"" wide ascii + $gen_much_sus44 = "\"u\"+\"e" wide ascii + $gen_much_sus45 = "/*//*/" wide ascii + $gen_much_sus46 = "(\"/*/\"" wide ascii + $gen_much_sus47 = "eval(eval(" wide ascii + // self remove + $gen_much_sus48 = "unlink(__FILE__)" wide ascii + $gen_much_sus49 = "Shell.Users" wide ascii + $gen_much_sus50 = "PasswordType=Regular" wide ascii + $gen_much_sus51 = "-Expire=0" wide ascii + $gen_much_sus60 = "_=$$_" wide ascii + $gen_much_sus61 = "_=$$_" wide ascii + $gen_much_sus62 = "++;$" wide ascii + $gen_much_sus63 = "++; $" wide ascii + $gen_much_sus64 = "_.=$_" wide ascii + $gen_much_sus70 = "-perm -04000" wide ascii + $gen_much_sus71 = "-perm -02000" wide ascii + $gen_much_sus72 = "grep -li password" wide ascii + $gen_much_sus73 = "-name config.inc.php" wide ascii + // touch without parameters sets the time to now, not malicious and gives fp + $gen_much_sus75 = "password crack" wide ascii + $gen_much_sus76 = "mysqlDll.dll" wide ascii + $gen_much_sus77 = "net user" wide ascii + $gen_much_sus80 = "fopen(\".htaccess\",\"w" wide ascii + $gen_much_sus81 = /strrev\(['"]/ wide ascii + $gen_much_sus82 = "PHPShell" fullword wide ascii + $gen_much_sus821= "PHP Shell" fullword wide ascii + $gen_much_sus83 = "phpshell" fullword wide ascii + $gen_much_sus84 = "PHPshell" fullword wide ascii + $gen_much_sus87 = "deface" wide ascii + $gen_much_sus88 = "Deface" wide ascii + $gen_much_sus89 = "backdoor" wide ascii + $gen_much_sus90 = "r00t" fullword wide ascii + $gen_much_sus91 = "xp_cmdshell" fullword wide ascii + $gen_much_sus92 = "base64_decode(base64_decode(" fullword wide ascii + $gen_much_sus93 = "eval(\"/*" wide ascii + $gen_much_sus94 = "=$_COOKIE;" wide ascii + + $gif = { 47 49 46 38 } + + + condition: + //any of them or + ( + ( + ( + $php_short in (0..100) or + $php_short in (filesize-1000..filesize) + ) + and not any of ( $no_* ) + ) + or any of ( $php_new* ) + ) + and + ( ( + not any of ( $cfp* ) and + ( + any of ( $callback* ) or + all of ( $m_callback* ) + ) + ) + or ( + any of ( $cpayload* ) or + all of ( $m_cpayload_preg_filter* ) + ) + ) and ( + any of ( $cobfs* ) + ) + and + ( filesize < 1KB or + ( filesize < 3KB and + ( ( + $gif at 0 or + ( + filesize < 4KB and + ( + 1 of ( $gen_much_sus* ) or + 2 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 20KB and + ( + 2 of ( $gen_much_sus* ) or + 3 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 50KB and + ( + 2 of ( $gen_much_sus* ) or + 4 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 100KB and + ( + 2 of ( $gen_much_sus* ) or + 6 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 150KB and + ( + 3 of ( $gen_much_sus* ) or + 7 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 500KB and + ( + 4 of ( $gen_much_sus* ) or + 8 of ( $gen_bit_sus* ) + ) + ) + ) + or #obf1 > 10 ) ) ) +} + +rule webshell_php_includer_eval +{ + meta: + description = "PHP webshell which eval()s another included file" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + hash = "3a07e9188028efa32872ba5b6e5363920a6b2489" + date = "2021/01/13" + modified = "2023-04-05" + + strings: + $payload1 = "eval" fullword wide ascii + $payload2 = "assert" fullword wide ascii + $include1 = "$_FILE" wide ascii + $include2 = "include" wide ascii + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = " 20 and filesize < 200 and ( + ( + ( + $php_short in (0..100) or + $php_short in (filesize-1000..filesize) + ) + and not any of ( $no_* ) + ) + or any of ( $php_new* ) + ) + and ( + any of ( $dynamic* ) + ) + and not any of ( $pd_fp* ) +} + +rule webshell_php_dynamic_big +{ + meta: + description = "PHP webshell using $a($code) for kind of eval with encoded blob to decode, e.g. b374k" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + date = "2021/02/07" + modified = "2023-04-05" + score = 50 + hash = "6559bfc4be43a55c6bb2bd867b4c9b929713d3f7f6de8111a3c330f87a9b302c" + hash = "9e82c9c2fa64e26fd55aa18f74759454d89f968068d46b255bd4f41eb556112e" + hash = "6def5296f95e191a9c7f64f7d8ac5c529d4a4347ae484775965442162345dc93" + hash = "dadfdc4041caa37166db80838e572d091bb153815a306c8be0d66c9851b98c10" + hash = "0a4a292f6e08479c04e5c4fdc3857eee72efa5cd39db52e4a6e405bf039928bd" + hash = "4326d10059e97809fb1903eb96fd9152cc72c376913771f59fa674a3f110679e" + hash = "b49d0f942a38a33d2b655b1c32ac44f19ed844c2479bad6e540f69b807dd3022" + hash = "575edeb905b434a3b35732654eedd3afae81e7d99ca35848c509177aa9bf9eef" + hash = "ee34d62e136a04e2eaf84b8daa12c9f2233a366af83081a38c3c973ab5e2c40f" + + strings: + + //strings from private rule capa_bin_files + $dex = { 64 65 ( 78 | 79 ) 0a 30 } + $pack = { 50 41 43 4b 00 00 00 02 00 } + + //strings from private rule capa_php_new_long + // no = + $new_php2 = "" wide ascii + $gen_bit_sus45 = "" wide ascii + $gen_bit_sus46 = "shell_" wide ascii + //fp: $gen_bit_sus47 = "Shell" fullword wide ascii + $gen_bit_sus50 = "bypass" wide ascii + $gen_bit_sus52 = " ^ $" wide ascii + $gen_bit_sus53 = ".ssh/authorized_keys" wide ascii + $gen_bit_sus55 = /\w'\.'\w/ wide ascii + $gen_bit_sus56 = /\w\"\.\"\w/ wide ascii + $gen_bit_sus57 = "dumper" wide ascii + $gen_bit_sus59 = "'cmd'" wide ascii + $gen_bit_sus60 = "\"execute\"" wide ascii + $gen_bit_sus61 = "/bin/sh" wide ascii + $gen_bit_sus62 = "Cyber" wide ascii + $gen_bit_sus63 = "portscan" fullword wide ascii + $gen_bit_sus65 = "whoami" fullword wide ascii + $gen_bit_sus67 = "$password='" fullword wide ascii + $gen_bit_sus68 = "$password=\"" fullword wide ascii + $gen_bit_sus69 = "$cmd" fullword wide ascii + $gen_bit_sus70 = "\"?>\"." fullword wide ascii + $gen_bit_sus71 = "Hacking" fullword wide ascii + $gen_bit_sus72 = "hacking" fullword wide ascii + $gen_bit_sus73 = ".htpasswd" wide ascii + $gen_bit_sus74 = /\btouch\(\$[^,]{1,30},/ wide ascii + $gen_bit_sus99 = "$password = " wide ascii + $gen_bit_sus100 = "();$" wide ascii + + // very suspicious strings, one is enough + $gen_much_sus7 = "Web Shell" nocase + $gen_much_sus8 = "WebShell" nocase + $gen_much_sus3 = "hidded shell" + $gen_much_sus4 = "WScript.Shell.1" nocase + $gen_much_sus5 = "AspExec" + $gen_much_sus14 = "\\pcAnywhere\\" nocase + $gen_much_sus15 = "antivirus" nocase + $gen_much_sus16 = "McAfee" nocase + $gen_much_sus17 = "nishang" + $gen_much_sus18 = "\"unsafe" fullword wide ascii + $gen_much_sus19 = "'unsafe" fullword wide ascii + $gen_much_sus24 = "exploit" fullword wide ascii + $gen_much_sus25 = "Exploit" fullword wide ascii + $gen_much_sus26 = "TVqQAAMAAA" wide ascii + $gen_much_sus30 = "Hacker" wide ascii + $gen_much_sus31 = "HACKED" fullword wide ascii + $gen_much_sus32 = "hacked" fullword wide ascii + $gen_much_sus33 = "hacker" wide ascii + $gen_much_sus34 = "grayhat" nocase wide ascii + $gen_much_sus35 = "Microsoft FrontPage" wide ascii + $gen_much_sus36 = "Rootkit" wide ascii + $gen_much_sus37 = "rootkit" wide ascii + $gen_much_sus38 = "/*-/*-*/" wide ascii + $gen_much_sus39 = "u\"+\"n\"+\"s" wide ascii + $gen_much_sus40 = "\"e\"+\"v" wide ascii + $gen_much_sus41 = "a\"+\"l\"" wide ascii + $gen_much_sus42 = "\"+\"(\"+\"" wide ascii + $gen_much_sus43 = "q\"+\"u\"" wide ascii + $gen_much_sus44 = "\"u\"+\"e" wide ascii + $gen_much_sus45 = "/*//*/" wide ascii + $gen_much_sus46 = "(\"/*/\"" wide ascii + $gen_much_sus47 = "eval(eval(" wide ascii + // self remove + $gen_much_sus48 = "unlink(__FILE__)" wide ascii + $gen_much_sus49 = "Shell.Users" wide ascii + $gen_much_sus50 = "PasswordType=Regular" wide ascii + $gen_much_sus51 = "-Expire=0" wide ascii + $gen_much_sus60 = "_=$$_" wide ascii + $gen_much_sus61 = "_=$$_" wide ascii + $gen_much_sus62 = "++;$" wide ascii + $gen_much_sus63 = "++; $" wide ascii + $gen_much_sus64 = "_.=$_" wide ascii + $gen_much_sus70 = "-perm -04000" wide ascii + $gen_much_sus71 = "-perm -02000" wide ascii + $gen_much_sus72 = "grep -li password" wide ascii + $gen_much_sus73 = "-name config.inc.php" wide ascii + // touch without parameters sets the time to now, not malicious and gives fp + $gen_much_sus75 = "password crack" wide ascii + $gen_much_sus76 = "mysqlDll.dll" wide ascii + $gen_much_sus77 = "net user" wide ascii + $gen_much_sus80 = "fopen(\".htaccess\",\"w" wide ascii + $gen_much_sus81 = /strrev\(['"]/ wide ascii + $gen_much_sus82 = "PHPShell" fullword wide ascii + $gen_much_sus821= "PHP Shell" fullword wide ascii + $gen_much_sus83 = "phpshell" fullword wide ascii + $gen_much_sus84 = "PHPshell" fullword wide ascii + $gen_much_sus87 = "deface" wide ascii + $gen_much_sus88 = "Deface" wide ascii + $gen_much_sus89 = "backdoor" wide ascii + $gen_much_sus90 = "r00t" fullword wide ascii + $gen_much_sus91 = "xp_cmdshell" fullword wide ascii + $gen_much_sus92 = "DEFACE" fullword wide ascii + $gen_much_sus93 = "Bypass" fullword wide ascii + $gen_much_sus94 = /eval\s{2,20}\(/ nocase wide ascii + $gen_much_sus100 = "rot13" wide ascii + $gen_much_sus101 = "ini_set('error_log'" wide ascii + $gen_much_sus102 = "base64_decode(base64_decode(" wide ascii + $gen_much_sus103 = "=$_COOKIE;" wide ascii + // ¦{1}.$ .. |{9}.$ + $gen_much_sus104 = { C0 A6 7B 3? 7D 2E 24 } + $gen_much_sus105 = "$GLOBALS[\"__" wide ascii + // those calculations don't make really sense :) + $gen_much_sus106 = ")-0)" wide ascii + $gen_much_sus107 = "-0)+" wide ascii + $gen_much_sus108 = "+0)+" wide ascii + $gen_much_sus109 = "+(0/" wide ascii + $gen_much_sus110 = "+(0+" wide ascii + $gen_much_sus111 = "extract($_REQUEST)" wide ascii + $gen_much_sus112 = " 2 and + #weevely4 > 1 + ) + ) or ( + filesize < 4KB and + ( + 1 of ( $gen_much_sus* ) or + 2 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 20KB and + ( + 2 of ( $gen_much_sus* ) or + 4 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 50KB and + ( + 3 of ( $gen_much_sus* ) or + 5 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 100KB and + ( + 3 of ( $gen_much_sus* ) or + 6 of ( $gen_bit_sus* ) + ) + ) or ( + filesize < 160KB and + ( + 3 of ( $gen_much_sus* ) or + 7 of ( $gen_bit_sus* ) or + ( + // php files which use strings in the full ascii8 spectrum have a much hioher deviation than normal php-code + // e.g. 4057005718bb18b51b02d8b807265f8df821157ac47f78ace77f21b21fc77232 + math.deviation(500, filesize-500, 89.0) > 70 + // uncomment and include an "and" above for debugging, also import on top of file. needs yara 4.2.0 + //console.log("high deviation") and + //console.log(math.deviation(500, filesize-500, 89.0)) + ) + // TODO: requires yara 4.2.0 so wait a bit until that's more common + //or + //( + // big file and just one line = minified + //filesize > 10KB and + //math.count(0x0A) < 2 + //) + ) + ) or ( + filesize < 500KB and + ( + 4 of ( $gen_much_sus* ) or + 8 of ( $gen_bit_sus* ) or + #gen_much_sus104 > 4 + + ) + ) + ) or ( + // file shouldn't be too small to have big enough data for math.entropy + filesize > 2KB and filesize < 1MB and + ( + ( + // base64 : + // ignore first and last 500bytes because they usually contain code for decoding and executing + math.entropy(500, filesize-500) >= 5.7 and + // encoded text has a higher mean than text or code because it's missing the spaces and special chars with the low numbers + math.mean(500, filesize-500) > 80 and + // deviation of base64 is ~20 according to CyberChef_v9.21.0.html#recipe=Generate_Lorem_Ipsum(3,'Paragraphs')To_Base64('A-Za-z0-9%2B/%3D')To_Charcode('Space',10)Standard_Deviation('Space') + // lets take a bit more because it might not be pure base64 also include some xor, shift, replacement, ... + // 89 is the mean of the base64 chars + math.deviation(500, filesize-500, 89.0) < 23 + ) or ( + // gzinflated binary sometimes used in php webshells + // ignore first and last 500bytes because they usually contain code for decoding and executing + math.entropy(500, filesize-500) >= 7.7 and + // encoded text has a higher mean than text or code because it's missing the spaces and special chars with the low numbers + math.mean(500, filesize-500) > 120 and + math.mean(500, filesize-500) < 136 and + // deviation of base64 is ~20 according to CyberChef_v9.21.0.html#recipe=Generate_Lorem_Ipsum(3,'Paragraphs')To_Base64('A-Za-z0-9%2B/%3D')To_Charcode('Space',10)Standard_Deviation('Space') + // lets take a bit more because it might not be pure base64 also include some xor, shift, replacement, ... + // 89 is the mean of the base64 chars + math.deviation(500, filesize-500, 89.0) > 65 + ) + ) + ) + ) +} + +rule webshell_php_encoded_big +{ + meta: + description = "PHP webshell using some kind of eval with encoded blob to decode" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + date = "2021/02/07" + modified = "2023-04-05" + score = 50 + hash = "1d4b374d284c12db881ba42ee63ebce2759e0b14" + + strings: + + //strings from private rule capa_php_new + $new_php1 = /<\?=[\w\s@$]/ wide ascii + $new_php2 = " 2KB and + ( + // base64 : + // ignore first and last 500bytes because they usually contain code for decoding and executing + math.entropy(500, filesize-500) >= 5.7 and + // encoded text has a higher mean than text or code because it's missing the spaces and special chars with the low numbers + math.mean(500, filesize-500) > 80 and + // deviation of base64 is ~20 according to CyberChef_v9.21.0.html#recipe=Generate_Lorem_Ipsum(3,'Paragraphs')To_Base64('A-Za-z0-9%2B/%3D')To_Charcode('Space',10)Standard_Deviation('Space') + // lets take a bit more because it might not be pure base64 also include some xor, shift, replacement, ... + // 89 is the mean of the base64 chars + math.deviation(500, filesize-500, 89.0) < 24 + ) or ( + // gzinflated binary sometimes used in php webshells + // ignore first and last 500bytes because they usually contain code for decoding and executing + math.entropy(500, filesize-500) >= 7.7 and + // encoded text has a higher mean than text or code because it's missing the spaces and special chars with the low numbers + math.mean(500, filesize-500) > 120 and + math.mean(500, filesize-500) < 136 and + // deviation of base64 is ~20 according to CyberChef_v9.21.0.html#recipe=Generate_Lorem_Ipsum(3,'Paragraphs')To_Base64('A-Za-z0-9%2B/%3D')To_Charcode('Space',10)Standard_Deviation('Space') + // lets take a bit more because it might not be pure base64 also include some xor, shift, replacement, ... + // 89 is the mean of the base64 chars + math.deviation(500, filesize-500, 89.0) > 65 + ) + ) + +} + +rule webshell_php_generic_backticks +{ + meta: + description = "Generic PHP webshell which uses backticks 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)" + date = "2021/01/07" + modified = "2023-04-05" + hash = "339f32c883f6175233f0d1a30510caa52fdcaa37" + hash = "8db86ad90883cd208cf86acd45e67c03f994998804441705d690cb6526614d00" + hash = "af987b0eade03672c30c095cee0c7c00b663e4b3c6782615fb7e430e4a7d1d75" + hash = "67339f9e70a17af16cf51686918cbe1c0604e129950129f67fe445eaff4b4b82" + hash = "144e242a9b219c5570973ca26d03e82e9fbe7ba2773305d1713288ae3540b4ad" + hash = "8db86ad90883cd208cf86acd45e67c03f994998804441705d690cb6526614d00" + + strings: + $backtick = /`\s*{?\$(_POST\[|_GET\[|_REQUEST\[|_SERVER\['HTTP_)/ wide ascii + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = "My PHP Shell + $pbs35 = /@\$_GET\s?\[\d\]\)\.@\$_\(\$_GET\s?\[\d\]\)/ wide ascii + $pbs36 = /@\$_GET\s?\[\d\]\)\.@\$_\(\$_POST\s?\[\d\]\)/ wide ascii + $pbs37 = /@\$_POST\s?\[\d\]\)\.@\$_\(\$_GET\s?\[\d\]\)/ wide ascii + $pbs38 = /@\$_POST\[\d\]\)\.@\$_\(\$_POST\[\d\]\)/ wide ascii + $pbs39 = /@\$_REQUEST\[\d\]\)\.@\$_\(\$_REQUEST\[\d\]\)/ wide ascii + $pbs42 = "array(\"find config.inc.php files\", \"find / -type f -name config.inc.php\")" wide ascii + $pbs43 = "$_SERVER[\"\\x48\\x54\\x54\\x50" wide ascii + $pbs52 = "preg_replace(\"/[checksql]/e\"" + $pbs53 = "='http://www.zjjv.com'" + $pbs54 = "=\"http://www.zjjv.com\"" + + $pbs60 = /setting\["AccountType"\]\s?=\s?3/ + $pbs61 = "~+d()\"^\"!{+{}" + $pbs62 = "use function \\eval as " + $pbs63 = "use function \\assert as " + $pbs64 = "eval(`/*" wide ascii + $pbs65 = "/* Reverse engineering of this file is strictly prohibited. File protected by copyright law and provided under license. */" wide ascii + $pbs66 = "Tas9er" fullword wide ascii + $pbs67 = "\"TSOP_\";" fullword wide ascii // reverse _POST + $pbs68 = "str_rot13('nffreg')" wide ascii // rot13(assert) + $pbs69 = "=`{$'" wide ascii + $pbs70 = "{'_'.$_}[\"_\"](${'_'.$_}[\"_" wide ascii + $pbs71 = "\"e45e329feb5d925b\"" wide ascii + $pbs72 = "| PHP FILE MANAGER" wide ascii + $pbs73 = "\neval(htmlspecialchars_decode(gzinflate(base64_decode($" wide ascii + $pbs74 = "/*\n\nShellindir.org\n\n*/" wide ascii + $pbs75 = "$shell = 'uname -a; w; id; /bin/sh -i';" wide ascii + $pbs76 = "'password' . '/' . 'id' . '/' . " wide ascii + $pbs77 = "= create_function /*" wide ascii + $pbs78 = "W3LL M!N! SH3LL" wide ascii + $pbs79 = "extract($_REQUEST)&&@$" wide ascii + $pbs80 = "\"P-h-p-S-p-y\"" wide ascii + $pbs81 = "\\x5f\\x72\\x6f\\x74\\x31\\x33" wide ascii + $pbs82 = "\\x62\\x61\\x73\\x65\\x36\\x34\\x5f" wide ascii + $pbs83 = "*/base64_decode/*" wide ascii + $pbs84 = "\n@eval/*" wide ascii + $pbs85 = "*/eval/*" wide ascii + $pbs86 = "*/ array /*" wide ascii + $pbs87 = "2jtffszJe" wide ascii + $pbs88 = "edocne_46esab" wide ascii + $pbs89 = "eval($_HEADERS" wide ascii + $pbs90 = ">Infinity-Sh3ll<" ascii + + $front1 = "\"" nocase wide ascii + + //strings from private rule capa_php_old_safe + $php_short = "" wide ascii + // prevent xml and asp from hitting with the short tag + $no_xml1 = "assert(strpos($styles, $" + $gfp3 = "$module = new $_GET['module']($_GET['scope']);" + $gfp4 = "$plugin->$_POST['action']($_POST['id']);" + $gfp5 = "$_POST[partition_by]($_POST[" + $gfp6 = "$object = new $_REQUEST['type']($_REQUEST['id']);" + $gfp7 = "The above example code can be easily exploited by passing in a string such as" // ... ;) + $gfp8 = "Smarty_Internal_Debug::start_render($_template);" + $gfp9 = "?p4yl04d=UNION%20SELECT%20'%20system($_GET['command']);%20?>',2,3%20INTO%20OUTFILE%20'/var/www/w3bsh3ll.php" + $gfp10 = "[][}{;|]\\|\\\\[+=]\\|=>?" + $gfp11 = "(eval (getenv \"EPROLOG\")))" + $gfp12 = "ZmlsZV9nZXRfY29udGVudHMoJ2h0dHA6Ly9saWNlbnNlLm9wZW5jYXJ0LWFwaS5jb20vbGljZW5zZS5waHA/b3JkZXJ" + + //strings from private rule capa_php_input + $inp1 = "php://input" wide ascii + $inp2 = /_GET\s?\[/ wide ascii + // for passing $_GET to a function + $inp3 = /\(\s?\$_GET\s?\)/ wide ascii + $inp4 = /_POST\s?\[/ wide ascii + $inp5 = /\(\s?\$_POST\s?\)/ wide ascii + $inp6 = /_REQUEST\s?\[/ wide ascii + $inp7 = /\(\s?\$_REQUEST\s?\)/ wide ascii + // PHP automatically adds all the request headers into the $_SERVER global array, prefixing each header name by the "HTTP_" string, so e.g. @eval($_SERVER['HTTP_CMD']) will run any code in the HTTP header CMD + $inp15 = "_SERVER['HTTP_" wide ascii + $inp16 = "_SERVER[\"HTTP_" wide ascii + $inp17 = /getenv[\t ]{0,20}\([\t ]{0,20}['"]HTTP_/ wide ascii + $inp18 = "array_values($_SERVER)" wide ascii + $inp19 = /file_get_contents\("https?:\/\// wide ascii + + condition: + filesize < 700KB and ( + ( + ( + $php_short in (0..100) or + $php_short in (filesize-1000..filesize) + ) + and not any of ( $no_* ) + ) + or any of ( $php_new* ) + ) + and not ( + any of ( $gfp* ) + ) + and + ( 1 of ( $sstring* ) and ( + any of ( $inp* ) + ) + ) +} + +rule webshell_php_in_htaccess +{ + meta: + description = "Use Apache .htaccess to execute php code inside .htaccess" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + date = "2021/01/07" + modified = "2023-04-05" + hash = "c026d4512a32d93899d486c6f11d1e13b058a713" + + strings: + $hta = "AddType application/x-httpd-php .htaccess" wide ascii + + condition: + filesize <100KB and $hta +} + +rule webshell_php_function_via_get +{ + meta: + description = "Webshell which sends eval/assert via GET" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + date = "2021/01/09" + modified = "2023-04-05" + hash = "ce739d65c31b3c7ea94357a38f7bd0dc264da052d4fd93a1eabb257f6e3a97a6" + hash = "d870e971511ea3e082662f8e6ec22e8a8443ca79" + hash = "73fa97372b3bb829835270a5e20259163ecc3fdbf73ef2a99cb80709ea4572be" + + strings: + $sr0 = /\$_GET\s?\[.{1,30}\]\(\$_GET\s?\[/ wide ascii + $sr1 = /\$_POST\s?\[.{1,30}\]\(\$_GET\s?\[/ wide ascii + $sr2 = /\$_POST\s?\[.{1,30}\]\(\$_POST\s?\[/ wide ascii + $sr3 = /\$_GET\s?\[.{1,30}\]\(\$_POST\s?\[/ wide ascii + $sr4 = /\$_REQUEST\s?\[.{1,30}\]\(\$_REQUEST\s?\[/ wide ascii + $sr5 = /\$_SERVER\s?\[HTTP_.{1,30}\]\(\$_SERVER\s?\[HTTP_/ wide ascii + + //strings from private rule php_false_positive + // try to use only strings which would be flagged by themselves as suspicious by other rules, e.g. eval + // a good choice is a string with good atom quality = ideally 4 unusual characters next to each other + $gfp1 = "eval(\"return [$serialised_parameter" // elgg + $gfp2 = "$this->assert(strpos($styles, $" + $gfp3 = "$module = new $_GET['module']($_GET['scope']);" + $gfp4 = "$plugin->$_POST['action']($_POST['id']);" + $gfp5 = "$_POST[partition_by]($_POST[" + $gfp6 = "$object = new $_REQUEST['type']($_REQUEST['id']);" + $gfp7 = "The above example code can be easily exploited by passing in a string such as" // ... ;) + $gfp8 = "Smarty_Internal_Debug::start_render($_template);" + $gfp9 = "?p4yl04d=UNION%20SELECT%20'%20system($_GET['command']);%20?>',2,3%20INTO%20OUTFILE%20'/var/www/w3bsh3ll.php" + $gfp10 = "[][}{;|]\\|\\\\[+=]\\|=>?" + $gfp11 = "(eval (getenv \"EPROLOG\")))" + $gfp12 = "ZmlsZV9nZXRfY29udGVudHMoJ2h0dHA6Ly9saWNlbnNlLm9wZW5jYXJ0LWFwaS5jb20vbGljZW5zZS5waHA/b3JkZXJ" + + condition: + filesize < 500KB and not ( + any of ( $gfp* ) + ) + and any of ( $sr* ) +} + +rule webshell_php_writer +{ + meta: + description = "PHP webshell which only writes an uploaded file to disk" + license = "Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE" + author = "Arnim Rupp (https://github.com/ruppde)" + date = "2021/04/17" + modified = "2023-04-05" + score = 50 + hash = "ec83d69512aa0cc85584973f5f0850932fb1949fb5fb2b7e6e5bbfb121193637" + hash = "407c15f94a33232c64ddf45f194917fabcd2e83cf93f38ee82f9720e2635fa64" + + strings: + $sus3 = "'upload'" wide ascii + $sus4 = "\"upload\"" wide ascii + $sus5 = "\"Upload\"" wide ascii + $sus6 = "gif89" wide ascii + //$sus13= "