From e3b724a688ed658214660b28ed3763e8db9e3f96 Mon Sep 17 00:00:00 2001 From: xarkes Date: Wed, 30 Mar 2016 09:50:01 +0200 Subject: Add ASP webshell detection --- php-malware-finder/asp.yara | 46 +++++ php-malware-finder/common.yara | 145 +++++++++++++ php-malware-finder/docroot-check.sh | 2 +- php-malware-finder/generate_whitelist.py | 7 +- php-malware-finder/malwares.yara | 283 -------------------------- php-malware-finder/php.yara | 145 +++++++++++++ php-malware-finder/phpmalwarefinder | 59 +++++- php-malware-finder/samples/classic/cmdasp.asp | 55 +++++ php-malware-finder/tests.sh | 13 ++ 9 files changed, 461 insertions(+), 294 deletions(-) create mode 100644 php-malware-finder/asp.yara create mode 100644 php-malware-finder/common.yara delete mode 100644 php-malware-finder/malwares.yara create mode 100644 php-malware-finder/php.yara create mode 100644 php-malware-finder/samples/classic/cmdasp.asp diff --git a/php-malware-finder/asp.yara b/php-malware-finder/asp.yara new file mode 100644 index 0000000..26483a1 --- /dev/null +++ b/php-malware-finder/asp.yara @@ -0,0 +1,46 @@ +import "hash" +include "whitelist.yara" +include "common.yara" + +global private rule IsAsp +{ + strings: + $asp = /<%|@{}/ + $cs = /using .{4,25};/ + + condition: + ($asp or $cs) and filesize < 5MB +} + +rule ObfuscatedAsp +{ + strings: + $ = /LANGUAGE\s*=\s*VBScript.Encode/ nocase + $ = /(".{1,5}"&){5,}/ // "e"&"v"&"a"&"l" + $ = /(chr\s*\(\s*\d{1,3}\s*\)[+\)\s]*){5,}/ nocase // chr(114)+chr(101)+chr(113)+chr(117)+chr(101) + $stunnix = /execute\("dIm [a-z]*"\):[a-z]* = unescape/ nocase // http://stunnix.com/ + + condition: + any of them and not IsWhitelisted +} + +rule ObfuscatedEncodingAsp +{ + strings: + $unicode = /\\u[a-f0-9]/ nocase + $html_encode = /&#([0-9]{3}|x[a-f0-9]{2});/ nocase + + condition: + (#unicode >= 10 or #html_encode >= 10) and not IsWhitelisted +} + +rule DangerousAsp +{ + strings: + $ = /createobject\s*\(\s*"(WScript\.Shell|WScript\.Network|Shell\.Application|Scripting\.FileSystemObject|ScriptControl)/ nocase + $ = /eval\s*\({0,1}\s*request/ nocase + + condition: + 2 of them and not IsWhitelisted +} + diff --git a/php-malware-finder/common.yara b/php-malware-finder/common.yara new file mode 100644 index 0000000..38b6726 --- /dev/null +++ b/php-malware-finder/common.yara @@ -0,0 +1,145 @@ +private rule IRC +{ + strings: + $ = "USER" fullword + $ = "PASS" fullword + $ = "PRIVMSG" fullword + $ = "MODE" fullword + $ = "PING" fullword + $ = "PONG" fullword + $ = "JOIN" fullword + $ = "PART" fullword + + condition: + 5 of them +} + +private rule base64 +{ + strings: + $eval = "ZXZhbCg" + $system = "c3lzdGVt" + $preg_replace = "cHJlZ19yZXBsYWNl" + $exec = "ZXhlYyg" + $base64_decode = "YmFzZTY0X2RlY29kZ" + $perl_shebang = "IyEvdXNyL2Jpbi9wZXJsCg" + $cmd_exe = "Y21kLmV4ZQ" + $powershell = "cG93ZXJzaGVsbC5leGU" + + condition: + any of them +} + +private rule hex +{ + strings: + $globals = "\\x47\\x4c\\x4f\\x42\\x41\\x4c\\x53" nocase + $eval = "\\x65\\x76\\x61\\x6C\\x28" nocase + $exec = "\\x65\\x78\\x65\\x63" nocase + $system = "\\x73\\x79\\x73\\x74\\x65\\x6d" nocase + $preg_replace = "\\x70\\x72\\x65\\x67\\x5f\\x72\\x65\\x70\\x6c\\x61\\x63\\x65" nocase + $http_user_agent = "\\x48\\124\\x54\\120\\x5f\\125\\x53\\105\\x52\\137\\x41\\107\\x45\\116\\x54" nocase + + condition: + any of them +} + +rule SuspiciousEncoding +{ + condition: + base64 or hex +} + +rule DodgyStrings +{ + strings: + $ = ".bash_history" + $ = /AddType\s+application\/x-httpd-php/ nocase + $ = /php_value\s*auto_prepend_file/ nocase + $ = /SecFilterEngine\s+Off/ nocase // disable modsec + $ = /Add(Handler|Type|OutputFilter)\s+[^\s]+\s+\.htaccess/ nocase + $ = ".mysql_history" + $ = ".ssh/authorized_keys" + $ = "/(.*)/e" // preg_replace code execution + $ = "/../../../" + $ = "/etc/passwd" + $ = "/etc/proftpd.conf" + $ = "/etc/resolv.conf" + $ = "/etc/shadow" + $ = "/etc/syslog.conf" + $ = "/proc/cpuinfo" fullword + $ = "/var/log/lastlog" + $ = "/windows/system32/" + $ = "LOAD DATA LOCAL INFILE" nocase + $ = "WScript.Shell" + $ = "WinExec" + $ = "b374k" fullword nocase + $ = "backdoor" fullword nocase + $ = /(c99|r57|fx29)shell/ + $ = "cmd.exe" fullword nocase + $ = "powershell.exe" fullword nocase + $ = /defac(ed|er|ement|ing)/ fullword nocase + $ = "evilc0ders" fullword nocase + $ = "exploit" fullword nocase + $ = "find . -type f" fullword + $ = "hashcrack" nocase + $ = "id_rsa" fullword + $ = "ipconfig" fullword nocase + $ = "kernel32.dll" fullword nocase + $ = "kingdefacer" nocase + $ = "Wireghoul" nocase fullword + $ = "libpcprofile" // CVE-2010-3856 local root + $ = "locus7s" nocase + $ = "ls -la" fullword + $ = "meterpreter" fullword + $ = "nc -l" fullword + $ = "php://" + $ = "ps -aux" fullword + $ = "rootkit" fullword nocase + $ = "slowloris" fullword nocase + $ = "suhosin.executor.func.blacklist" + $ = "sun-tzu" fullword nocase // Because quotes from the Art of War is mandatory for any cool webshell. + $ = "uname -a" fullword + $ = "warez" fullword nocase + $ = "whoami" fullword + $ = /(reverse|web|cmd)\s*shell/ nocase + $ = /-perm -0[24]000/ // find setuid files + $ = /\/bin\/(ba)?sh/ fullword + $ = /hack(ing|er|ed)/ nocase + $ = /xp_(execresultset|regenumkeys|cmdshell|filelist)/ + + $vbs = /language\s*=\s*vbscript/ nocase + $asp = "scripting.filesystemobject" nocase + + condition: + IRC or 2 of them and not IsWhitelisted +} + +rule Websites +{ + strings: + $ = "1337day.com" nocase + $ = "antichat.ru" nocase + $ = "ccteam.ru" nocase + $ = "crackfor" nocase + $ = "darkc0de" nocase + $ = "egyspider.eu" nocase + $ = "exploit-db.com" nocase + $ = "fopo.com.ar" nocase /* Free Online Php Obfuscator */ + $ = "hashchecker.com" nocase + $ = "hashkiller.com" nocase + $ = "md5crack.com" nocase + $ = "md5decrypter.com" nocase + $ = "milw0rm.com" nocase + $ = "milw00rm.com" nocase + $ = "packetstormsecurity" nocase + $ = "rapid7.com" nocase + $ = "securityfocus" nocase + $ = "shodan.io" nocase + $ = "github.com/b374k/b374k" nocase + $ = "mumaasp.com" nocase + + condition: + any of them and not IsWhitelisted +} + diff --git a/php-malware-finder/docroot-check.sh b/php-malware-finder/docroot-check.sh index 4d280c2..fa67a11 100644 --- a/php-malware-finder/docroot-check.sh +++ b/php-malware-finder/docroot-check.sh @@ -2,7 +2,7 @@ PATH=/usr/bin:/bin:/sbin:/usr/sbin apache_confdir="/etc/apache2/sites-available" -pmf_conf="/etc/phpmalwarefinder/malwares.yara" +pmf_conf="/etc/phpmalwarefinder/php.yara" pmf_cachedir="/tmp" # grab the different document roots to scan each and everyone of them diff --git a/php-malware-finder/generate_whitelist.py b/php-malware-finder/generate_whitelist.py index e54de72..ca9fa2d 100644 --- a/php-malware-finder/generate_whitelist.py +++ b/php-malware-finder/generate_whitelist.py @@ -13,8 +13,13 @@ except ImportError: if len(sys.argv) != 3: print 'Usage: %s name_of_the_rule_and_version folder_to_scan' % sys.argv[0] + sys.exit(1) + +if not os.path.isdir(sys.argv[2]): + print '%s is not a folder !' % sys.argv[2] + sys.exit(1) -rules = yara.compile('./malwares.yara', includes=True, error_on_warning=True) +rules = yara.compile('./php.yara', includes=True, error_on_warning=True) output_list = list() diff --git a/php-malware-finder/malwares.yara b/php-malware-finder/malwares.yara deleted file mode 100644 index f4e2dac..0000000 --- a/php-malware-finder/malwares.yara +++ /dev/null @@ -1,283 +0,0 @@ -import "hash" -include "whitelist.yara" - -/* - Detect: - - phpencode.org - - http://www.pipsomania.com/best_php_obfuscator.do - - http://atomiku.com/online-php-code-obfuscator/ - - http://www.webtoolsvn.com/en-decode/ - - http://obfuscator.uk/example/ - - http://w3webtools.com/encode-php-online/ - - http://www.joeswebtools.com/security/php-obfuscator/ - - https://github.com/epinna/weevely3 - - http://cipherdesign.co.uk/service/php-obfuscator - - http://sysadmin.cyklodev.com/online-php-obfuscator/ - - http://mohssen.org/SpinObf.php - - https://code.google.com/p/carbylamine/ - - https://github.com/tennc/webshell - - - https://github.com/wireghoul/htshells - - Thanks to: - - https://stackoverflow.com/questions/3115559/exploitable-php-functions -*/ - -global private rule IsPhp -{ - strings: - $php = /<\?[^x]/ - - condition: - $php and filesize < 5MB -} - -private rule IRC -{ - strings: - $ = "USER" fullword - $ = "PASS" fullword - $ = "PRIVMSG" fullword - $ = "MODE" fullword - $ = "PING" fullword - $ = "PONG" fullword - $ = "JOIN" fullword - $ = "PART" fullword - - condition: - 5 of them -} - -private rule CloudFlareBypass -{ - strings: - $ = "chk_jschl" - $ = "jschl_vc" - $ = "jschl_answer" - - condition: - 2 of them // Better be safe than sorry -} - -rule ObfuscatedPhp -{ - strings: - $eval = /(<\?php|[;{}])\s*@?(eval|preg_replace|system|assert|passthru|(pcntl_)?exec|win_shell_execute|call_user_func(_array)?)\s*\(/ nocase // ;eval( <- this is dodgy - $b374k = "'ev'.'al'" - $align = /(\$\w+=[^;]*)*;\$\w+=@?\$\w+\(/ //b374k - $weevely3 = /\$\w=\$[a-zA-Z]\('',\$\w\);\$\w\(\);/ // weevely3 launcher - $c99_launcher = /;\$\w+\(\$\w+(,\s?\$\w+)+\);/ // http://bartblaze.blogspot.fr/2015/03/c99shell-not-dead.html - $variable_variable = /\${\$[0-9a-zA-z]+}/ - $too_many_chr = /(chr\([\d]+\)\.){2}/ // concatenation of more than two `chr()` - $concat = /(\$[^\n\r]+\.){5}/ // concatenation of more than 5 words - $var_as_func = /\$_(GET|POST|COOKIE|REQUEST)\s*\[[^\]]+\]\s*\(/ - $gif = /^GIF89/ -condition: - any of them and not IsWhitelisted -} - -private rule base64 -{ - strings: - $eval = "ZXZhbCg" - $system = "c3lzdGVt" - $preg_replace = "cHJlZ19yZXBsYWNl" - $exec = "ZXhlYyg" - $base64_decode = "YmFzZTY0X2RlY29kZ" - $perl_shebang = "IyEvdXNyL2Jpbi9wZXJsCg" - condition: - any of them -} - -private rule hex -{ - strings: - $globals = "\\x47\\x4c\\x4f\\x42\\x41\\x4c\\x53" nocase - $eval = "\\x65\\x76\\x61\\x6C\\x28" nocase - $exec = "\\x65\\x78\\x65\\x63" nocase - $system = "\\x73\\x79\\x73\\x74\\x65\\x6d" nocase - $preg_replace = "\\x70\\x72\\x65\\x67\\x5f\\x72\\x65\\x70\\x6c\\x61\\x63\\x65" nocase - $http_user_agent = "\\x48\\124\\x54\\120\\x5f\\125\\x53\\105\\x52\\137\\x41\\107\\x45\\116\\x54" nocase - - condition: - any of them -} - -rule SuspiciousEncoding -{ - condition: - base64 or hex -} - -rule DodgyPhp -{ - strings: - $basedir_bypass = /curl_init\s*\(\s*["']file:\/\// - $basedir_bypass2 = "file:file:///" // https://www.intelligentexploit.com/view-details.html?id=8719 - $disable_magic_quotes = /set_magic_quotes_runtime\s*\(\s*0/ - $execution = /(eval|assert|passthru|exec|include|system|pcntl_exec|win_shell_execute|base64_decode|`|array_map|call_user_func(_array)?)\s*\(\s*(base64_decode|php:\/\/input|str_rot13|gz(inflate|uncompress)|getenv|pack|\\?\$_(GET|REQUEST|POST|COOKIE))/ nocase - $execution2 = /(array_filter|array_reduce|array_walk(_recursive)?|array_walk|assert_options|uasort|uksort|usort|preg_replace_callback|iterator_apply)\s*\(\s*[^,]+,\s*(base64_decode|php:\/\/input|str_rot13|gz(inflate|uncompress)|getenv|pack|\\?\$_(GET|REQUEST|POST|COOKIE))/ nocase // functions that takes a callback as 2nd parameter - - $htaccess = "SetHandler application/x-httpd-php" - $iis_com = /IIS:\/\/localhost\/w3svc/ - $include = /include\s*\(\s*[^\.]+\.(png|jpg|gif|bmp)/ // Clever includes - $ini_get = /ini_(get|set|restore)\s*\(\s*['"](safe_mode|open_basedir|disable_function|safe_mode_exec_dir|safe_mode_include_dir|register_globals|allow_url_include)/ nocase - $pr = /(preg_replace(_callback)?|mb_ereg_replace|preg_filter)\s*\(\s*['"]\/[^\/]*\/e/ nocase // http://php.net/manual/en/function.preg-replace.php - $safemode_bypass = /\x00\/\.\.\/|LD_PRELOAD/ - $shellshock = /\(\)\s*{\s*:\s*;\s*}\s*;/ - $udp_dos = /fsockopen\s*\(\s*['"]udp:\/\// - $user_function = /(call_user_func|create_function)/ nocase - $various = " diff --git a/php-malware-finder/tests.sh b/php-malware-finder/tests.sh index fe9141a..2dee339 100755 --- a/php-malware-finder/tests.sh +++ b/php-malware-finder/tests.sh @@ -14,6 +14,16 @@ run_test(){ CPT=$((CPT+1)) } +run_test_asp(){ + NB_DETECTED=$(${PMF} -v -l asp "$SAMPLES"/"$1" | grep -c "$2" 2>/dev/null) + + if [[ "$NB_DETECTED" != 1 ]]; then + echo "[-] $2 was not detected in $1, sorry" + exit 1 + fi + CPT=$((CPT+1)) +} + # Real samples run_test cpanel.php '0x294d:$eval: {eval(' run_test freepbx.php 'ObfuscatedPhp' @@ -79,4 +89,7 @@ run_test artificial/bypasses.php 'DodgyPhp' run_test artificial/bypasses.php '0x6d:$execution: call_user_func_array($_POST' run_test artificial/bypasses.php "0x132:\$var_as_func: \$_POST\['funct'\](" +# Asp files +run_test_asp classic/cmdasp.asp 'DodgyStrings' + echo "[+] Congratz, the $CPT tests succeeded!" -- cgit v1.3