diff options
| author | Julien Voisin | 2016-02-03 14:16:16 +0100 |
|---|---|---|
| committer | Julien Voisin | 2016-02-03 14:16:16 +0100 |
| commit | bbcf378a2b50525022e2065ef95bd7d5ad5886bc (patch) | |
| tree | a9ee6054f5d4a49c07aa42a365fec475b5ea10f1 | |
| parent | 53070beff9d5a6ff8526feb6fee30c3de6b7982c (diff) | |
| parent | 002f75633c6968ec824e7da8fa6682a248e719ad (diff) | |
Merge branch 'master' of github.com:nbs-system/php-malware-finder
| -rw-r--r-- | php-malware-finder/README.md | 14 | ||||
| -rw-r--r-- | php-malware-finder/malwares.yara | 89 | ||||
| -rwxr-xr-x | php-malware-finder/phpmalwarefinder | 9 | ||||
| -rw-r--r-- | php-malware-finder/whitelist.yara | 6 |
4 files changed, 69 insertions, 49 deletions
diff --git a/php-malware-finder/README.md b/php-malware-finder/README.md index 59187b1..67dad30 100644 --- a/php-malware-finder/README.md +++ b/php-malware-finder/README.md | |||
| @@ -14,7 +14,8 @@ Detect potentially malicious PHP files. | |||
| 14 | 14 | ||
| 15 | ## What does it detect? | 15 | ## What does it detect? |
| 16 | 16 | ||
| 17 | PHP-malware-finder does its very best to detect obfuscated/dodgy code as well as files using PHP functions often used in malwares/webshells. | 17 | PHP-malware-finder does its very best to detect obfuscated/dodgy code as well as |
| 18 | files using PHP functions often used in malwares/webshells. | ||
| 18 | 19 | ||
| 19 | The following list of encoders/obfuscators/webshells are also detected: | 20 | The following list of encoders/obfuscators/webshells are also detected: |
| 20 | 21 | ||
| @@ -33,9 +34,14 @@ The following list of encoders/obfuscators/webshells are also detected: | |||
| 33 | * [tennc]( http://tennc.github.io/webshell/ ) | 34 | * [tennc]( http://tennc.github.io/webshell/ ) |
| 34 | * [web-malware-collection]( https://github.com/nikicat/web-malware-collection ) | 35 | * [web-malware-collection]( https://github.com/nikicat/web-malware-collection ) |
| 35 | 36 | ||
| 37 | |||
| 38 | Of course it's easy to bypass PMF, but its goal is to catch kiddies and idiots, | ||
| 39 | not people with a working brain. | ||
| 40 | |||
| 36 | ## How does it work? | 41 | ## How does it work? |
| 37 | 42 | ||
| 38 | Detection is performed by crawling the filesystem and testing files against a [set]( https://github.com/nbs-system/php-malware-finder/blob/master/malwares.yara ) | 43 | Detection is performed by crawling the filesystem and testing files against a |
| 44 | [set]( https://github.com/nbs-system/php-malware-finder/blob/master/malwares.yara ) | ||
| 39 | of [YARA](https://plusvic.github.io/yara/) rules. Yes, it's that simple! | 45 | of [YARA](https://plusvic.github.io/yara/) rules. Yes, it's that simple! |
| 40 | 46 | ||
| 41 | 47 | ||
| @@ -47,6 +53,7 @@ Usage phpmalwarefinder [-cfhw] <file|folder> ... | |||
| 47 | -c Optional path to a configuration file | 53 | -c Optional path to a configuration file |
| 48 | -f Fast mode | 54 | -f Fast mode |
| 49 | -h Show this help message | 55 | -h Show this help message |
| 56 | -t Specify the number of threads to use (8 by default) | ||
| 50 | -v Verbose mode | 57 | -v Verbose mode |
| 51 | ``` | 58 | ``` |
| 52 | 59 | ||
| @@ -59,7 +66,8 @@ $ yara -r ./malwares.yara /var/www | |||
| 59 | ## Whitelisting | 66 | ## Whitelisting |
| 60 | 67 | ||
| 61 | Check the [whitelist.yara]( https://github.com/nbs-system/php-malware-finder/blob/master/whitelist.yara ) file. | 68 | Check the [whitelist.yara]( https://github.com/nbs-system/php-malware-finder/blob/master/whitelist.yara ) file. |
| 62 | If you're lazy, you can generate whitelists for entire folders with the [generate_whitelist.py]( https://github.com/nbs-system/php-malware-finder/blob/master/generate_whitelist.py ) script. | 69 | If you're lazy, you can generate whitelists for entire folders with the |
| 70 | [generate_whitelist.py]( https://github.com/nbs-system/php-malware-finder/blob/master/generate_whitelist.py ) script. | ||
| 63 | 71 | ||
| 64 | ## Licensing | 72 | ## Licensing |
| 65 | 73 | ||
diff --git a/php-malware-finder/malwares.yara b/php-malware-finder/malwares.yara index f733bc3..d0b5c35 100644 --- a/php-malware-finder/malwares.yara +++ b/php-malware-finder/malwares.yara | |||
| @@ -57,16 +57,17 @@ private rule CloudFlareBypass | |||
| 57 | rule ObfuscatedPhp | 57 | rule ObfuscatedPhp |
| 58 | { | 58 | { |
| 59 | strings: | 59 | strings: |
| 60 | $eval = /[;{}][\t ]*@?(eval|preg_replace|system|exec|assert|passthru)\(/ // ;eval( <- this is dodgy | 60 | $eval = /(<\?php\s*\n*\r*|[;{}])\s*@?(eval|preg_replace|system|exec|assert|passthru|win_shell_execute)/ // ;eval( <- this is dodgy |
| 61 | $b374k = /'ev'\.'al'/ | 61 | $b374k = "'ev'.'al'" |
| 62 | $align = /(\$\w+=[^;]*)*;\$\w+=@?\$\w+\(/ //b374k | 62 | $align = /(\$\w+=[^;]*)*;\$\w+=@?\$\w+\(/ //b374k |
| 63 | $oneliner = /<\?php\s*\n*\r*\s*(eval|preg_replace|system|exec|assert|passthru)\(/ | 63 | $oneliner = /<\?php\s*\n*\r*\s*@?(eval|preg_replace|system|exec|assert|passthru|win_shell_execute)\(/ |
| 64 | $weevely3 = /\$\w=\$[a-zA-Z]\('',\$\w\);\$\w\(\);/ // weevely3 launcher | 64 | $weevely3 = /\$\w=\$[a-zA-Z]\('',\$\w\);\$\w\(\);/ // weevely3 launcher |
| 65 | $c99_launcher = /;\$\w+\(\$\w+(,\s?\$\w+)+\);/ // http://bartblaze.blogspot.fr/2015/03/c99shell-not-dead.html | 65 | $c99_launcher = /;\$\w+\(\$\w+(,\s?\$\w+)+\);/ // http://bartblaze.blogspot.fr/2015/03/c99shell-not-dead.html |
| 66 | $strange_arg = /\${\$[0-9a-zA-z]+}/ | 66 | $strange_arg = /\${\$[0-9a-zA-z]+}/ |
| 67 | $too_many_chr = /(chr\([\d]+\)\.){2,}?/ | 67 | $too_many_chr = /(chr\([\d]+\)\.){2,}?/ |
| 68 | $b64_concat = /('[A-Za-z0-9=+]*'\.){4,8}?/ | 68 | $many_comments = /\/\*.{,28}\*\/[^\/]*\/\*/ // Something like as/* */ser/* */t |
| 69 | condition: | 69 | $b64_concat = /('[A-Za-z0-9=+]*'\.){4,8}?/ |
| 70 | condition: | ||
| 70 | any of them and not IsWhitelisted | 71 | any of them and not IsWhitelisted |
| 71 | } | 72 | } |
| 72 | 73 | ||
| @@ -106,14 +107,13 @@ rule DodgyPhp | |||
| 106 | strings: | 107 | strings: |
| 107 | $vars = /\$__+/ // $__ is rarely used in legitimate scripts | 108 | $vars = /\$__+/ // $__ is rarely used in legitimate scripts |
| 108 | $double_encoding = /(base64_decode\s*\(\s*){2}/ | 109 | $double_encoding = /(base64_decode\s*\(\s*){2}/ |
| 109 | $execution = /(eval|assert|passthru|exec|system|win_shell_execute|base64_decode)\s*\(\s*(base64_decode|php:\/\/input|str_rot13|gz(inflate|uncompress)|getenv|pack|\\?\$_(GET|REQUEST|POST))/ | 110 | $execution = /(eval|assert|passthru|exec|system|win_shell_execute|base64_decode)\s*\(\s*(base64_decode|php:\/\/input|str_rot13|gz(inflate|uncompress)|getenv|pack|\\?\$_(GET|REQUEST|POST|COOKIE))/ |
| 110 | $basedir_bypass = /(curl_init\([\"']file:[\"']|file:file:\/\/)/ | 111 | $basedir_bypass = /(curl_init\([\"']file:[\"']|file:file:\/\/)/ |
| 111 | $safemode_bypass = /\x00\/\.\.\/|LD_PRELOAD/ | 112 | $safemode_bypass = /\x00\/\.\.\/|LD_PRELOAD/ |
| 112 | $shellshock = /putenv\(["']PHP_[^=]=\(\) { [^}] };/ | 113 | $shellshock = /putenv\(["']PHP_[^=]=\(\) { [^}] };/ |
| 113 | $ini_get = | 114 | $restore_bypass = /ini_restore\(['"](safe_mode|open_basedir|disable_function|safe_mode_exec_dir|safe_mode_include_dir|register_globals)['"]\)/ |
| 114 | /ini_get\(['"](safe_mode|open_basedir|disable_function|safe_mode_exec_dir|safe_mode_include_dir|register_globals)['"]\)/ | 115 | $ini_get = /ini_get\(['"](safe_mode|open_basedir|disable_function|safe_mode_exec_dir|safe_mode_include_dir|register_globals)['"]\)/ |
| 115 | $restore_bypass = | 116 | |
| 116 | /ini_restore\(['"](safe_mode|open_basedir|disable_function|safe_mode_exec_dir|safe_mode_include_dir|register_globals)['"]\)/ | ||
| 117 | $various = "<!--#exec cmd=" //http://www.w3.org/Jigsaw/Doc/User/SSI.html#exec | 117 | $various = "<!--#exec cmd=" //http://www.w3.org/Jigsaw/Doc/User/SSI.html#exec |
| 118 | $pr = /(preg_replace(_callback)?|mb_ereg_replace|preg_filter)\s*\(['"]\/[^\/]*\/e['"]/ // http://php.net/manual/en/function.preg-replace.php | 118 | $pr = /(preg_replace(_callback)?|mb_ereg_replace|preg_filter)\s*\(['"]\/[^\/]*\/e['"]/ // http://php.net/manual/en/function.preg-replace.php |
| 119 | $include = /include\([^\.]+\.(png|jpg|gif|bmp)/ // Clever includes | 119 | $include = /include\([^\.]+\.(png|jpg|gif|bmp)/ // Clever includes |
| @@ -121,6 +121,7 @@ rule DodgyPhp | |||
| 121 | $udp_dos = /sockopen\s*\(['"]udp:\/\// | 121 | $udp_dos = /sockopen\s*\(['"]udp:\/\// |
| 122 | $iniset_urlinclude = /ini_set\('allow_url_include,\ * 1'\)/ | 122 | $iniset_urlinclude = /ini_set\('allow_url_include,\ * 1'\)/ |
| 123 | $iis_com = /IIS:\/\/localhost\/w3svc/ | 123 | $iis_com = /IIS:\/\/localhost\/w3svc/ |
| 124 | $user_function = /(call_user_func|create_function)/ | ||
| 124 | $disable_magic_quotes = /set_magic_quotes_runtime\(0\)/ | 125 | $disable_magic_quotes = /set_magic_quotes_runtime\(0\)/ |
| 125 | 126 | ||
| 126 | condition: | 127 | condition: |
| @@ -174,30 +175,37 @@ rule DangerousPhp | |||
| 174 | rule DodgyStrings | 175 | rule DodgyStrings |
| 175 | { | 176 | { |
| 176 | strings: | 177 | strings: |
| 178 | $ = "/../../../" | ||
| 179 | $ = /\/bin\/(ba)?sh/ fullword | ||
| 177 | $ = "/etc/passwd" | 180 | $ = "/etc/passwd" |
| 178 | $ = "/etc/shadow" | 181 | $ = "/etc/proftpd.conf" |
| 179 | $ = "/etc/resolv.conf" | 182 | $ = "/etc/resolv.conf" |
| 183 | $ = "/etc/shadow" | ||
| 180 | $ = "/etc/syslog.conf" | 184 | $ = "/etc/syslog.conf" |
| 181 | $ = "/etc/proftpd.conf" | 185 | $ = "/proc/cpuinfo" fullword |
| 186 | $ = "/windows/system32/" | ||
| 187 | $ = "WScript.Shell" | ||
| 182 | $ = "WinExec" | 188 | $ = "WinExec" |
| 183 | $ = "uname -a" fullword | 189 | $ = "b374k" fullword nocase |
| 184 | $ = "nc -l" fullword | 190 | $ = "backdoor" fullword nocase |
| 185 | $ = "ls -la" fullword | 191 | $ = "c99shell" fullword nocase |
| 186 | $ = "cmd.exe" fullword nocase | 192 | $ = "cmd.exe" fullword nocase |
| 187 | $ = "ipconfig" fullword nocase | ||
| 188 | $ = "find . -type f" fullword | ||
| 189 | $ = "defaced" fullword nocase | 193 | $ = "defaced" fullword nocase |
| 190 | $ = "slowloris" fullword nocase | ||
| 191 | $ = "id_rsa" fullword | ||
| 192 | $ = "backdoor" fullword nocase | ||
| 193 | $ = "webshell" fullword nocase | ||
| 194 | $ = "exploit" fullword nocase | 194 | $ = "exploit" fullword nocase |
| 195 | $ = "hacking" fullword nocase | 195 | $ = "find . -type f" fullword |
| 196 | $ = "/proc/cpuinfo" fullword | 196 | $ = /hack(ing|er)/ nocase |
| 197 | $ = "/bin/sh" fullword | 197 | $ = "hashcrack" nocase |
| 198 | $ = "/bin/bash" fullword | 198 | $ = "id_rsa" fullword |
| 199 | $ = "ipconfig" fullword nocase | ||
| 200 | $ = "kingdefacer" nocase | ||
| 201 | $ = "locus7s" nocase | ||
| 202 | $ = "ls -la" fullword | ||
| 203 | $ = "nc -l" fullword | ||
| 199 | $ = "ps -aux" fullword | 204 | $ = "ps -aux" fullword |
| 200 | $ = "b374k" fullword | 205 | $ = "rootkit" fullword nocase |
| 206 | $ = "slowloris" fullword nocase | ||
| 207 | $ = "uname -a" fullword | ||
| 208 | $ = "warez" fullword nocase | ||
| 201 | $ = /(reverse|web)\s*shell/ nocase | 209 | $ = /(reverse|web)\s*shell/ nocase |
| 202 | 210 | ||
| 203 | $vbs = /language\s*=\s*vbscript/ nocase | 211 | $vbs = /language\s*=\s*vbscript/ nocase |
| @@ -210,28 +218,23 @@ rule DodgyStrings | |||
| 210 | rule Websites | 218 | rule Websites |
| 211 | { | 219 | { |
| 212 | strings: | 220 | strings: |
| 213 | $ = "milw0rm.com" | ||
| 214 | $ = "exploit-db.com" | ||
| 215 | $ = "1337day.com" | 221 | $ = "1337day.com" |
| 216 | $ = "rapid7.com" | 222 | $ = "antichat.ru" |
| 217 | $ = "shodan.io" | 223 | $ = "ccteam.ru" |
| 218 | $ = "packetstormsecurity" | ||
| 219 | $ = "crackfor" nocase | 224 | $ = "crackfor" nocase |
| 220 | $ = "md5.rednoize" | ||
| 221 | $ = "hashcracking" nocase | ||
| 222 | $ = "darkc0de" nocase | 225 | $ = "darkc0de" nocase |
| 223 | $ = "securityfocus" nocase | 226 | $ = "egyspider.eu" |
| 224 | $ = "antichat.ru" | 227 | $ = "exploit-db.com" |
| 225 | $ = "KingDefacer" nocase | 228 | $ = "fopo.com.ar" /* Free Online Php Obfuscator */ |
| 229 | $ = "hashchecker.com" | ||
| 230 | $ = "hashkiller.com" nocase | ||
| 226 | $ = "md5crack.com" | 231 | $ = "md5crack.com" |
| 227 | $ = "md5decrypter.com" | 232 | $ = "md5decrypter.com" |
| 228 | $ = "hashkiller.com" | 233 | $ = "milw0rm.com" |
| 229 | $ = "hashchecker.com" | 234 | $ = "packetstormsecurity" nocase |
| 230 | $ = "www.fopo.com.ar" /* Free Online Php Obfuscator */ | 235 | $ = "rapid7.com" |
| 231 | $ = "ccteam.ru" | 236 | $ = "securityfocus" nocase |
| 232 | $ = "locus7s.com" | 237 | $ = "shodan.io" |
| 233 | $ = "b374k" | ||
| 234 | $ = "www.egyspider.eu" | ||
| 235 | 238 | ||
| 236 | condition: | 239 | condition: |
| 237 | any of them and not IsWhitelisted | 240 | any of them and not IsWhitelisted |
diff --git a/php-malware-finder/phpmalwarefinder b/php-malware-finder/phpmalwarefinder index 20d3cee..49cf8ce 100755 --- a/php-malware-finder/phpmalwarefinder +++ b/php-malware-finder/phpmalwarefinder | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #!/usr/bin/env bash | 1 | #!/usr/bin/env bash |
| 2 | 2 | ||
| 3 | |||
| 3 | YARA=$(type -P yara) | 4 | YARA=$(type -P yara) |
| 4 | CONFIG_PATH='/etc/phpmalwarefinder/malwares.yara' | 5 | CONFIG_PATH='/etc/phpmalwarefinder/malwares.yara' |
| 5 | IONICE_BIN=$(type -P ionice) | 6 | IONICE_BIN=$(type -P ionice) |
| @@ -50,12 +51,13 @@ Usage ${0##*/} [-cfhw] <file|folder> ... | |||
| 50 | -c Optional path to a configuration file | 51 | -c Optional path to a configuration file |
| 51 | -f Fast mode | 52 | -f Fast mode |
| 52 | -h Show this help message | 53 | -h Show this help message |
| 54 | -t Specify the number of threads to use (8 by default) | ||
| 53 | -v Verbose mode | 55 | -v Verbose mode |
| 54 | EOF | 56 | EOF |
| 55 | } | 57 | } |
| 56 | 58 | ||
| 57 | OPTIND=1 | 59 | OPTIND=1 |
| 58 | while getopts "c:fhv" opt; do | 60 | while getopts "c:fht:v" opt; do |
| 59 | case "$opt" in | 61 | case "$opt" in |
| 60 | h) | 62 | h) |
| 61 | show_help | 63 | show_help |
| @@ -67,6 +69,9 @@ while getopts "c:fhv" opt; do | |||
| 67 | c) | 69 | c) |
| 68 | CONFIG_PATH=${OPTARG} | 70 | CONFIG_PATH=${OPTARG} |
| 69 | ;; | 71 | ;; |
| 72 | t) | ||
| 73 | OPTS="${OPTS} --threads=${OPTARG}" | ||
| 74 | ;; | ||
| 70 | v) | 75 | v) |
| 71 | OPTS="${OPTS} -s" | 76 | OPTS="${OPTS} -s" |
| 72 | ;; | 77 | ;; |
| @@ -90,7 +95,7 @@ then | |||
| 90 | exit 1 | 95 | exit 1 |
| 91 | fi | 96 | fi |
| 92 | 97 | ||
| 93 | if [ -z $@ ] | 98 | if [ -z "$@" ] |
| 94 | then | 99 | then |
| 95 | show_help | 100 | show_help |
| 96 | exit 1 | 101 | exit 1 |
diff --git a/php-malware-finder/whitelist.yara b/php-malware-finder/whitelist.yara index a798ee8..107c638 100644 --- a/php-malware-finder/whitelist.yara +++ b/php-malware-finder/whitelist.yara | |||
| @@ -23,7 +23,11 @@ private rule Wordpress : Blog | |||
| 23 | /* Wordpress 3.2.1 */ | 23 | /* Wordpress 3.2.1 */ |
| 24 | hash.sha1(0, filesize) == "b4f53b8c360f9e47cc63047305a0ce2e3ff6a251" or // wp-includes/functions.php | 24 | hash.sha1(0, filesize) == "b4f53b8c360f9e47cc63047305a0ce2e3ff6a251" or // wp-includes/functions.php |
| 25 | hash.sha1(0, filesize) == "ac8298df16a560c80fb213ef3f51f90df8ef5292" or // wp-includes/class-phpmailer.php | 25 | hash.sha1(0, filesize) == "ac8298df16a560c80fb213ef3f51f90df8ef5292" or // wp-includes/class-phpmailer.php |
| 26 | hash.sha1(0, filesize) == "232e4705e3aa28269c4d5e4a4a700bb7a2d06f24" // wp-admin/includes/menu.php | 26 | hash.sha1(0, filesize) == "232e4705e3aa28269c4d5e4a4a700bb7a2d06f24" or // wp-admin/includes/menu.php |
| 27 | |||
| 28 | /* Wordpress 4.4 */ | ||
| 29 | hash.sha1(0, filesize) == "2fdf93ae88735d062a8635ac1d22a6904cb89ab8" or // wp-includes/formatting.php | ||
| 30 | hash.sha1(0, filesize) == "ccd23ef96a588840943fba081bfa6f88531c4abc" // wp-admin/includes/class-pclzip.php | ||
| 27 | } | 31 | } |
| 28 | 32 | ||
| 29 | private rule Prestashop : ECommerce | 33 | private rule Prestashop : ECommerce |
