Skip to content

Commit

Permalink
feat: add path setters and backups flags
Browse files Browse the repository at this point in the history
Fix some issues with initialization
Update readme docs with programmatically usage example
Add new flags:

```
-b   --backup                - Make a backup of every touched files

--path-backups=""            - Set backups path directory (default ./scanner-backups)
                               Is recommended put files outside the public document path
--path-logs=""               - Set quarantine log file (default ./scanner.log)
--path-quarantine=""         - Set quarantine path directory (default ./scanner-quarantine)
                               Is recommended put files outside the public document path
--path-report=""             - Set report log file (default ./scanner-report.log)
--path-whitelist=""          - Set whitelist file (default ./scanner-whitelist.json)
```

BREAKING CHANGE:
Rename class Application to Scanner
  • Loading branch information
marcocesarato committed Oct 7, 2020
1 parent f2a7d67 commit 010a875
Show file tree
Hide file tree
Showing 9 changed files with 335 additions and 81 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
scanner-infected.log
scanner.log
*.log
*.logs
scanner-whitelist.json

vendor/**
Expand Down
54 changes: 39 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# AMWSCAN - PHP Antimalware Scanner

**Version:** 0.5.3.93 beta
**Version:** 0.6.0.106 beta

**Github:** https://github.com/marcocesarato/PHP-Antimalware-Scanner

Expand Down Expand Up @@ -140,8 +140,9 @@ Flags:
-s --only-signatures - Check only virus signatures (like exploit but more specific)
-h --help - Show the available flags and arguments
-l --log="" - Write a log file on 'scanner.log' or the specified filepath
-r --report - Report scan only mode without check and remove malware. It also write
a report with all malware paths found to 'scanner-infected.log'
-r --report - Report scan only mode without check and remove malware (like --auto-skip).
It also write a report with all malware paths found
-b --backup - Make a backup of every touched files
-u --update - Update scanner to last version
-v --version - Get version number
Expand All @@ -154,6 +155,14 @@ Flags:
--filter-path/s="" - Filter path/s, for multiple value separate with comma
Wildcards are enabled ex. /path/*/htdocs or /path/*.php
--path-backups="" - Set backups path directory (default ./scanner-backups)
Is recommended put files outside the public document path
--path-logs="" - Set quarantine log file (default ./scanner.log)
--path-quarantine="" - Set quarantine path directory (default ./scanner-quarantine)
Is recommended put files outside the public document path
--path-report="" - Set report log file (default ./scanner-report.log)
--path-whitelist="" - Set whitelist file (default ./scanner-whitelist.json)
--exploits="" - Filter exploits
--functions="" - Define functions to search
--whitelist-only-path - Check on whitelist only file path and not line number
Expand Down Expand Up @@ -183,26 +192,41 @@ Examples: php -d disable_functions='' scanner ./mywebsite/http/ -l -s --only-exp
php -d disable_functions='' scanner --agile --only-exploits
php -d disable_functions='' scanner --exploits="double_var2" --functions="eval, str_replace"
Usage: php scanner [--agile|-a] [--help|-h] [--log|-l <log>] [--offset <offset>] [--limit <limit>] [--report|-r] [--version|-v]
[--update|-u] [--only-signatures|-s] [--only-exploits|-e] [--only-functions|-f] [--list]
Usage: php scanner [<path>] [--agile|-a] [--help|-h] [--log|-l <log>] [--offset <offset>] [--limit <limit>] [--report|-r]
[--version|-v] [--update|-u] [--only-signatures|-s] [--only-exploits|-e] [--only-functions|-f] [--list]
[--list-exploits] [--list-functions] [--exploits <exploits>] [--functions <functions>]
[--whitelist-only-path] [--max-filesize <max-filesize>] [--silent]
[--whitelist-only-path] [--max-filesize <max-filesize>] [--silent] [--backup|-b]
[--ignore-paths|--ignore-path <ignore-paths>] [--filter-paths|--filter-path <filter-paths>]
[--auto-clean] [--auto-clean-line] [--auto-delete] [--auto-quarantine] [--auto-skip] [--auto-whitelist]
[--auto-prompt <auto-prompt>] [<path>]
[--auto-prompt <auto-prompt>] [--path-whitelist <path-whitelist>] [--path-backups <path-backups>]
[--path-quarantine <path-quarantine>] [--path-logs <path-logs>] [--path-report <path-report>]
```

### Programmatically

```php
use marcocesarato\amwscan\Application;

$app = new Application();
$app->setPathScan("my/path/to/scan")
->setSilentMode()
->setAgileMode()
->setAutoClean()
->run();
use marcocesarato\amwscan\Scanner;

$app = new Scanner();
$report = $app->setPathScan("my/path/to/scan")
->setSilentMode()
->setAgileMode()
->setAutoSkip()
->run();
```

##### Report Object

```php
object(stdClass) (7) {
["scanned"] => int(0)
["detected"] => int(0)
["removed"] => array(0) {}
["ignored"] => array(0) {}
["edited"] => array(0) {}
["quarantine"] => array(0) {}
["whitelist"] => array(0) {}
}
```

### Exploits and Functions List
Expand Down
3 changes: 2 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

## TODO

* Rollback
* Multi Language
* Output with EventSource
* Checksum files of the most popular platform for a whitelist (and implement the check with checksum) for no have more false positive
1. Wordpress
1. Wordpress (can be used api with version autodetection)
2. WooCommerce
3. Magento
4. Joomla
Expand Down
Binary file modified dist/scanner
Binary file not shown.
2 changes: 1 addition & 1 deletion dist/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.5.3.93
0.6.0.106
108 changes: 102 additions & 6 deletions src/Actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,30 @@

namespace marcocesarato\amwscan;

use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;

class Actions
{
/**
* Put content.
*
* @param $filename
* @param $data
* @param int $flags
* @param null $context
*
* @return false|int
*/
public static function putContents($filename, $data, $flags = 0, $context = null)
{
if (Scanner::isBackupEnabled()) {
self::makeBackup($filename);
}

return file_put_contents($filename, $data, $flags, $context);
}

/**
* Clean Evil Code.
*
Expand Down Expand Up @@ -57,7 +79,11 @@ public static function cleanEvilCodeLine($code, $pattern_found)
*/
public static function deleteFile($file)
{
return unlink($file);
if (Scanner::isBackupEnabled()) {
self::makeBackup($file);
}

return self::unlink($file);
}

/**
Expand All @@ -69,7 +95,8 @@ public static function deleteFile($file)
*/
public static function moveToQuarantine($file)
{
$quarantine = Application::getPathQuarantine() . str_replace(realpath(Application::currentDirectory()), '', $file);
$quarantine = Scanner::getPathQuarantine() . DIRECTORY_SEPARATOR . str_replace(realpath(Scanner::getPathScan()), '', realpath($file));
$quarantine = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $quarantine);
if (!is_dir(dirname($quarantine))) {
if (!mkdir($concurrentDirectory = dirname($quarantine), 0755, true) && !is_dir($concurrentDirectory)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory));
Expand All @@ -80,6 +107,27 @@ public static function moveToQuarantine($file)
return $quarantine;
}

/**
* Move to Quarantine.
*
* @param $file
*
* @return string
*/
public static function makeBackup($file)
{
$backup = Scanner::getPathBackups() . DIRECTORY_SEPARATOR . str_replace(realpath(Scanner::getPathScan()), '', realpath($file));
$backup = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $backup);
if (!is_dir(dirname($backup))) {
if (!mkdir($concurrentDirectory = dirname($backup), 0755, true) && !is_dir($concurrentDirectory)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory));
}
}
copy($file, $backup);

return $backup;
}

/**
* Add to Whitelist.
*
Expand All @@ -90,12 +138,12 @@ public static function moveToQuarantine($file)
*/
public static function addToWhitelist($file, $pattern_found)
{
$whitelist = Application::getWhitelist();
$whitelist = Scanner::getWhitelist();
foreach ($pattern_found as $key => $pattern) {
$exploit = $pattern['key'];
$lineNumber = $pattern['line'];
$match = $pattern['match'];
$fileName = str_replace(Application::getPathScan(), '', $file);
$fileName = str_replace(Scanner::getPathScan(), '', $file);
$key = md5($exploit . $fileName . $lineNumber);
$whitelist[$key] = array(
'file' => $fileName,
Expand All @@ -104,9 +152,9 @@ public static function addToWhitelist($file, $pattern_found)
'match' => $match,
);
}
Application::setWhitelist($whitelist);
Scanner::setWhitelist($whitelist);

return file_put_contents(Application::getPathWhitelist(), json_encode($whitelist));
return file_put_contents(Scanner::getPathWhitelist(), json_encode($whitelist));
}

/**
Expand All @@ -116,6 +164,10 @@ public static function addToWhitelist($file, $pattern_found)
*/
public static function openWithVim($file)
{
if (Scanner::isBackupEnabled()) {
self::makeBackup($file);
}

$descriptors = array(
array('file', '/dev/tty', 'r'),
array('file', '/dev/tty', 'w'),
Expand All @@ -137,6 +189,10 @@ public static function openWithVim($file)
*/
public static function openWithNano($file)
{
if (Scanner::isBackupEnabled()) {
self::makeBackup($file);
}

$descriptors = array(
array('file', '/dev/tty', 'r'),
array('file', '/dev/tty', 'w'),
Expand All @@ -150,4 +206,44 @@ public static function openWithNano($file)
}
}
}

/**
* Clean Quarantine path.
*
* @return bool
*/
public static function cleanQuarantine()
{
return self::unlink(Scanner::getPathQuarantine());
}

/**
* Unlink.
*
* @param $path
*
* @return bool
*/
protected static function unlink($path)
{
if (is_dir($path) && !is_link($path)) {
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);

foreach ($files as $fileinfo) {
$action = ($fileinfo->isDir() ? 'rmdir' : 'unlink');
$action($fileinfo->getRealPath());
}

return rmdir($path);
}

if (file_exists($path)) {
return unlink($path);
}

return false;
}
}
33 changes: 21 additions & 12 deletions src/Console.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public static function eol($n)
*/
public static function header()
{
$version = Application::getVersion();
$version = Scanner::getVersion();
self::newLine(2);
$header = <<<EOD
█████╗ ███╗ ███╗██╗ ██╗███████╗ ██████╗ █████╗ ███╗ ██╗
Expand Down Expand Up @@ -336,7 +336,7 @@ public static function write($string, $foreground_color = 'white', $background_c
$foreground_color = null;
$background_color = null;
}
if (Application::isLogsEnabled() && $log === null) {
if (Scanner::isLogsEnabled() && $log === null) {
$log = true;
}
if ($escape) {
Expand All @@ -351,7 +351,7 @@ public static function write($string, $foreground_color = 'white', $background_c
}
$colored_string .= $return_string . "\033[0m";

if (!Application::isSilentMode()) {
if (!Scanner::isSilentMode()) {
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
echo $return_string;
} else {
Expand All @@ -360,7 +360,7 @@ public static function write($string, $foreground_color = 'white', $background_c
}

if ($log) {
self::log($string, $foreground_color);
self::log($string, (!empty($foreground_color) && $foreground_color !== 'white' ? $foreground_color : $background_color));
}
}

Expand Down Expand Up @@ -390,11 +390,11 @@ public static function read($string, $foreground_color = 'white', $background_co

$read = null;

if (!Application::isSilentMode()) {
if (!Scanner::isSilentMode()) {
if (stripos(PHP_OS, 'WIN') === 0) {
echo Application::getName() . ' > ' . trim($string) . ' ';
echo Scanner::getName() . ' > ' . trim($string) . ' ';
} else {
echo Application::getName() . ' > ' . trim($colored_string) . ' ';
echo Scanner::getName() . ' > ' . trim($colored_string) . ' ';
}
}

Expand Down Expand Up @@ -468,7 +468,7 @@ public static function log($string, $color = '')
break;
}
$string = '[' . date('Y-m-d H:i:s') . '] [' . $type . '] ' . $string . PHP_EOL;
file_put_contents(Application::getPathLogs(), $string, FILE_APPEND);
file_put_contents(Scanner::getPathLogs(), $string, FILE_APPEND);
}
}

Expand Down Expand Up @@ -513,7 +513,7 @@ public static function helplist($type = null)
public static function helper()
{
self::displayTitle('Help', 'black', 'cyan');
$dir = Application::currentDirectory();
$dir = Scanner::currentDirectory();
$help = <<<EOD
IMPORTANT: You will be solely responsible for any damage to your computer system or loss of data
Expand All @@ -533,8 +533,9 @@ public static function helper()
-s --only-signatures - Check only virus signatures (like exploit but more specific)
-h --help - Show the available flags and arguments
-l --log="" - Write a log file on 'index.php.log' or the specified filepath
-r --report - Report scan only mode without check and remove malware. It also write
a report with all malware paths found to 'scanner-infected.log'
-r --report - Report scan only mode without check and remove malware (like --auto-skip).
It also write a report with all malware paths found
-b --backup - Make a backup of every touched files
-u --update - Update index.php to last version
-v --version - Get version number
Expand All @@ -546,6 +547,14 @@ public static function helper()
Wildcards are enabled ex. /path/*/cache or /path/*.log
--filter-path/s="" - Filter path/s, for multiple value separate with comma
Wildcards are enabled ex. /path/*/htdocs or /path/*.php
--path-backups="" - Set backups path directory (default ./scanner-backups)
Is recommended put files outside the public document path
--path-logs="" - Set quarantine log file (default ./scanner.log)
--path-quarantine="" - Set quarantine path directory (default ./scanner-quarantine)
Is recommended put files outside the public document path
--path-report="" - Set report log file (default ./scanner-report.log)
--path-whitelist="" - Set whitelist file (default ./scanner-whitelist.json)
--exploits="" - Filter exploits
--functions="" - Define functions to search
Expand Down Expand Up @@ -577,6 +586,6 @@ public static function helper()
php -d disable_functions='' scanner --exploits="double_var2" --functions="eval, str_replace"
php -d disable_functions='' scanner --ignore-paths="/my/path/*.log,/my/path/*/cache/*"
EOD;
self::displayLine($help . self::eol(2) . Application::getArgv()->usage(), 2);
self::displayLine($help . self::eol(2) . Scanner::getArgv()->usage(), 2);
}
}
Loading

0 comments on commit 010a875

Please sign in to comment.