Output formatting argument

This commit is contained in:
Gabor Gyorvari
2018-09-05 13:01:21 +02:00
parent d17d6c01ba
commit f9647806c8
2 changed files with 91 additions and 34 deletions

View File

@@ -31,6 +31,7 @@ Usage: php scan.php -d <directory>
-p --pattern Show Patterns next to the file name -p --pattern Show Patterns next to the file name
-t --time Show time of last file change -t --time Show time of last file change
--line-number Display matching pattern line number in file --line-number Display matching pattern line number in file
--output-format Custom defined output format
``` ```
Ignore argument could be used multiple times and accept glob style matching ex.: "`cache*`", "`??-cache.php`" or "`/cache`" etc. Ignore argument could be used multiple times and accept glob style matching ex.: "`cache*`", "`??-cache.php`" or "`/cache`" etc.
@@ -38,8 +39,22 @@ Ignore argument could be used multiple times and accept glob style matching ex.:
Extension argument defaults to "`.php`" and also can be used multiple times too. Extension argument defaults to "`.php`" and also can be used multiple times too.
* `--base64` is an alternative scan mode which ignores the main pattern files and uses a large list of php keywords and functions that have been converted to base64. Slower and prone to false positives, but gives additional base64 scanning coverage. These pattern files are located in base64_patterns and were derived from php 7 keywords and functions. Not many PHP extensions are included. * `--base64` is an alternative scan mode which ignores the main pattern files and uses a large list of php keywords and functions that have been converted to base64. Slower and prone to false positives, but gives additional base64 scanning coverage. These pattern files are located in base64_patterns and were derived from php 7 keywords and functions. Not many PHP extensions are included.
* `--comment` flag will display the last comment to appear in the pattern file before the matched pattern, so documenting the pattern files is important. * `--comment` flag will display the last comment to appear in the pattern file before the matched pattern, so documenting the pattern files is important.
* `--pattern` flag will display the pattern string that was matched.
Output formatting
-----------------
Default output depending on the specified parameters, but the full format is "%S %T %M # {%F} %C %P # %L" and using ANSI coloring too.
Possible variables are:
* `%S` - matching indicator, possible values are OK, ER, WL
* `%T` - file change time
* `%M` - file md5 hash value
* `%F` - file with path
* `%P` - pattern
* `%C` - pattern comment
* `%L` - matching pattern line number
Patterns Patterns
-------- --------
@@ -56,7 +71,7 @@ Whitelisting
See [whitelist.txt](https://github.com/scr34m/php-malware-scanner/blob/master/whitelist.txt) file for a predefined MD5 hash list. Only the first 32 characters are used, rest of the line ignored so feel free to leave a comment. See [whitelist.txt](https://github.com/scr34m/php-malware-scanner/blob/master/whitelist.txt) file for a predefined MD5 hash list. Only the first 32 characters are used, rest of the line ignored so feel free to leave a comment.
Tools Tools
--------- -----
**text2base64.py** **text2base64.py**

104
scan.php
View File

@@ -38,6 +38,7 @@ class MalwareScanner
private $flagExtraCheck = false; private $flagExtraCheck = false;
private $flagFollowSymlink = false; private $flagFollowSymlink = false;
private $flagLineNumber = false; private $flagLineNumber = false;
private $outputFormat = '';
private $whitelist = array(); private $whitelist = array();
private $ignore = array(); private $ignore = array();
private $stat = array( private $stat = array(
@@ -199,7 +200,8 @@ class MalwareScanner
'no-stop', 'no-stop',
'pattern', 'pattern',
'time', 'time',
'line-number' 'line-number',
'output-format:'
) )
); );
@@ -268,6 +270,11 @@ class MalwareScanner
if (isset($options['line-number'])) { if (isset($options['line-number'])) {
$this->setFlagLineNumber(true); $this->setFlagLineNumber(true);
} }
if (isset($options['output-format'])) {
$this->setOutputFormat(
is_array($options['output-format']) ? $options['output-format'] : array ($options['output-format'])
);
}
} }
public function setExtensions(array $a) public function setExtensions(array $a)
@@ -341,6 +348,11 @@ class MalwareScanner
$this->flagNoStop = $b; $this->flagNoStop = $b;
} }
public function setOutputFormat(array $format)
{
$this->outputFormat = array_shift($format);
}
// @see http://stackoverflow.com/a/13914119 // @see http://stackoverflow.com/a/13914119
private function pathMatches($path, $pattern, $ignoreCase = false) private function pathMatches($path, $pattern, $ignoreCase = false)
{ {
@@ -367,21 +379,29 @@ class MalwareScanner
return (bool)preg_match($expr, $path); return (bool)preg_match($expr, $path);
} }
/* /**
Formats and prints the scan result output line by line. * Formats and prints the scan result output line by line.
Depending on specified options, it will print: *
-Status code * Depending on specified options, it will print:
-Last Modified Time * - Status code
-MD5 Hash * - Last Modified Time
-File Path * - MD5 Hash
-Pattern Matched * - File Path
-The last comment to appear in the pattern file before this pattern * - Pattern Matched
*/ * - The last comment to appear in the pattern file before this pattern
* - Matching line number
*
* @param $found
* @param $path
* @param $pattern
* @param $comment
* @param $hash
* @param $lineNumber
*/
private function printPath($found, $path, $pattern, $comment, $hash, $lineNumber) private function printPath($found, $path, $pattern, $comment, $hash, $lineNumber)
{ {
$output_string = '# '; $default_format = '%S ';
//OK
if (!$found) { if (!$found) {
if ($this->flagHideOk) { if ($this->flagHideOk) {
return; return;
@@ -389,55 +409,77 @@ class MalwareScanner
$state = 'OK'; $state = 'OK';
$hash = ' '; $hash = ' ';
$state_color = $this->ANSI_GREEN; $state_color = $this->ANSI_GREEN;
} //WL } elseif ($this->inWhitelist($hash)) {
elseif ($this->inWhitelist($hash)) {
if ($this->flagHideWhitelist) { if ($this->flagHideWhitelist) {
return; return;
} }
$state = 'WL'; $state = 'WL';
$state_color = $this->ANSI_YELLOW; $state_color = $this->ANSI_YELLOW;
} //ER } else {
else {
$state = 'ER'; $state = 'ER';
$state_color = $this->ANSI_RED; $state_color = $this->ANSI_RED;
} }
$output_string = $state_color . $output_string . $state . $this->ANSI_OFF . ' ';
//Include cTime //Include cTime
if ($this->flagTime) { if ($this->flagTime) {
$changed_time = filectime($path); $changed_time = filectime($path);
$htime = date('H:i d-m-Y', $changed_time); $ctime = date('H:i d-m-Y', $changed_time);
$output_string = $output_string . $this->ANSI_BLUE . $htime . $this->ANSI_OFF . ' '; $default_format .= '%T';
} else {
$ctime = '';
} }
//Include Checksum/Hash //Include Checksum/Hash
if ($this->flagChecksum) { if ($this->flagChecksum) {
$output_string = $output_string . $this->ANSI_BLUE . $hash . $this->ANSI_OFF . ' '; $default_format .= '%M ';
} }
//Append Path // '#' and {} included to prevent accidental script execution attempts
//'#' and {} included to prevent accidental script execution attempts
// in the event that script output is pasted into a root terminal // in the event that script output is pasted into a root terminal
$opath = '# ' . '{' . $path . '}'; $default_format .= '# {%F} ';
$output_string = $output_string . $opath . ' ';
//'#' added again as code snippets have the potential to be valid shell commands //'#' added again as code snippets have the potential to be valid shell commands
if ($found) { if ($found) {
if ($this->flagPattern) { if ($this->flagPattern) {
$opatt = "# $pattern"; $default_format .= '%P ';
$output_string = $output_string . $state_color . $opatt . $this->ANSI_OFF . ' ';
} }
if ($this->flagComments) { if ($this->flagComments) {
$output_string = $output_string . $this->ANSI_BLUE . $comment . $this->ANSI_OFF . ' '; $default_format .= '%C ';
} }
if ($this->flagLineNumber) { if ($this->flagLineNumber) {
$output_string = $output_string . '# ' . $lineNumber; $default_format .= '# %L';
} }
} }
$output_string = trim($output_string) . PHP_EOL; if ($this->outputFormat) {
$map = [
'%S' => $state,
'%T' => $ctime,
'%M' => $hash,
'%F' => $path,
'%P' => $pattern,
'%C' => $comment,
'%L' => $lineNumber,
];
} else {
$map = [
'%S' => $state_color . '# ' . $state . $this->ANSI_OFF,
'%T' => $this->ANSI_BLUE . $ctime . $this->ANSI_OFF,
'%M' => $this->ANSI_BLUE . $hash . $this->ANSI_OFF,
'%F' => $path,
'%P' => $state_color . '#' . $pattern . $this->ANSI_OFF,
'%C' => $this->ANSI_BLUE . $comment . $this->ANSI_OFF,
'%L' => $lineNumber,
];
}
echo $output_string; if ($this->outputFormat) {
$format = $this->outputFormat;
} else {
$format = trim($default_format);
}
echo str_replace(array_keys($map), array_values($map), $format) . PHP_EOL;
} }
//Recursively scales the file system. //Recursively scales the file system.