PluginProbe ʕ •ᴥ•ʔ
Wordfence Security – Firewall, Malware Scan, and Login Security / 3.2.6
Wordfence Security – Firewall, Malware Scan, and Login Security v3.2.6
8.2.2 8.2.1 8.2.0 3.7.1 3.7.2 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.8.8 3.8.9 3.9.1 4.0.1 4.0.2 4.0.3 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.0.9 5.1.1 5.1.2 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.2.1 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.1 5.3.10 5.3.11 5.3.12 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.3.8 5.3.9 6.0.1 6.0.10 6.0.11 6.0.12 6.0.14 6.0.15 6.0.16 6.0.17 6.0.18 6.0.19 6.0.2 6.0.20 6.0.21 6.0.22 6.0.23 6.0.24 6.0.25 6.0.3 6.0.4 6.0.5 6.0.6 6.0.7 6.0.8 6.0.9 6.1.1 6.1.10 6.1.11 6.1.12 6.1.14 6.1.15 6.1.16 6.1.17 6.1.2 6.1.3 6.1.4 6.1.5 6.1.6 6.1.7 6.1.8 6.1.9 6.2.0 6.2.1 6.2.10 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.7 6.2.8 6.2.9 6.3.0 6.3.1 6.3.10 6.3.11 6.3.12 6.3.14 6.3.15 6.3.16 6.3.17 6.3.18 6.3.19 6.3.2 6.3.20 6.3.21 6.3.22 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.3.8 6.3.9 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1.0 7.1.1 7.1.10 7.1.11 7.1.12 7.1.14 7.1.15 7.1.16 7.1.17 7.1.18 7.1.19 7.1.2 7.1.20 7.1.3 7.1.4 7.1.5 7.1.6 7.1.7 7.1.8 7.1.9 7.10.0 7.10.1 7.10.2 7.10.3 7.10.4 7.10.5 7.10.6 7.10.7 7.11.0 7.11.1 7.11.2 7.11.3 7.11.4 7.11.5 7.11.6 7.11.7 7.2.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3.1 7.3.2 7.3.3 7.3.4 7.3.5 7.3.6 7.4.0 7.4.1 7.4.10 7.4.11 7.4.12 7.4.14 7.4.2 7.4.3 trunk 7.4.4 1.1 7.4.5 1.2 7.4.6 1.3 7.4.7 1.3.1 7.4.8 1.3.2 7.4.9 1.3.3 7.5.0 1.4.2 7.5.1 1.4.3 7.5.10 1.4.4 7.5.11 1.4.5 7.5.2 1.4.6 7.5.3 1.4.7 7.5.4 1.4.8 7.5.5 1.5.1 7.5.6 1.5.2 7.5.7 1.5.3 7.5.8 1.5.4 7.5.9 1.5.5 7.6.0 1.5.6 7.6.1 2.0.1 7.6.2 2.0.2 7.7.0 2.0.3 7.7.1 2.0.5 7.8.0 2.0.6 7.8.1 2.0.7 7.8.2 2.1.0 7.9.0 2.1.1 7.9.1 2.1.2 7.9.2 2.1.3 7.9.3 2.1.4 8.0.0 2.1.5 8.0.1 3.0.2 8.0.2 3.0.3 8.0.3 3.0.4 8.0.4 3.0.5 8.0.5 3.0.6 8.1.0 3.0.7 8.1.1 3.0.8 8.1.2 3.0.9 8.1.3 3.1.0 8.1.4 3.1.1 v1.4.1 3.1.2 3.1.4 3.1.6 3.2.1 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.4.1 3.4.4 3.4.5 3.5.1 3.5.2 3.6.1 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9
wordfence / lib / wordfenceHash.php
wordfence / lib Last commit date
Diff 14 years ago .htaccess 14 years ago Diff.php 14 years ago GeoIP.dat 13 years ago IPTraf.php 13 years ago diffResult.php 14 years ago email_genericAlert.php 14 years ago email_newIssues.php 14 years ago email_unlockRequest.php 14 years ago menu_activity.php 13 years ago menu_blockedIPs.php 13 years ago menu_countryBlocking.php 13 years ago menu_options.php 13 years ago menu_scan.php 13 years ago menu_scanSchedule.php 13 years ago schedWeekEntry.php 13 years ago sysinfo.php 14 years ago unknownFiles.php 13 years ago viewFullActivityLog.php 13 years ago wf503.php 13 years ago wfAPI.php 13 years ago wfAction.php 14 years ago wfArray.php 13 years ago wfBrowscap.php 14 years ago wfBrowscapCache.php 14 years ago wfBulkCountries.php 13 years ago wfConfig.php 13 years ago wfCountryMap.php 13 years ago wfCrawl.php 13 years ago wfDB.php 13 years ago wfDict.php 14 years ago wfGeoIP.php 13 years ago wfIssues.php 13 years ago wfLockedOut.php 14 years ago wfLog.php 13 years ago wfModTracker.php 14 years ago wfRate.php 14 years ago wfScanEngine.php 13 years ago wfSchema.php 13 years ago wfUnlockMsg.php 14 years ago wfUtils.php 13 years ago wfViewResult.php 14 years ago wordfenceClass.php 13 years ago wordfenceConstants.php 13 years ago wordfenceHash.php 13 years ago wordfenceScanner.php 13 years ago wordfenceURLHoover.php 13 years ago
wordfenceHash.php
224 lines
1 <?php
2 require_once('wordfenceClass.php');
3 class wordfenceHash {
4 private $apiKey = false;
5 private $wp_version = false;
6 private $api = false;
7 private $db = false;
8 private $table = false;
9 private $fileQ = array();
10
11 //Begin serialized vars
12 private $whitespace = array("\n","\r","\t"," ");
13 public $totalData = 0; //To do a sanity check, don't use 'du' because it gets sparse files wrong and reports blocks used on disk. Use : find . -type f -ls | awk '{total += $7} END {print total}'
14 public $totalFiles = 0;
15 public $totalDirs = 0;
16 public $linesOfPHP = 0;
17 public $linesOfJCH = 0; //lines of HTML, CSS and javascript
18 public $striplen = 0;
19 private $hashPacket = "";
20 public $hashStorageID = false;
21 private $hashingStartTime = false;
22 private $lastStatusTime = false;
23 public function __sleep(){ //same order as above
24 if(sizeof($this->fileQ) > 0){
25 throw new Exception("Sanity fail. fileQ is not empty. Has: " . sizeof($this->fileQ));
26 }
27 return array('whitespace', 'totalData', 'totalFiles', 'totalDirs', 'linesOfPHP', 'linesOfJCH', 'striplen', 'hashPacket', 'hashStorageID', 'hashingStartTime', 'lastStatusTime');
28 }
29 public function __construct($striplen){
30 $this->striplen = $striplen;
31 $this->db = new wfDB();
32 $this->table = $this->db->prefix() . 'wfFileQueue';
33 $this->apiKey = wfConfig::get('apiKey');
34 $this->wp_version = wfUtils::getWPVersion();
35 $this->api = new wfAPI($this->apiKey, $this->wp_version);
36 }
37 public function __wakeup(){
38 $this->db = new wfDB();
39 $this->table = $this->db->prefix() . 'wfFileQueue';
40 $this->apiKey = wfConfig::get('apiKey');
41 $this->wp_version = wfUtils::getWPVersion();
42 $this->api = new wfAPI($this->apiKey, $this->wp_version);
43 }
44 public function buildFileQueue($path, $only = array()){ //base path and 'only' is a list of files and dirs in the bast that are the only ones that should be processed. Everything else in base is ignored. If only is empty then everything is processed.
45 $this->db->truncate($this->table);
46 if($path[strlen($path) - 1] != '/'){
47 $path .= '/';
48 }
49 if(! is_readable($path)){
50 throw new Exception("Could not read directory $path to do scan.");
51 exit();
52 }
53 $files = scandir($path);
54 foreach($files as $file){
55 if(sizeof($only) > 0 && (! in_array($file, $only))){
56 continue;
57 }
58 $file = $path . $file;
59 wordfence::status(4, 'info', "Hashing item in base dir: $file");
60 $this->_dirHash($file);
61 }
62 $this->writeFileQueue(); //Final write to DB
63
64 }
65 public function genHashes($forkObj){
66 if(! $this->hashingStartTime){
67 $this->hashingStartTime = microtime(true);
68 }
69 if(! $this->lastStatusTime){
70 $this->lastStatusTime = microtime(true);
71 }
72 $haveMoreInDB = true;
73 while($haveMoreInDB){
74 $haveMoreInDB = false;
75 //This limit used to be 1000, but we changed it to 5 because forkIfNeeded needs to run frequently, but
76 // we still want to minimize the number of queries we do.
77 // So now we select, process and delete 5 from teh queue and then check forkIfNeeded()
78 // So this assumes that processing 5 files won't take longer than wfScanEngine::$maxExecTime (which was 10 at the time of writing, which is 2 secs per file)
79 $res = $this->db->query("select id, filename from " . $this->table . " limit 5");
80 $ids = array();
81 while($rec = mysql_fetch_row($res)){
82 $this->processFile($rec[1]);
83 array_push($ids, $rec[0]);
84 $haveMoreInDB = true;
85 }
86 if(sizeof($ids) > 0){
87 $this->db->query("delete from " . $this->table . " where id IN (" . implode(',', $ids) . ")");
88 }
89 $forkObj->forkIfNeeded();
90 }
91 //Will only reach here if we empty file queue. fork may cause exit
92 $this->sendHashPacket();
93 $this->db->truncate($this->table); //Also resets id autoincrement to 1
94 $this->writeHashingStatus();
95 }
96 private function writeHashingStatus(){
97 $this->lastStatusTime = microtime(true);
98 wordfence::status(2, 'info', "Scanned " . $this->totalFiles . " files at a rate of " . sprintf('%.2f', ($this->totalFiles / (microtime(true) - $this->hashingStartTime))) . " files per second.");
99 }
100 private function _dirHash($path){
101 if(substr($path, -3, 3) == '/..' || substr($path, -2, 2) == '/.'){
102 return;
103 }
104 if(! is_readable($path)){ return; } //Applies to files and dirs
105 if(is_dir($path)){
106 $this->totalDirs++;
107 if($path[strlen($path) - 1] != '/'){
108 $path .= '/';
109 }
110 $cont = scandir($path);
111 for($i = 0; $i < sizeof($cont); $i++){
112 if($cont[$i] == '.' || $cont[$i] == '..'){ continue; }
113 $file = $path . $cont[$i];
114 if(is_file($file)){
115 $this->qFile($file);
116 } else if(is_dir($file)) {
117 $this->_dirHash($file);
118 }
119 }
120 } else {
121 if(is_file($path)){
122 $this->qFile($path);
123 }
124 }
125 }
126 private function qFile($file){
127 $this->fileQ[] = $file;
128 if(sizeof($this->fileQ) > 1000){
129 $this->writeFileQueue();
130 }
131 }
132 private function writeFileQueue(){
133 $sql = "insert into " . $this->table . " (filename) values ";
134 $added = false;
135 foreach($this->fileQ as $val){
136 $added = true;
137 $sql .= "('" . mysql_real_escape_string($val) . "'),";
138 }
139 if($added){
140 $sql = rtrim($sql, ',');
141 $this->db->query($sql);
142 }
143 $this->fileQ = array();
144 }
145 private function processFile($file){
146 if(wfUtils::fileTooBig($file)){
147 wordfence::status(4, 'info', "Skipping file larger than max size: $file");
148 return;
149 }
150 if(function_exists('memory_get_usage')){
151 wordfence::status(4, 'info', "Scanning: $file (Mem:" . sprintf('%.1f', memory_get_usage(true) / (1024 * 1024)) . "M)");
152 } else {
153 wordfence::status(4, 'info', "Scanning: $file");
154 }
155 $wfHash = $this->wfHash($file);
156 if($wfHash){
157 $packetFile = substr($file, $this->striplen);
158 $this->hashPacket .= $wfHash[0] . $wfHash[1] . pack('n', strlen($packetFile)) . $packetFile;
159 if(strlen($this->hashPacket) > 500000){ //roughly 2 megs in string mem space
160 $this->writeHashingStatus();
161 $this->sendHashPacket();
162 }
163
164 //Now that we know we can open the file, lets update stats
165 if(preg_match('/\.(?:js|html|htm|css)$/i', $file)){
166 $this->linesOfJCH += sizeof(file($file));
167 } else if(preg_match('/\.php$/i', $file)){
168 $this->linesOfPHP += sizeof(file($file));
169 }
170 $this->totalFiles++;
171 $this->totalData += filesize($file); //We already checked if file overflows int in the fileTooBig routine above
172 if(microtime(true) - $this->lastStatusTime > 1){
173 $this->writeHashingStatus();
174 }
175 } else {
176 wordfence::status(2, 'error', "Could not gen hash for file (probably because we don't have permission to access the file): $file");
177 }
178 }
179 private function sendHashPacket(){
180 wordfence::status(4, 'info', "Sending packet of hash data to Wordfence scanning servers");
181 if(strlen($this->hashPacket) < 1){
182 return;
183 }
184 if($this->hashStorageID){
185 $dataArr = $this->api->binCall('add_hash_chunk', "WFID:" . pack('N', $this->hashStorageID) . $this->hashPacket);
186 $this->hashPacket = "";
187 if(is_array($dataArr) && isset($dataArr['data']) && $dataArr['data'] == $this->hashStorageID){
188 //keep going
189 } else {
190 throw new Exception("Could not store an additional chunk of hash data on Wordfence servers with ID: " . $this->hashStorageID);
191 }
192 } else {
193 $dataArr = $this->api->binCall('add_hash_chunk', "WFST:" . $this->hashPacket);
194 $this->hashPacket = "";
195 if(is_array($dataArr) && isset($dataArr['data']) && preg_match('/^\d+$/', $dataArr['data'])){
196 $this->hashStorageID = $dataArr['data'];
197 } else {
198 throw new Exception("Could not store hash data on Wordfence servers. Got response: " . var_export($dataArr, true));
199 }
200 }
201 }
202 public function getHashStorageID(){
203 return $this->hashStorageID;
204 }
205 public function wfHash($file){
206 wfUtils::errorsOff();
207 $md5 = @md5_file($file, false);
208 wfUtils::errorsOn();
209
210 if(! $md5){ return false; }
211 $fp = @fopen($file, "rb");
212 if(! $fp){
213 return false;
214 }
215 $ctx = hash_init('sha256');
216 while (!feof($fp)) {
217 hash_update($ctx, str_replace($this->whitespace,"",fread($fp, 65536)));
218 }
219 $shac = hash_final($ctx, false);
220 return array($md5, $shac);
221 }
222 }
223 ?>
224