├── scanner-logs
├── .gitkeep
└── scannerfiles.txt
├── README.md
├── index.php
├── LICENSE
└── src
└── phpWebScan.php
/scanner-logs/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/scanner-logs/scannerfiles.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Php Website Scanner
2 | A php script that will check all files for malware injection, new files, removed files and modified files since the last scan
3 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | readFile();
27 | $scan->scan($_SERVER['DOCUMENT_ROOT']);
28 | $scan->sendAlert();
29 |
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Kenny Turner
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/phpWebScan.php:
--------------------------------------------------------------------------------
1 | scanned_files[] = $dir;
23 |
24 | $files = scandir($dir);
25 |
26 | // loop through the DIR and check for files or Directories
27 | foreach($files as $file) {
28 | if(is_file($dir.'/'.$file) && !in_array($dir.'/'.$file,$this->scanned_files)) {
29 | // grab the cile contents and check for malware injection
30 | $this->check(file_get_contents($dir.'/'.$file),$dir.'/'.$file);
31 | } elseif(is_dir($dir.'/'.$file) && substr($file,0,1) != '.') {
32 | // do not scan scanner log files as they change every scan
33 | if($file != 'scanner-logs')
34 | $this->scan($dir.'/'.$file);
35 | }
36 | }
37 | }
38 |
39 | /**
40 | * Function to check the file contents for injections
41 | * @string $contents Content of the file
42 | * @string $file Filename being checked
43 | */
44 | public function check($contents,$file) {
45 | $this->scanned_files[] = $file;
46 | $this->fileindex[] = $file;
47 |
48 | // check for injection
49 | if(preg_match('/eval\((base64|eval|\$_|\$\$|\$[A-Za-z_0-9\{]*(\(|\{|\[))/i',$contents)) {
50 | $this->infected_files[] = $file;
51 | echo 'Infected File : '.$file.'
';
52 | }
53 |
54 | /* if you are looking for other injected code add here */
55 | if(preg_match('/x65\/li\x6eweb/' , $contents)){
56 | $this->infected_files[] = $file;
57 | echo 'Infected File : '.$file.'
';
58 | }
59 |
60 | // check for modification
61 | if(filemtime($file) > $this->lastscan){
62 | $this->modified[] = $file.' modified '.date ("F d Y H:i:s.", filemtime($file));
63 | }
64 | }
65 |
66 | /**
67 | * Function to create a message containing results of scan
68 | */
69 | public function sendalert() {
70 | // files count
71 | $message = "== FILES SCANNED ==
";
72 | $message .= count($this->fileindex)." files scanned
";
73 | $message .= count($this->oldfileindex)." last scanned
";
74 |
75 | // infected file list
76 | if(count($this->infected_files) != 0) {
77 | $message .= "== MALICIOUS CODE FOUND ==
";
78 | $message .= "The following files appear to be infected:
";
79 | foreach($this->infected_files as $inf) {
80 | $message .= " - $inf
";
81 | }
82 | } else {
83 | $message .= "
== LOOKS ALL CLEAN TO ME ==
";
84 | }
85 |
86 | // files added
87 | $difference = array_diff($this->fileindex, $this->oldfileindex);
88 | if(count($difference) > 0){
89 | // set flag for file write
90 | $updateList = true;
91 |
92 | $message .= "
== FILES ADDED ==
";
93 | foreach ($difference as $added) {
94 | $message .= $added."
";
95 | }
96 | } else {
97 | $message .= "
== NO FILES HAVE BEEN ADDED ==
";
98 | }
99 |
100 | // files Removed
101 | $removed = array_diff($this->oldfileindex, $this->fileindex);
102 | if(count($removed) > 0){
103 | // set flag for file write
104 | $updateList = true;
105 |
106 | // add results to message
107 | $message .= "
== FILES REMOVED ==
";
108 | foreach ($removed as $deleted) {
109 | $message .= $deleted."
";
110 | }
111 | } else {
112 | $message .= "
== NO FILES HAVE BEEN REMOVED ==
";
113 | }
114 |
115 | // files modified
116 | if(count($this->modified) > 0) {
117 | // set flag for file write
118 | $updateList = true;
119 |
120 | $message .= "
== FILES MODIFIED ==
";
121 | foreach ($this->modified as $modded) {
122 | $message .= $modded."
";
123 | }
124 | } else {
125 | $message .= "
== NO FILES HAVE BEEN MODIFIED ==
";
126 | }
127 |
128 | // do we need to create an updated file list
129 | if($updateList){
130 | // create an update file list
131 | self::writeFile();
132 | }
133 |
134 | $header = "
'.$message.''; 145 | 146 | // log record 147 | self::logResults($message); 148 | } 149 | 150 | /** 151 | * Function will create a file containing a serialiazed array of files scanned 152 | */ 153 | public function writeFile() { 154 | // debug. Uncomment to get a fresh file list 155 | // $this->freshclean(); 156 | 157 | $data = serialize($this->fileindex); 158 | $fopen = fopen('scanner-logs/scannerfiles.txt', 'w+'); 159 | fwrite($fopen, $data); 160 | fclose($fopen); 161 | } 162 | 163 | /** 164 | * Function to read the previously canned filenames and unserialize them to an array 165 | * It will also return the last time a file list was created 166 | */ 167 | public function readFile() { 168 | $this->oldfileindex = unserialize(file_get_contents('scanner-logs/scannerfiles.txt')); 169 | $this->lastscan = filemtime('scanner-logs/scannerfiles.txt'); 170 | } 171 | 172 | /** 173 | * Function to help with debugging. Will clear the fileindex array. 174 | */ 175 | public function freshclean() { 176 | unset($this->fileindex); 177 | $this->fileindex[] = ''; 178 | } 179 | 180 | /** 181 | * Function to log results for future reading 182 | * @string $message Records a log of the results 183 | */ 184 | public function logResults($message) { 185 | $fopen = fopen('scanner-logs/scan-results-'.date('H:i').'.log', 'w+'); 186 | fwrite($fopen, $message); 187 | fclose($fopen); 188 | } 189 | } 190 | 191 | 192 | 193 | --------------------------------------------------------------------------------