33
2
mirror of https://github.com/joomla-extensions/jedchecker.git synced 2024-12-11 13:52:26 +00:00

support of "scopes" for JAMSS rules

This commit is contained in:
Denis Ryabov 2021-11-16 22:30:37 +03:00
parent d0719e4d4a
commit bf2d44a585

View File

@ -134,19 +134,27 @@ class JedcheckerRulesJamss extends JEDcheckerRule
'Detected preg_replace function that evaluates (executes) mathed code. ' . 'Detected preg_replace function that evaluates (executes) mathed code. ' .
'This means if PHP code is passed it will be executed.', 'This means if PHP code is passed it will be executed.',
// [3] = description // [3] = description
'php',
// [4] = scope:
// 'full' - entire file,
// 'clean' - with stripped PHP comments,
// 'php' - with stripped HTML and PHP comments,
// 'code' - with stripped HTML, PHP comments, and strings
'Part example code from http://sucuri.net/malware/backdoor-phppreg_replaceeval'), 'Part example code from http://sucuri.net/malware/backdoor-phppreg_replaceeval'),
// [4] = More Information link // [5] = More Information link
array('c999*sh_surl', array('c999*sh_surl',
'Backdoor: PHP:C99:045', 'Backdoor: PHP:C99:045',
'2', '2',
'Detected the "C99? backdoor that allows attackers to manage (and reinfect) your site remotely. ' . 'Detected the "C99? backdoor that allows attackers to manage (and reinfect) your site remotely. ' .
'It is often used as part of a compromise to maintain access to the hacked sites.', 'It is often used as part of a compromise to maintain access to the hacked sites.',
'php',
'http://sucuri.net/malware/backdoor-phpc99045'), 'http://sucuri.net/malware/backdoor-phpc99045'),
array('preg_match\s*\(\s*\"\s*/\s*bot\s*/\s*\"', array('preg_match\s*\(\s*\"\s*/\s*bot\s*/\s*\"',
'Backdoor: PHP:R57:01', 'Backdoor: PHP:R57:01',
'3', '3',
'Detected the "R57? backdoor that allows attackers to access, modify and reinfect your site. ' . 'Detected the "R57? backdoor that allows attackers to access, modify and reinfect your site. ' .
'It is often hidden in the filesystem and hard to find without access to the server or logs.', 'It is often hidden in the filesystem and hard to find without access to the server or logs.',
'php',
'http://sucuri.net/malware/backdoor-phpr5701'), 'http://sucuri.net/malware/backdoor-phpr5701'),
array('eval[\s/\*\#]*\(stripslashes[\s/\*\#]*\([\s/\*\#]*\$_(REQUEST|POST|GET)\s*\[\s*\\\s*[\'\"]\s*asc\s*\\\s*[\'\"]', array('eval[\s/\*\#]*\(stripslashes[\s/\*\#]*\([\s/\*\#]*\$_(REQUEST|POST|GET)\s*\[\s*\\\s*[\'\"]\s*asc\s*\\\s*[\'\"]',
'Backdoor: PHP:GENERIC:07', 'Backdoor: PHP:GENERIC:07',
@ -155,6 +163,7 @@ class JedcheckerRulesJamss extends JEDcheckerRule
'upload files, delete files, access, modify and/or reinfect your site. ' . 'upload files, delete files, access, modify and/or reinfect your site. ' .
'It is often hidden in the filesystem and hard to find without access to the server or logs. ' . 'It is often hidden in the filesystem and hard to find without access to the server or logs. ' .
'It also includes uploadify scripts and similars that offer upload options without security. ', 'It also includes uploadify scripts and similars that offer upload options without security. ',
'php',
'http://sucuri.net/malware/backdoor-phpgeneric07'), 'http://sucuri.net/malware/backdoor-phpgeneric07'),
/*array('https?\S{1,63}\.ru', /*array('https?\S{1,63}\.ru',
'russian URL', 'russian URL',
@ -167,37 +176,44 @@ class JedcheckerRulesJamss extends JEDcheckerRule
'7', '7',
'Detected the “Filesman” backdoor that allows attackers to access, modify and reinfect your site. ' . 'Detected the “Filesman” backdoor that allows attackers to access, modify and reinfect your site. ' .
'It is often hidden in the filesystem and hard to find without access to the server or logs.', 'It is often hidden in the filesystem and hard to find without access to the server or logs.',
'php',
'http://sucuri.net/malware/backdoor-phpfilesman02'), 'http://sucuri.net/malware/backdoor-phpfilesman02'),
array('(include|require)(_once)*\s*[\"\'][\w\W\s/\*]*php://input[\w\W\s/\*]*[\"\']', array('(include|require)(_once)*\s*[\"\'][\w\W\s/\*]*php://input[\w\W\s/\*]*[\"\']',
'PHP:\input include', 'PHP:\input include',
'8', '8',
'Detected the method of reading input through PHP protocol handler in include/require statements.',), 'Detected the method of reading input through PHP protocol handler in include/require statements.',
'php'),
array('data:;base64', array('data:;base64',
'data:;base64 include', 'data:;base64 include',
'9', '9',
'Detected the method of executing base64 data in include.',), 'Detected the method of executing base64 data in include.',
'php'),
array('RewriteCond\s*%\{HTTP_REFERER\}', array('RewriteCond\s*%\{HTTP_REFERER\}',
'.HTACCESS RewriteCond-Referer', '.HTACCESS RewriteCond-Referer',
'10', '10',
'Your .htaccess file has a conditional redirection based on "HTTP Referer". ' . 'Your .htaccess file has a conditional redirection based on "HTTP Referer". ' .
'This means it redirects according to site/url from where your visitors came to your site. ' . 'This means it redirects according to site/url from where your visitors came to your site. ' .
'Such technique has been used for unwanted redirections after coming from Google or other search engines, ' . 'Such technique has been used for unwanted redirections after coming from Google or other search engines, ' .
'so check this directive carefully.',), 'so check this directive carefully.',
'full'),
array('brute\s*force', array('brute\s*force',
'"Brute Force" words', '"Brute Force" words',
'11', '11',
'Detected the "Brute Force" words mentioned in code. <u>Sometimes it\'s a "false positive"</u> because ' . 'Detected the "Brute Force" words mentioned in code. <u>Sometimes it\'s a "false positive"</u> because ' .
'several developers like to mention it in they code, but it\'s worth double-checking if this file ' . 'several developers like to mention it in they code, but it\'s worth double-checking if this file ' .
'is untouched (eg. compare it with one in original extension package).'), 'is untouched (eg. compare it with one in original extension package).',
'full'),
array('GIF89a.*[\r\n]*.*<\?php', array('GIF89a.*[\r\n]*.*<\?php',
'PHP file desguised as GIF image', 'PHP file desguised as GIF image',
'15', '15',
'Detected a PHP file that was most probably uploaded as an image via webform that loosely only checks ' . 'Detected a PHP file that was most probably uploaded as an image via webform that loosely only checks ' .
'file headers.',), 'file headers.',
'full'),
array('\$ip[\w\W\s/\*]*=[\w\W\s/\*]*getenv\(["\']REMOTE_ADDR["\']\);[\w\W\s/\*]*[\r\n]\$message', array('\$ip[\w\W\s/\*]*=[\w\W\s/\*]*getenv\(["\']REMOTE_ADDR["\']\);[\w\W\s/\*]*[\r\n]\$message',
'Probably malicious PHP script that "calls home"', 'Probably malicious PHP script that "calls home"',
'16', '16',
'Detected script variations often used to inform the attackers about found vulnerable website.',), 'Detected script variations often used to inform the attackers about found vulnerable website.',
'php'),
array('(?:\b(?:eval|gzuncompress|gzinflate|base64_decode|str_rot13|strrev|strtr|rawurldecode|' . array('(?:\b(?:eval|gzuncompress|gzinflate|base64_decode|str_rot13|strrev|strtr|rawurldecode|' .
'assert|unpack|urldecode)[\s/\*\w\W\(]*){2,}', 'assert|unpack|urldecode)[\s/\*\w\W\(]*){2,}',
'PHP: multiple encoded, most probably obfuscated code found', 'PHP: multiple encoded, most probably obfuscated code found',
@ -208,41 +224,49 @@ class JedcheckerRulesJamss extends JEDcheckerRule
'serialised object data. ' . 'serialised object data. ' .
'Please inspect the file manually and compare it with the one in the original extension or ' . 'Please inspect the file manually and compare it with the one in the original extension or ' .
'Joomla package to verify that this is not a false positive.', 'Joomla package to verify that this is not a false positive.',
'code',
'Thanks to Dario Pintarić (dario.pintaric[et}orion-web.hr for this report!'), 'Thanks to Dario Pintarić (dario.pintaric[et}orion-web.hr for this report!'),
array('<\s*iframe', array('<\s*iframe',
'IFRAME element', 'IFRAME element',
'18', '18',
'Found IFRAME element in code. It\'s mostly benevolent, but often used for bad stuff, ' . 'Found IFRAME element in code. It\'s mostly benevolent, but often used for bad stuff, ' .
'so please check if it\'s a valid code.'), 'so please check if it\'s a valid code.',
'clean'),
array('strrev[\s/\*\#]*\([\s/\*\#]*[\'"]\s*tressa\s*[\'"]\s*\)', array('strrev[\s/\*\#]*\([\s/\*\#]*[\'"]\s*tressa\s*[\'"]\s*\)',
'Reversed string "assert"', 'Reversed string "assert"',
'19', '19',
'Assert function name is being hidden behind strrev().'), 'Assert function name is being hidden behind strrev().',
'php'),
array('is_writable[\s/\*\#]*\([\s/\*\#]*getcwd', array('is_writable[\s/\*\#]*\([\s/\*\#]*getcwd',
'Is the current DIR Writable?', 'Is the current DIR Writable?',
'20', '20',
'This could be harmless, but used in some malware'), 'This could be harmless, but used in some malware',
'code'),
array('(?:\\\\x[0-9A-Fa-f]{1,2}|\\\\[0-7]{1,3}){2,}', array('(?:\\\\x[0-9A-Fa-f]{1,2}|\\\\[0-7]{1,3}){2,}',
'At least two characters in hexadecimal or octal notation', 'At least two characters in hexadecimal or octal notation',
'21', '21',
'Found at least two characters in hexadecimal or octal notation. It doesn\'t mean it is malicious, ' . 'Found at least two characters in hexadecimal or octal notation. It doesn\'t mean it is malicious, ' .
'but it could be code hidding behind such notation.'), 'but it could be code hidding behind such notation.',
'php'),
array('\$_F\s*=\s*__FILE__\s*;\s*\$_X\s*=', array('\$_F\s*=\s*__FILE__\s*;\s*\$_X\s*=',
'SourceCop encoded code', 'SourceCop encoded code',
'22', '22',
'Found the SourceCop encoded code. It is often used for malicious code ' . 'Found the SourceCop encoded code. It is often used for malicious code ' .
'hiding, so go and check the code with some online SourceCop decoders'), 'hiding, so go and check the code with some online SourceCop decoders',
'code'),
array('\b(?:exec|passthru|shell_exec|system|proc_\w+|popen)\b[\w\W\s/\*]*\([\s/\*\#\'\"\w\W\-\_]*(?:\$_GET|\$_POST)', array('\b(?:exec|passthru|shell_exec|system|proc_\w+|popen)\b[\w\W\s/\*]*\([\s/\*\#\'\"\w\W\-\_]*(?:\$_GET|\$_POST)',
'shell command execution from POST/GET variables', 'shell command execution from POST/GET variables',
'23', '23',
'Found direct shell command execution getting variables from POST/GET, ' . 'Found direct shell command execution getting variables from POST/GET, ' .
'which is highly dangerous security flaw or a part of malicious webrootkit'), 'which is highly dangerous security flaw or a part of malicious webrootkit',
'code'),
array('\$\w[\w\W\s/\*]*=[\w\W\s/\*]*`.*`', array('\$\w[\w\W\s/\*]*=[\w\W\s/\*]*`.*`',
'PHP execution operator: backticks (``)', 'PHP execution operator: backticks (``)',
'24', '24',
'PHP execution operator found. Note that these are not single-quotes! ' . 'PHP execution operator found. Note that these are not single-quotes! ' .
'PHP will attempt to execute the contents of the backticks as a shell ' . 'PHP will attempt to execute the contents of the backticks as a shell ' .
'command, which might indicate a part of a webrootkit'), 'command, which might indicate a part of a webrootkit',
'code'),
); );
$jamssFileNames = array( $jamssFileNames = array(
@ -316,21 +340,29 @@ class JedcheckerRulesJamss extends JEDcheckerRule
} }
else else
{ {
$content = JEDCheckerHelper::cleanPhpCode($content, JEDCheckerHelper::CLEAN_COMMENTS); $scopes = array(
'full' => $content,
'clean' => JEDCheckerHelper::cleanPhpCode($content, JEDCheckerHelper::CLEAN_COMMENTS),
'php' => JEDCheckerHelper::cleanPhpCode($content, JEDCheckerHelper::CLEAN_COMMENTS | JEDCheckerHelper::CLEAN_HTML),
'code' => JEDCheckerHelper::cleanPhpCode($content, JEDCheckerHelper::CLEAN_COMMENTS | JEDCheckerHelper::CLEAN_HTML | JEDCheckerHelper::CLEAN_STRINGS)
);
// Do a search for fingerprints // Do a search for fingerprints
foreach ($patterns As $pattern) foreach ($patterns as $pattern)
{ {
$scope = (is_array($pattern) && isset($pattern[4])) ? $pattern[4] : 'clean';
$scoped_content = $scopes[$scope];
if (is_array($pattern)) if (is_array($pattern))
{ {
// It's a pattern // It's a pattern
// RegEx modifiers: i=case-insensitive; s=dot matches also newlines; S=optimization // RegEx modifiers: i=case-insensitive; s=dot matches also newlines; S=optimization
preg_match_all('#' . $pattern[0] . '#isS', $content, $found, PREG_OFFSET_CAPTURE); preg_match_all('#' . $pattern[0] . '#isS', $scoped_content, $found, PREG_OFFSET_CAPTURE);
} }
else else
{ {
// It's a string // It's a string
preg_match_all('#' . $pattern . '#isS', $content, $found, PREG_OFFSET_CAPTURE); preg_match_all('#' . $pattern . '#isS', $scoped_content, $found, PREG_OFFSET_CAPTURE);
} }
// Remove outer array from results // Remove outer array from results
@ -357,22 +389,22 @@ class JedcheckerRulesJamss extends JEDcheckerRule
// The offset is in $match[1] // The offset is in $match[1]
$offset = $match[1]; $offset = $match[1];
// Note: negative 3rd argument is used for right-to-left search // Note: negative 3rd argument is used for right-to-left search
$start = strrpos($content, "\n", -(strlen($content) - $offset)); $start = strrpos($scoped_content, "\n", $offset - strlen($scoped_content));
if ($start === false) if ($start === false)
{ {
$start = 0; $start = 0;
} }
$end = strpos($content, "\n", $offset); $end = strpos($scoped_content, "\n", $offset);
if ($end === false) if ($end === false)
{ {
$end = strlen($content); $end = strlen($scoped_content);
} }
$first_code = substr($content, $start, min($end - $start, 200)); $first_code = substr($scoped_content, $start, min($end - $start, 200));
$first_line = $this->calculate_line_number($offset, $content); $first_line = $this->calculate_line_number($offset, $scoped_content);
break; break;
} }