Skip to content

Commit 010a875

Browse files
committed
feat: add path setters and backups flags
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
1 parent f2a7d67 commit 010a875

9 files changed

+335
-81
lines changed

.gitignore

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
scanner-infected.log
2-
scanner.log
1+
*.log
2+
*.logs
33
scanner-whitelist.json
44

55
vendor/**

README.md

+39-15
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# AMWSCAN - PHP Antimalware Scanner
44

5-
**Version:** 0.5.3.93 beta
5+
**Version:** 0.6.0.106 beta
66

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

@@ -140,8 +140,9 @@ Flags:
140140
-s --only-signatures - Check only virus signatures (like exploit but more specific)
141141
-h --help - Show the available flags and arguments
142142
-l --log="" - Write a log file on 'scanner.log' or the specified filepath
143-
-r --report - Report scan only mode without check and remove malware. It also write
144-
a report with all malware paths found to 'scanner-infected.log'
143+
-r --report - Report scan only mode without check and remove malware (like --auto-skip).
144+
It also write a report with all malware paths found
145+
-b --backup - Make a backup of every touched files
145146
-u --update - Update scanner to last version
146147
-v --version - Get version number
147148
@@ -154,6 +155,14 @@ Flags:
154155
--filter-path/s="" - Filter path/s, for multiple value separate with comma
155156
Wildcards are enabled ex. /path/*/htdocs or /path/*.php
156157
158+
--path-backups="" - Set backups path directory (default ./scanner-backups)
159+
Is recommended put files outside the public document path
160+
--path-logs="" - Set quarantine log file (default ./scanner.log)
161+
--path-quarantine="" - Set quarantine path directory (default ./scanner-quarantine)
162+
Is recommended put files outside the public document path
163+
--path-report="" - Set report log file (default ./scanner-report.log)
164+
--path-whitelist="" - Set whitelist file (default ./scanner-whitelist.json)
165+
157166
--exploits="" - Filter exploits
158167
--functions="" - Define functions to search
159168
--whitelist-only-path - Check on whitelist only file path and not line number
@@ -183,26 +192,41 @@ Examples: php -d disable_functions='' scanner ./mywebsite/http/ -l -s --only-exp
183192
php -d disable_functions='' scanner --agile --only-exploits
184193
php -d disable_functions='' scanner --exploits="double_var2" --functions="eval, str_replace"
185194
186-
Usage: php scanner [--agile|-a] [--help|-h] [--log|-l <log>] [--offset <offset>] [--limit <limit>] [--report|-r] [--version|-v]
187-
[--update|-u] [--only-signatures|-s] [--only-exploits|-e] [--only-functions|-f] [--list]
195+
Usage: php scanner [<path>] [--agile|-a] [--help|-h] [--log|-l <log>] [--offset <offset>] [--limit <limit>] [--report|-r]
196+
[--version|-v] [--update|-u] [--only-signatures|-s] [--only-exploits|-e] [--only-functions|-f] [--list]
188197
[--list-exploits] [--list-functions] [--exploits <exploits>] [--functions <functions>]
189-
[--whitelist-only-path] [--max-filesize <max-filesize>] [--silent]
198+
[--whitelist-only-path] [--max-filesize <max-filesize>] [--silent] [--backup|-b]
190199
[--ignore-paths|--ignore-path <ignore-paths>] [--filter-paths|--filter-path <filter-paths>]
191200
[--auto-clean] [--auto-clean-line] [--auto-delete] [--auto-quarantine] [--auto-skip] [--auto-whitelist]
192-
[--auto-prompt <auto-prompt>] [<path>]
201+
[--auto-prompt <auto-prompt>] [--path-whitelist <path-whitelist>] [--path-backups <path-backups>]
202+
[--path-quarantine <path-quarantine>] [--path-logs <path-logs>] [--path-report <path-report>]
193203
```
194204

195205
### Programmatically
196206

197207
```php
198-
use marcocesarato\amwscan\Application;
199-
200-
$app = new Application();
201-
$app->setPathScan("my/path/to/scan")
202-
->setSilentMode()
203-
->setAgileMode()
204-
->setAutoClean()
205-
->run();
208+
use marcocesarato\amwscan\Scanner;
209+
210+
$app = new Scanner();
211+
$report = $app->setPathScan("my/path/to/scan")
212+
->setSilentMode()
213+
->setAgileMode()
214+
->setAutoSkip()
215+
->run();
216+
```
217+
218+
##### Report Object
219+
220+
```php
221+
object(stdClass) (7) {
222+
["scanned"] => int(0)
223+
["detected"] => int(0)
224+
["removed"] => array(0) {}
225+
["ignored"] => array(0) {}
226+
["edited"] => array(0) {}
227+
["quarantine"] => array(0) {}
228+
["whitelist"] => array(0) {}
229+
}
206230
```
207231

208232
### Exploits and Functions List

TODO.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
## TODO
44

5+
* Rollback
56
* Multi Language
67
* Output with EventSource
78
* Checksum files of the most popular platform for a whitelist (and implement the check with checksum) for no have more false positive
8-
1. Wordpress
9+
1. Wordpress (can be used api with version autodetection)
910
2. WooCommerce
1011
3. Magento
1112
4. Joomla

dist/scanner

17.1 KB
Binary file not shown.

dist/version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.5.3.93
1+
0.6.0.106

src/Actions.php

+102-6
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,30 @@
22

33
namespace marcocesarato\amwscan;
44

5+
use RecursiveDirectoryIterator;
6+
use RecursiveIteratorIterator;
7+
58
class Actions
69
{
10+
/**
11+
* Put content.
12+
*
13+
* @param $filename
14+
* @param $data
15+
* @param int $flags
16+
* @param null $context
17+
*
18+
* @return false|int
19+
*/
20+
public static function putContents($filename, $data, $flags = 0, $context = null)
21+
{
22+
if (Scanner::isBackupEnabled()) {
23+
self::makeBackup($filename);
24+
}
25+
26+
return file_put_contents($filename, $data, $flags, $context);
27+
}
28+
729
/**
830
* Clean Evil Code.
931
*
@@ -57,7 +79,11 @@ public static function cleanEvilCodeLine($code, $pattern_found)
5779
*/
5880
public static function deleteFile($file)
5981
{
60-
return unlink($file);
82+
if (Scanner::isBackupEnabled()) {
83+
self::makeBackup($file);
84+
}
85+
86+
return self::unlink($file);
6187
}
6288

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

110+
/**
111+
* Move to Quarantine.
112+
*
113+
* @param $file
114+
*
115+
* @return string
116+
*/
117+
public static function makeBackup($file)
118+
{
119+
$backup = Scanner::getPathBackups() . DIRECTORY_SEPARATOR . str_replace(realpath(Scanner::getPathScan()), '', realpath($file));
120+
$backup = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $backup);
121+
if (!is_dir(dirname($backup))) {
122+
if (!mkdir($concurrentDirectory = dirname($backup), 0755, true) && !is_dir($concurrentDirectory)) {
123+
throw new \RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory));
124+
}
125+
}
126+
copy($file, $backup);
127+
128+
return $backup;
129+
}
130+
83131
/**
84132
* Add to Whitelist.
85133
*
@@ -90,12 +138,12 @@ public static function moveToQuarantine($file)
90138
*/
91139
public static function addToWhitelist($file, $pattern_found)
92140
{
93-
$whitelist = Application::getWhitelist();
141+
$whitelist = Scanner::getWhitelist();
94142
foreach ($pattern_found as $key => $pattern) {
95143
$exploit = $pattern['key'];
96144
$lineNumber = $pattern['line'];
97145
$match = $pattern['match'];
98-
$fileName = str_replace(Application::getPathScan(), '', $file);
146+
$fileName = str_replace(Scanner::getPathScan(), '', $file);
99147
$key = md5($exploit . $fileName . $lineNumber);
100148
$whitelist[$key] = array(
101149
'file' => $fileName,
@@ -104,9 +152,9 @@ public static function addToWhitelist($file, $pattern_found)
104152
'match' => $match,
105153
);
106154
}
107-
Application::setWhitelist($whitelist);
155+
Scanner::setWhitelist($whitelist);
108156

109-
return file_put_contents(Application::getPathWhitelist(), json_encode($whitelist));
157+
return file_put_contents(Scanner::getPathWhitelist(), json_encode($whitelist));
110158
}
111159

112160
/**
@@ -116,6 +164,10 @@ public static function addToWhitelist($file, $pattern_found)
116164
*/
117165
public static function openWithVim($file)
118166
{
167+
if (Scanner::isBackupEnabled()) {
168+
self::makeBackup($file);
169+
}
170+
119171
$descriptors = array(
120172
array('file', '/dev/tty', 'r'),
121173
array('file', '/dev/tty', 'w'),
@@ -137,6 +189,10 @@ public static function openWithVim($file)
137189
*/
138190
public static function openWithNano($file)
139191
{
192+
if (Scanner::isBackupEnabled()) {
193+
self::makeBackup($file);
194+
}
195+
140196
$descriptors = array(
141197
array('file', '/dev/tty', 'r'),
142198
array('file', '/dev/tty', 'w'),
@@ -150,4 +206,44 @@ public static function openWithNano($file)
150206
}
151207
}
152208
}
209+
210+
/**
211+
* Clean Quarantine path.
212+
*
213+
* @return bool
214+
*/
215+
public static function cleanQuarantine()
216+
{
217+
return self::unlink(Scanner::getPathQuarantine());
218+
}
219+
220+
/**
221+
* Unlink.
222+
*
223+
* @param $path
224+
*
225+
* @return bool
226+
*/
227+
protected static function unlink($path)
228+
{
229+
if (is_dir($path) && !is_link($path)) {
230+
$files = new RecursiveIteratorIterator(
231+
new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS),
232+
RecursiveIteratorIterator::CHILD_FIRST
233+
);
234+
235+
foreach ($files as $fileinfo) {
236+
$action = ($fileinfo->isDir() ? 'rmdir' : 'unlink');
237+
$action($fileinfo->getRealPath());
238+
}
239+
240+
return rmdir($path);
241+
}
242+
243+
if (file_exists($path)) {
244+
return unlink($path);
245+
}
246+
247+
return false;
248+
}
153249
}

src/Console.php

+21-12
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public static function eol($n)
8080
*/
8181
public static function header()
8282
{
83-
$version = Application::getVersion();
83+
$version = Scanner::getVersion();
8484
self::newLine(2);
8585
$header = <<<EOD
8686
█████╗ ███╗ ███╗██╗ ██╗███████╗ ██████╗ █████╗ ███╗ ██╗
@@ -336,7 +336,7 @@ public static function write($string, $foreground_color = 'white', $background_c
336336
$foreground_color = null;
337337
$background_color = null;
338338
}
339-
if (Application::isLogsEnabled() && $log === null) {
339+
if (Scanner::isLogsEnabled() && $log === null) {
340340
$log = true;
341341
}
342342
if ($escape) {
@@ -351,7 +351,7 @@ public static function write($string, $foreground_color = 'white', $background_c
351351
}
352352
$colored_string .= $return_string . "\033[0m";
353353

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

362362
if ($log) {
363-
self::log($string, $foreground_color);
363+
self::log($string, (!empty($foreground_color) && $foreground_color !== 'white' ? $foreground_color : $background_color));
364364
}
365365
}
366366

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

391391
$read = null;
392392

393-
if (!Application::isSilentMode()) {
393+
if (!Scanner::isSilentMode()) {
394394
if (stripos(PHP_OS, 'WIN') === 0) {
395-
echo Application::getName() . ' > ' . trim($string) . ' ';
395+
echo Scanner::getName() . ' > ' . trim($string) . ' ';
396396
} else {
397-
echo Application::getName() . ' > ' . trim($colored_string) . ' ';
397+
echo Scanner::getName() . ' > ' . trim($colored_string) . ' ';
398398
}
399399
}
400400

@@ -468,7 +468,7 @@ public static function log($string, $color = '')
468468
break;
469469
}
470470
$string = '[' . date('Y-m-d H:i:s') . '] [' . $type . '] ' . $string . PHP_EOL;
471-
file_put_contents(Application::getPathLogs(), $string, FILE_APPEND);
471+
file_put_contents(Scanner::getPathLogs(), $string, FILE_APPEND);
472472
}
473473
}
474474

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

0 commit comments

Comments
 (0)