Version Description
- Improved malware and phishing URL detection.
- Upgraded to Wordfence API version 1.9
- Fixed issue that caused large files to slow or crash a scan.
- Added workaround for PHP's broken filesize() function on 32 bit systems.
- Added an improved test mode for URL scanner for better unit testing on our end.
- Suppressed warnings issued when a reverse DNS lookup fails.
- Added improved debug output to becomeAdmin() function in scans to help diagnose scans not starting.
Download this release
Release Info
Developer | mmaunder |
Plugin | Wordfence Security – Firewall & Malware Scan |
Version | 3.0.6 |
Comparing to | |
See all releases |
Code changes from version 3.0.5 to 3.0.6
- js/admin.js +1 -1
- lib/wfAPI.php +1 -1
- lib/wfScanEngine.php +28 -1
- lib/wfUtils.php +27 -1
- lib/wordfenceClass.php +8 -6
- lib/wordfenceConstants.php +1 -1
- lib/wordfenceHash.php +5 -6
- lib/wordfenceScanner.php +7 -1
- lib/wordfenceURLHoover.php +102 -49
- readme.txt +13 -1
- wfscan.php +8 -0
- wordfence.php +2 -2
js/admin.js
CHANGED
@@ -503,7 +503,7 @@ window['wordfenceAdmin'] = {
|
|
503 |
var cb = false;
|
504 |
var self = this;
|
505 |
if(res.ok){
|
506 |
-
this.loadIssues(function(){ self.colorbox('400px', "Success deleting file", "The file " + res.file + "
|
507 |
} else if(res.cerrorMsg){
|
508 |
this.loadIssues(function(){ self.colorbox('400px', 'An error occurred', res.cerrorMsg); });
|
509 |
}
|
503 |
var cb = false;
|
504 |
var self = this;
|
505 |
if(res.ok){
|
506 |
+
this.loadIssues(function(){ self.colorbox('400px', "Success deleting file", "The file " + res.file + " was successfully deleted."); });
|
507 |
} else if(res.cerrorMsg){
|
508 |
this.loadIssues(function(){ self.colorbox('400px', 'An error occurred', res.cerrorMsg); });
|
509 |
}
|
lib/wfAPI.php
CHANGED
@@ -46,7 +46,7 @@ class wfAPI {
|
|
46 |
$this->curlContent = "";
|
47 |
$curl = curl_init($url);
|
48 |
curl_setopt ($curl, CURLOPT_TIMEOUT, 300);
|
49 |
-
curl_setopt ($curl, CURLOPT_USERAGENT, "Wordfence.com UA " . WORDFENCE_VERSION);
|
50 |
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, TRUE);
|
51 |
curl_setopt ($curl, CURLOPT_HEADER, 0);
|
52 |
curl_setopt ($curl, CURLOPT_SSL_VERIFYPEER, false);
|
46 |
$this->curlContent = "";
|
47 |
$curl = curl_init($url);
|
48 |
curl_setopt ($curl, CURLOPT_TIMEOUT, 300);
|
49 |
+
curl_setopt ($curl, CURLOPT_USERAGENT, "Wordfence.com UA " . (defined('WORDFENCE_VERSION') ? WORDFENCE_VERSION : '[Unknown version]') );
|
50 |
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, TRUE);
|
51 |
curl_setopt ($curl, CURLOPT_HEADER, 0);
|
52 |
curl_setopt ($curl, CURLOPT_SSL_VERIFYPEER, false);
|
lib/wfScanEngine.php
CHANGED
@@ -177,7 +177,7 @@ class wfScanEngine {
|
|
177 |
$fullFile = rtrim(ABSPATH, '/') . '/' . $file;
|
178 |
if($scanOutside){
|
179 |
$includeInScan[] = $file;
|
180 |
-
} else if(in_array($file, $baseWPStuff) || (is_file($fullFile) && is_readable($fullFile) &&
|
181 |
$includeInScan[] = $file;
|
182 |
}
|
183 |
}
|
@@ -621,6 +621,33 @@ class wfScanEngine {
|
|
621 |
$this->status(2, 'info', "Completed checking password strength of user '" . $userDat->user_login . "'");
|
622 |
return $haveIssue;
|
623 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
624 |
private function scan_diskSpace(){
|
625 |
$this->statusIDX['diskSpace'] = wordfence::statusStart("Scanning to check available disk space");
|
626 |
wfUtils::errorsOff();
|
177 |
$fullFile = rtrim(ABSPATH, '/') . '/' . $file;
|
178 |
if($scanOutside){
|
179 |
$includeInScan[] = $file;
|
180 |
+
} else if(in_array($file, $baseWPStuff) || (is_file($fullFile) && is_readable($fullFile) && (! wfUtils::fileTooBig($fullFile)) ) ){
|
181 |
$includeInScan[] = $file;
|
182 |
}
|
183 |
}
|
621 |
$this->status(2, 'info', "Completed checking password strength of user '" . $userDat->user_login . "'");
|
622 |
return $haveIssue;
|
623 |
}
|
624 |
+
/*
|
625 |
+
private function scan_sitePages(){
|
626 |
+
if(is_multisite()){ return; } //Multisite not supported by this function yet
|
627 |
+
$this->statusIDX['sitePages'] = wordfence::statusStart("Scanning externally for malware");
|
628 |
+
$resp = wp_remote_get(site_url());
|
629 |
+
if(is_array($resp) && isset($resp['body']) && strlen($rep['body']) > 0){
|
630 |
+
$this->hoover = new wordfenceURLHoover($this->apiKey, $this->wp_version);
|
631 |
+
$this->hoover->hoover(1, $rep['body']);
|
632 |
+
$hooverResults = $this->hoover->getBaddies();
|
633 |
+
if($this->hoover->errorMsg){
|
634 |
+
wordfence::statusEndErr();
|
635 |
+
throw new Exception($this->hoover->errorMsg);
|
636 |
+
}
|
637 |
+
$badURLs = array();
|
638 |
+
foreach($hooverResults as $idString => $hresults){
|
639 |
+
foreach($hresults as $result){
|
640 |
+
if(! in_array($result['URL'], $badURLs)){
|
641 |
+
$badURLs[] = $result['URL'];
|
642 |
+
}
|
643 |
+
}
|
644 |
+
}
|
645 |
+
if(sizeof($badURLs) > 0){
|
646 |
+
$this->addIssue('badSitePage', 1, 'badSitePage1', 'badSitePage1', "Your home page contains a malware URL");
|
647 |
+
}
|
648 |
+
}
|
649 |
+
}
|
650 |
+
*/
|
651 |
private function scan_diskSpace(){
|
652 |
$this->statusIDX['diskSpace'] = wordfence::statusStart("Scanning to check available disk space");
|
653 |
wfUtils::errorsOff();
|
lib/wfUtils.php
CHANGED
@@ -354,7 +354,7 @@ class wfUtils {
|
|
354 |
$host = $db->querySingle("select host from " . $reverseTable . " where IP=%s and unix_timestamp() - lastUpdate < %d", $IPn, WORDFENCE_REVERSE_LOOKUP_CACHE_TIME);
|
355 |
if(! $host){
|
356 |
$ptr = implode(".", array_reverse(explode(".",$IP))) . ".in-addr.arpa";
|
357 |
-
$host = dns_get_record($ptr, DNS_PTR);
|
358 |
if($host == null){
|
359 |
$host = 'NONE';
|
360 |
} else {
|
@@ -380,6 +380,32 @@ class wfUtils {
|
|
380 |
@ini_set('display_errors', self::$lastDisplayErrors);
|
381 |
if(class_exists('wfScan')){ wfScan::$errorHandlingOn = true; }
|
382 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
383 |
}
|
384 |
|
385 |
|
354 |
$host = $db->querySingle("select host from " . $reverseTable . " where IP=%s and unix_timestamp() - lastUpdate < %d", $IPn, WORDFENCE_REVERSE_LOOKUP_CACHE_TIME);
|
355 |
if(! $host){
|
356 |
$ptr = implode(".", array_reverse(explode(".",$IP))) . ".in-addr.arpa";
|
357 |
+
$host = @dns_get_record($ptr, DNS_PTR);
|
358 |
if($host == null){
|
359 |
$host = 'NONE';
|
360 |
} else {
|
380 |
@ini_set('display_errors', self::$lastDisplayErrors);
|
381 |
if(class_exists('wfScan')){ wfScan::$errorHandlingOn = true; }
|
382 |
}
|
383 |
+
public static function fileTooBig($file){
|
384 |
+
$fh = @fopen($file, 'r');
|
385 |
+
if(! $fh){ return false; }
|
386 |
+
$offset = WORDFENCE_MAX_FILE_SIZE_TO_PROCESS + 1;
|
387 |
+
$tooBig = false;
|
388 |
+
if(fseek($fh, $offset, SEEK_SET) === 0){
|
389 |
+
if(strlen(fread($fh, 1)) === 1){
|
390 |
+
$tooBig = true;
|
391 |
+
}
|
392 |
+
} //Otherwise we couldn't seek there so it must be smaller
|
393 |
+
fclose($fh);
|
394 |
+
return $tooBig;
|
395 |
+
}
|
396 |
+
public static function fileOver2Gigs($file){
|
397 |
+
$fh = @fopen($file, 'r');
|
398 |
+
if(! $fh){ return false; }
|
399 |
+
$offset = 2147483647;
|
400 |
+
$tooBig = false;
|
401 |
+
if(fseek($fh, $offset, SEEK_SET) === 0){
|
402 |
+
if(strlen(fread($fh, 1)) === 1){
|
403 |
+
$tooBig = true;
|
404 |
+
}
|
405 |
+
} //Otherwise we couldn't seek there so it must be smaller
|
406 |
+
fclose($fh);
|
407 |
+
return $tooBig;
|
408 |
+
}
|
409 |
}
|
410 |
|
411 |
|
lib/wordfenceClass.php
CHANGED
@@ -818,14 +818,12 @@ class wordfence {
|
|
818 |
if(strpos($localFile, ABSPATH) !== 0){
|
819 |
return array('errorMsg' => "An invalid file was requested for deletion.");
|
820 |
}
|
821 |
-
$filesize = filesize($localFile);
|
822 |
if(@unlink($localFile)){
|
823 |
$wfIssues->updateIssue($issueID, 'delete');
|
824 |
return array(
|
825 |
'ok' => 1,
|
826 |
'localFile' => $localFile,
|
827 |
-
'file' => $file
|
828 |
-
'filesize' => $filesize
|
829 |
);
|
830 |
} else {
|
831 |
$err = error_get_last();
|
@@ -1037,7 +1035,7 @@ class wordfence {
|
|
1037 |
$cont = @file_get_contents($localFile);
|
1038 |
$isEmpty = false;
|
1039 |
if(! $cont){
|
1040 |
-
if(file_exists($localFile) && filesize($localFile) === 0){
|
1041 |
$isEmpty = true;
|
1042 |
} else {
|
1043 |
$err = error_get_last();
|
@@ -1047,8 +1045,12 @@ class wordfence {
|
|
1047 |
}
|
1048 |
$fileMTime = @filemtime($localFile);
|
1049 |
$fileMTime = date('l jS \of F Y h:i:s A', $fileMTime);
|
1050 |
-
|
1051 |
-
|
|
|
|
|
|
|
|
|
1052 |
|
1053 |
require 'wfViewResult.php';
|
1054 |
exit(0);
|
818 |
if(strpos($localFile, ABSPATH) !== 0){
|
819 |
return array('errorMsg' => "An invalid file was requested for deletion.");
|
820 |
}
|
|
|
821 |
if(@unlink($localFile)){
|
822 |
$wfIssues->updateIssue($issueID, 'delete');
|
823 |
return array(
|
824 |
'ok' => 1,
|
825 |
'localFile' => $localFile,
|
826 |
+
'file' => $file
|
|
|
827 |
);
|
828 |
} else {
|
829 |
$err = error_get_last();
|
1035 |
$cont = @file_get_contents($localFile);
|
1036 |
$isEmpty = false;
|
1037 |
if(! $cont){
|
1038 |
+
if(file_exists($localFile) && filesize($localFile) === 0){ //There's a remote possibility that very large files on 32 bit systems will return 0 here, but it's about 1 in 2 billion
|
1039 |
$isEmpty = true;
|
1040 |
} else {
|
1041 |
$err = error_get_last();
|
1045 |
}
|
1046 |
$fileMTime = @filemtime($localFile);
|
1047 |
$fileMTime = date('l jS \of F Y h:i:s A', $fileMTime);
|
1048 |
+
if(wfUtils::fileOver2Gigs($localFile)){
|
1049 |
+
$fileSize = "Greater than 2 Gigs";
|
1050 |
+
} else {
|
1051 |
+
$fileSize = @filesize($localFile); //Checked if over 2 gigs above
|
1052 |
+
$fileSize = number_format($fileSize, 0, '', ',') . ' bytes';
|
1053 |
+
}
|
1054 |
|
1055 |
require 'wfViewResult.php';
|
1056 |
exit(0);
|
lib/wordfenceConstants.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
define('WORDFENCE_API_VERSION', 1.
|
3 |
define('WORDFENCE_API_URL_SEC', 'https://noc1.wordfence.com/');
|
4 |
define('WORDFENCE_API_URL_NONSEC', 'http://noc1.wordfence.com/');
|
5 |
define('WORDFENCE_MAX_SCAN_TIME', 600);
|
1 |
<?php
|
2 |
+
define('WORDFENCE_API_VERSION', 1.9);
|
3 |
define('WORDFENCE_API_URL_SEC', 'https://noc1.wordfence.com/');
|
4 |
define('WORDFENCE_API_URL_NONSEC', 'http://noc1.wordfence.com/');
|
5 |
define('WORDFENCE_MAX_SCAN_TIME', 600);
|
lib/wordfenceHash.php
CHANGED
@@ -139,16 +139,15 @@ class wordfenceHash {
|
|
139 |
$this->fileQ = array();
|
140 |
}
|
141 |
private function processFile($file){
|
142 |
-
if(
|
143 |
-
wordfence::status(
|
144 |
return;
|
145 |
}
|
146 |
-
|
147 |
if(function_exists('memory_get_usage')){
|
148 |
wordfence::status(4, 'info', "Scanning: $file (Mem:" . sprintf('%.1f', memory_get_usage(true) / (1024 * 1024)) . "M)");
|
149 |
-
|
150 |
wordfence::status(4, 'info', "Scanning: $file");
|
151 |
-
|
152 |
$wfHash = $this->wfHash($file);
|
153 |
if($wfHash){
|
154 |
$packetFile = substr($file, $this->striplen);
|
@@ -165,7 +164,7 @@ class wordfenceHash {
|
|
165 |
$this->linesOfPHP += sizeof(file($file));
|
166 |
}
|
167 |
$this->totalFiles++;
|
168 |
-
$this->totalData += filesize($file);
|
169 |
if(microtime(true) - $this->lastStatusTime > 1){
|
170 |
$this->writeHashingStatus();
|
171 |
}
|
139 |
$this->fileQ = array();
|
140 |
}
|
141 |
private function processFile($file){
|
142 |
+
if(wfUtils::fileTooBig($file)){
|
143 |
+
wordfence::status(4, 'info', "Skipping file larger than max size: $file");
|
144 |
return;
|
145 |
}
|
|
|
146 |
if(function_exists('memory_get_usage')){
|
147 |
wordfence::status(4, 'info', "Scanning: $file (Mem:" . sprintf('%.1f', memory_get_usage(true) / (1024 * 1024)) . "M)");
|
148 |
+
} else {
|
149 |
wordfence::status(4, 'info', "Scanning: $file");
|
150 |
+
}
|
151 |
$wfHash = $this->wfHash($file);
|
152 |
if($wfHash){
|
153 |
$packetFile = substr($file, $this->striplen);
|
164 |
$this->linesOfPHP += sizeof(file($file));
|
165 |
}
|
166 |
$this->totalFiles++;
|
167 |
+
$this->totalData += filesize($file); //We already checked if file overflows int in the fileTooBig routine above
|
168 |
if(microtime(true) - $this->lastStatusTime > 1){
|
169 |
$this->writeHashingStatus();
|
170 |
}
|
lib/wordfenceScanner.php
CHANGED
@@ -64,7 +64,13 @@ class wordfenceScanner {
|
|
64 |
if(preg_match('/^(?:jpg|jpeg|mp3|avi|m4v|gif|png)$/', $fileExt)){
|
65 |
continue;
|
66 |
}
|
67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
if($fsize > 1000000){
|
69 |
$fsize = sprintf('%.2f', ($fsize / 1000000)) . "M";
|
70 |
} else {
|
64 |
if(preg_match('/^(?:jpg|jpeg|mp3|avi|m4v|gif|png)$/', $fileExt)){
|
65 |
continue;
|
66 |
}
|
67 |
+
if(wfUtils::fileTooBig($this->path . $file)){
|
68 |
+
//We should not need this check because files > 2 gigs are not hashed and therefore won't be received back as unknowns from the API server
|
69 |
+
//But we do it anyway to be safe.
|
70 |
+
wordfence::status(2, 'error', "Encountered file that is too large: $file - Skipping.");
|
71 |
+
continue;
|
72 |
+
}
|
73 |
+
$fsize = filesize($this->path . $file); //Checked if too big above
|
74 |
if($fsize > 1000000){
|
75 |
$fsize = sprintf('%.2f', ($fsize / 1000000)) . "M";
|
76 |
} else {
|
lib/wordfenceURLHoover.php
CHANGED
@@ -8,6 +8,9 @@ class wordfenceURLHoover {
|
|
8 |
private $table = '';
|
9 |
private $apiKey = false;
|
10 |
private $wordpressVersion = false;
|
|
|
|
|
|
|
11 |
private $dRegex = 'aero|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|ss|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw|xn--lgbbat1ad8j|xn--fiqs8s|xn--fiqz9s|xn--wgbh1c|xn--j6w193g|xn--h2brj9c|xn--mgbbh1a71e|xn--fpcrj9c3d|xn--gecrj9c|xn--s9brj9c|xn--xkc2dl3a5ee0h|xn--45brj9c|xn--mgba3a4f16a|xn--mgbayh7gpa|xn--mgbc0a9azcg|xn--ygbi2ammx|xn--wgbl6a|xn--p1ai|xn--mgberp4a5d4ar|xn--90a3ac|xn--yfro4i67o|xn--clchc0ea0b2g2a9gcd|xn--3e0b707e|xn--fzc2c9e2c|xn--xkc2al3hye2a|xn--mgbtf8fl|xn--kprw13d|xn--kpry57d|xn--o3cw4h|xn--pgbs0dh|xn--mgbaam7a8h|xn--54b7fta0cc|xn--90ae|xn--node|xn--4dbrk0ce|xn--80ao21a|xn--mgb9awbf|xn--mgbai9azgqp6j|xn--j1amh|xn--mgb2ddes|xn--kgbechtv|xn--hgbk6aj7f53bba|xn--0zwm56d|xn--g6w251d|xn--80akhbyknj4f|xn--11b5bs3a9aj6g|xn--jxalpdlp|xn--9t4b11yi5a|xn--deba0ad|xn--zckzah|xn--hlcj6aya9esc7a';
|
12 |
private $api = false;
|
13 |
private $db = false;
|
@@ -20,37 +23,61 @@ class wordfenceURLHoover {
|
|
20 |
$this->api = new wfAPI($this->apiKey, $this->wordpressVersion);
|
21 |
$this->db = new wfDB();
|
22 |
}
|
23 |
-
public function __construct($apiKey, $wordpressVersion){
|
24 |
$this->hostsToAdd = new wfArray(array('owner', 'host', 'path', 'hostKey'));
|
25 |
$this->apiKey = $apiKey;
|
26 |
$this->wordpressVersion = $wordpressVersion;
|
27 |
$this->api = new wfAPI($apiKey, $wordpressVersion);
|
28 |
-
$
|
|
|
|
|
|
|
|
|
29 |
global $wpdb;
|
30 |
-
$
|
|
|
|
|
|
|
|
|
31 |
$this->db->query("truncate table $this->table");
|
32 |
}
|
33 |
public function hoover($id, $data){
|
34 |
if(strpos($data, '.') === false){
|
35 |
return;
|
36 |
}
|
37 |
-
if(! preg_match('/[a-zA-Z0-9\-]+\.(?:' . $this->dRegex . ')/i', $data)){
|
38 |
-
return;
|
39 |
-
}
|
40 |
try {
|
41 |
@preg_replace("/(?<=^|[^a-zA-Z0-9\-])((?:[a-zA-Z0-9\-]+\.)+)(" . $this->dRegex . ")((?:$|[^a-zA-Z0-9\-\.\'\"])[^\r\n\s\t\"\'\$\{\}<>]*)/ie", "\$this->" . "addHost(\$id, '$1$2', '$3')", $data);
|
42 |
} catch(Exception $e){ error_log("Regex error 1: $e"); }
|
43 |
-
preg_replace("/(?<=[^\d]|^)(\d{8,10}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})([^\d\'\"][^\r\n\s\t\"\'\$\{\}<>]*)/e", "\$this->" . "addIP(\$id, \"$1\",\"$2\")", $data);
|
44 |
$this->writeHosts();
|
45 |
}
|
46 |
private function dbg($msg){ if($this->debug){ error_log("DEBUG: $msg\n"); } }
|
47 |
public function addHost($id, $host, $path){
|
48 |
-
$path
|
|
|
|
|
|
|
|
|
49 |
$host = strtolower($host);
|
50 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
}
|
52 |
public function addIP($id, $ipdata, $path){
|
53 |
-
$
|
|
|
|
|
|
|
|
|
|
|
54 |
if(strstr($ipdata, '.') === false && $ipdata >= 16777216 && $ipdata <= 4026531840){
|
55 |
$ipdata = long2ip($ipdata);
|
56 |
}
|
@@ -67,51 +94,51 @@ class wordfenceURLHoover {
|
|
67 |
}
|
68 |
}
|
69 |
if($isValid && $ipdata){
|
70 |
-
$
|
|
|
|
|
71 |
}
|
72 |
}
|
73 |
public static function urlenc($m){
|
74 |
return urlencode($m[1]);
|
75 |
}
|
76 |
-
private function intAddHost($id, $host, $path){
|
77 |
-
if(strpos($path, '/') !== 0){
|
78 |
-
$path = '/';
|
79 |
-
}
|
80 |
-
$this->hostsToAdd->push(array('owner' => $id, 'host' => $host, 'path' => $path, 'hostKey' => $this->makeHostKey($host)));
|
81 |
-
if($this->hostsToAdd->size() > 1000){ $this->writeHosts(); }
|
82 |
-
return true;
|
83 |
-
}
|
84 |
private function writeHosts(){
|
85 |
if($this->hostsToAdd->size() < 1){ return; }
|
86 |
-
$
|
87 |
-
|
88 |
-
$
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
|
|
|
|
|
|
105 |
}
|
106 |
-
return $hostKey;
|
107 |
}
|
108 |
public function getBaddies(){
|
109 |
$allHostKeys = array();
|
110 |
$stime = microtime(true);
|
111 |
$allHostKeys = array();
|
112 |
-
|
113 |
-
|
114 |
-
|
|
|
|
|
|
|
|
|
115 |
}
|
116 |
//Now call API and check if any hostkeys are bad.
|
117 |
//This is a shortcut, because if no hostkeys are bad it saves us having to check URLs
|
@@ -119,6 +146,11 @@ class wordfenceURLHoover {
|
|
119 |
//Hostkeys are 4 byte sha256 prefixes
|
120 |
//Returned value is 2 byte shorts which are array indexes for bad keys that were passed in the original list
|
121 |
$this->dbg("Checking " . sizeof($allHostKeys) . " hostkeys");
|
|
|
|
|
|
|
|
|
|
|
122 |
$resp = $this->api->binCall('check_host_keys', implode('', $allHostKeys));
|
123 |
$this->dbg("Done hostkey check");
|
124 |
|
@@ -135,7 +167,9 @@ class wordfenceURLHoover {
|
|
135 |
$idx = $idxArr[1];
|
136 |
if(isset($allHostKeys[$idx]) ){
|
137 |
array_push($badHostKeys, $allHostKeys[$idx]);
|
|
|
138 |
} else {
|
|
|
139 |
$this->errorMsg = "Bad allHostKeys index: $idx";
|
140 |
return false;
|
141 |
}
|
@@ -150,20 +184,39 @@ class wordfenceURLHoover {
|
|
150 |
//need to figure out which id's have bad hostkeys
|
151 |
//need to feed in all URL's from those id's where the hostkey matches a URL
|
152 |
foreach($badHostKeys as $badHostKey){
|
153 |
-
|
154 |
-
|
155 |
-
$
|
156 |
-
|
157 |
-
$urlsToCheck[$rec['owner']]
|
|
|
|
|
|
|
|
|
|
|
158 |
}
|
159 |
-
|
160 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
}
|
162 |
}
|
163 |
}
|
164 |
|
165 |
if(sizeof($urlsToCheck) > 0){
|
166 |
$this->dbg("Checking " . sizeof($urlsToCheck) . " URLs");
|
|
|
|
|
|
|
|
|
|
|
167 |
$badURLs = $this->api->call('check_bad_urls', array(), array( 'toCheck' => json_encode($urlsToCheck)) );
|
168 |
$this->dbg("Done URL check");
|
169 |
if(is_array($badURLs) && sizeof($badURLs) > 0){
|
8 |
private $table = '';
|
9 |
private $apiKey = false;
|
10 |
private $wordpressVersion = false;
|
11 |
+
private $useDB = true;
|
12 |
+
private $hostKeys = array();
|
13 |
+
private $hostList = array();
|
14 |
private $dRegex = 'aero|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|ss|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw|xn--lgbbat1ad8j|xn--fiqs8s|xn--fiqz9s|xn--wgbh1c|xn--j6w193g|xn--h2brj9c|xn--mgbbh1a71e|xn--fpcrj9c3d|xn--gecrj9c|xn--s9brj9c|xn--xkc2dl3a5ee0h|xn--45brj9c|xn--mgba3a4f16a|xn--mgbayh7gpa|xn--mgbc0a9azcg|xn--ygbi2ammx|xn--wgbl6a|xn--p1ai|xn--mgberp4a5d4ar|xn--90a3ac|xn--yfro4i67o|xn--clchc0ea0b2g2a9gcd|xn--3e0b707e|xn--fzc2c9e2c|xn--xkc2al3hye2a|xn--mgbtf8fl|xn--kprw13d|xn--kpry57d|xn--o3cw4h|xn--pgbs0dh|xn--mgbaam7a8h|xn--54b7fta0cc|xn--90ae|xn--node|xn--4dbrk0ce|xn--80ao21a|xn--mgb9awbf|xn--mgbai9azgqp6j|xn--j1amh|xn--mgb2ddes|xn--kgbechtv|xn--hgbk6aj7f53bba|xn--0zwm56d|xn--g6w251d|xn--80akhbyknj4f|xn--11b5bs3a9aj6g|xn--jxalpdlp|xn--9t4b11yi5a|xn--deba0ad|xn--zckzah|xn--hlcj6aya9esc7a';
|
15 |
private $api = false;
|
16 |
private $db = false;
|
23 |
$this->api = new wfAPI($this->apiKey, $this->wordpressVersion);
|
24 |
$this->db = new wfDB();
|
25 |
}
|
26 |
+
public function __construct($apiKey, $wordpressVersion, $db = false){
|
27 |
$this->hostsToAdd = new wfArray(array('owner', 'host', 'path', 'hostKey'));
|
28 |
$this->apiKey = $apiKey;
|
29 |
$this->wordpressVersion = $wordpressVersion;
|
30 |
$this->api = new wfAPI($apiKey, $wordpressVersion);
|
31 |
+
if($db){
|
32 |
+
$this->db = $db;
|
33 |
+
} else {
|
34 |
+
$this->db = new wfDB();
|
35 |
+
}
|
36 |
global $wpdb;
|
37 |
+
if(isset($wpdb)){
|
38 |
+
$this->table = $wpdb->base_prefix . 'wfHoover';
|
39 |
+
} else {
|
40 |
+
$this->table = 'wp_wfHoover';
|
41 |
+
}
|
42 |
$this->db->query("truncate table $this->table");
|
43 |
}
|
44 |
public function hoover($id, $data){
|
45 |
if(strpos($data, '.') === false){
|
46 |
return;
|
47 |
}
|
|
|
|
|
|
|
48 |
try {
|
49 |
@preg_replace("/(?<=^|[^a-zA-Z0-9\-])((?:[a-zA-Z0-9\-]+\.)+)(" . $this->dRegex . ")((?:$|[^a-zA-Z0-9\-\.\'\"])[^\r\n\s\t\"\'\$\{\}<>]*)/ie", "\$this->" . "addHost(\$id, '$1$2', '$3')", $data);
|
50 |
} catch(Exception $e){ error_log("Regex error 1: $e"); }
|
51 |
+
@preg_replace("/(?<=[^\d]|^)(\d{8,10}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})([^\d\'\"][^\r\n\s\t\"\'\$\{\}<>]*)/e", "\$this->" . "addIP(\$id, \"$1\",\"$2\")", $data);
|
52 |
$this->writeHosts();
|
53 |
}
|
54 |
private function dbg($msg){ if($this->debug){ error_log("DEBUG: $msg\n"); } }
|
55 |
public function addHost($id, $host, $path){
|
56 |
+
if(strpos($path, '/') !== 0){
|
57 |
+
$path = '/';
|
58 |
+
} else {
|
59 |
+
$path = preg_replace_callback('/([^A-Za-z0-9\-\.\_\~:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,;\=]+)/', 'wordfenceURLHoover::urlenc', $path);
|
60 |
+
}
|
61 |
$host = strtolower($host);
|
62 |
+
$hostParts = explode('.', $host);
|
63 |
+
if(sizeof($hostParts) == 2){
|
64 |
+
$hostKey = substr(hash('sha256', $hostParts[0] . '.' . $hostParts[1] . '/', true), 0, 4);
|
65 |
+
$this->hostsToAdd->push(array('owner' => $id, 'host' => $host, 'path' => $path, 'hostKey' => $hostKey));
|
66 |
+
} else if(sizeof($hostParts) > 2){
|
67 |
+
$hostKeyThreeParts = substr(hash('sha256',$hostParts[sizeof($hostParts) - 3] . '.' . $hostParts[sizeof($hostParts) - 2] . '.' . $hostParts[sizeof($hostParts) - 1] . '/', true), 0, 4);
|
68 |
+
$hostKeyTwoParts = substr(hash('sha256', $hostParts[sizeof($hostParts) - 2] . '.' . $hostParts[sizeof($hostParts) - 1] . '/', true), 0, 4);
|
69 |
+
$this->hostsToAdd->push(array('owner' => $id, 'host' => $host, 'path' => $path, 'hostKey' => $hostKeyThreeParts));
|
70 |
+
$this->hostsToAdd->push(array('owner' => $id, 'host' => $host, 'path' => $path, 'hostKey' => $hostKeyTwoParts));
|
71 |
+
}
|
72 |
+
if($this->hostsToAdd->size() > 1000){ $this->writeHosts(); }
|
73 |
}
|
74 |
public function addIP($id, $ipdata, $path){
|
75 |
+
$this->dbg("Add IP called with $ipdata $path");
|
76 |
+
if(strpos($path, '/') !== 0){
|
77 |
+
$path = '/';
|
78 |
+
} else {
|
79 |
+
$path = preg_replace_callback('/([^A-Za-z0-9\-\.\_\~:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,;\=]+)/', 'wordfenceURLHoover::urlenc', $path);
|
80 |
+
}
|
81 |
if(strstr($ipdata, '.') === false && $ipdata >= 16777216 && $ipdata <= 4026531840){
|
82 |
$ipdata = long2ip($ipdata);
|
83 |
}
|
94 |
}
|
95 |
}
|
96 |
if($isValid && $ipdata){
|
97 |
+
$hostKey = substr(hash('sha256', $ipdata . '/', true), 0, 4);
|
98 |
+
$this->hostsToAdd->push(array('owner' => $id, 'host' => $ipdata, 'path' => $path, 'hostKey' => $hostKey));
|
99 |
+
if($this->hostsToAdd->size() > 1000){ $this->writeHosts(); }
|
100 |
}
|
101 |
}
|
102 |
public static function urlenc($m){
|
103 |
return urlencode($m[1]);
|
104 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
private function writeHosts(){
|
106 |
if($this->hostsToAdd->size() < 1){ return; }
|
107 |
+
if($this->useDB){
|
108 |
+
$sql = "insert into " . $this->table . " (owner, host, path, hostKey) values ";
|
109 |
+
while($elem = $this->hostsToAdd->shift()){
|
110 |
+
$sql .= sprintf("('%s', '%s', '%s', '%s'),",
|
111 |
+
mysql_real_escape_string($elem['owner']),
|
112 |
+
mysql_real_escape_string($elem['host']),
|
113 |
+
mysql_real_escape_string($elem['path']),
|
114 |
+
mysql_real_escape_string($elem['hostKey'])
|
115 |
+
);
|
116 |
+
}
|
117 |
+
$sql = rtrim($sql, ',');
|
118 |
+
$this->db->query($sql);
|
119 |
+
} else {
|
120 |
+
while($elem = $this->hostsToAdd->shift()){
|
121 |
+
$this->hostKeys[] = $elem['hostKey'];
|
122 |
+
$this->hostList[] = array(
|
123 |
+
'owner' => $elem['owner'],
|
124 |
+
'host' => $elem['host'],
|
125 |
+
'path' => $elem['path'],
|
126 |
+
'hostKey' => $elem['hostKey']
|
127 |
+
);
|
128 |
+
}
|
129 |
}
|
|
|
130 |
}
|
131 |
public function getBaddies(){
|
132 |
$allHostKeys = array();
|
133 |
$stime = microtime(true);
|
134 |
$allHostKeys = array();
|
135 |
+
if($this->useDB){
|
136 |
+
$q1 = $this->db->query("select distinct hostKey as hostKey from $this->table");
|
137 |
+
while($hRec = mysql_fetch_assoc($q1)){
|
138 |
+
array_push($allHostKeys, $hRec['hostKey']);
|
139 |
+
}
|
140 |
+
} else {
|
141 |
+
$allHostKeys = $this->hostKeys;
|
142 |
}
|
143 |
//Now call API and check if any hostkeys are bad.
|
144 |
//This is a shortcut, because if no hostkeys are bad it saves us having to check URLs
|
146 |
//Hostkeys are 4 byte sha256 prefixes
|
147 |
//Returned value is 2 byte shorts which are array indexes for bad keys that were passed in the original list
|
148 |
$this->dbg("Checking " . sizeof($allHostKeys) . " hostkeys");
|
149 |
+
if($this->debug){
|
150 |
+
foreach($allHostKeys as $key){
|
151 |
+
$this->dbg("Checking hostkey: " . bin2hex($key));
|
152 |
+
}
|
153 |
+
}
|
154 |
$resp = $this->api->binCall('check_host_keys', implode('', $allHostKeys));
|
155 |
$this->dbg("Done hostkey check");
|
156 |
|
167 |
$idx = $idxArr[1];
|
168 |
if(isset($allHostKeys[$idx]) ){
|
169 |
array_push($badHostKeys, $allHostKeys[$idx]);
|
170 |
+
$this->dbg("Got bad hostkey for record: " . var_export($allHostKeys[$idx], true));
|
171 |
} else {
|
172 |
+
$this->dbg("Bad allHostKeys index: $idx");
|
173 |
$this->errorMsg = "Bad allHostKeys index: $idx";
|
174 |
return false;
|
175 |
}
|
184 |
//need to figure out which id's have bad hostkeys
|
185 |
//need to feed in all URL's from those id's where the hostkey matches a URL
|
186 |
foreach($badHostKeys as $badHostKey){
|
187 |
+
if($this->useDB){
|
188 |
+
$q1 = $this->db->query("select owner, host, path from $this->table where hostKey='%s'", $badHostKey);
|
189 |
+
while($rec = mysql_fetch_assoc($q1)){
|
190 |
+
$url = 'http://' . $rec['host'] . $rec['path'];
|
191 |
+
if(! isset($urlsToCheck[$rec['owner']])){
|
192 |
+
$urlsToCheck[$rec['owner']] = array();
|
193 |
+
}
|
194 |
+
if(! in_array($url, $urlsToCheck[$rec['owner']])){
|
195 |
+
$urlsToCheck[$rec['owner']][] = $url;
|
196 |
+
}
|
197 |
}
|
198 |
+
} else {
|
199 |
+
foreach($this->hostList as $rec){
|
200 |
+
if($rec['hostKey'] == $badHostKey){
|
201 |
+
$url = 'http://' . $rec['host'] . $rec['path'];
|
202 |
+
if(! isset($urlsToCheck[$rec['owner']])){
|
203 |
+
$urlsToCheck[$rec['owner']] = array();
|
204 |
+
}
|
205 |
+
if(! in_array($url, $urlsToCheck[$rec['owner']])){
|
206 |
+
$urlsToCheck[$rec['owner']][] = $url;
|
207 |
+
}
|
208 |
+
}
|
209 |
}
|
210 |
}
|
211 |
}
|
212 |
|
213 |
if(sizeof($urlsToCheck) > 0){
|
214 |
$this->dbg("Checking " . sizeof($urlsToCheck) . " URLs");
|
215 |
+
if($this->debug){
|
216 |
+
foreach($urlsToCheck as $url){
|
217 |
+
$this->dbg("Checking URL: " . var_export($url, true));
|
218 |
+
}
|
219 |
+
}
|
220 |
$badURLs = $this->api->call('check_bad_urls', array(), array( 'toCheck' => json_encode($urlsToCheck)) );
|
221 |
$this->dbg("Done URL check");
|
222 |
if(is_array($badURLs) && sizeof($badURLs) > 0){
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
|
|
3 |
Tags: wordpress, security, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure
|
4 |
Requires at least: 3.3.1
|
5 |
Tested up to: 3.4.1
|
6 |
-
Stable tag: 3.0.
|
7 |
|
8 |
Wordfence Security is a free enterprise class security plugin that includes a firewall, virus scanning, real-time traffic with geolocation and more.
|
9 |
|
@@ -152,6 +152,15 @@ or a theme, because often these have been updated to fix a security hole.
|
|
152 |
5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
|
153 |
|
154 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
= 3.0.5 =
|
156 |
* Fixed "The key used to start a scan has expired." error and added data to help diagnose future issues like this.
|
157 |
* Removed HTTPHeaders from wfHits table which was using a lot of disk space and not used much.
|
@@ -431,6 +440,9 @@ or a theme, because often these have been updated to fix a security hole.
|
|
431 |
* Initial public release of Wordfence.
|
432 |
|
433 |
== Upgrade Notice ==
|
|
|
|
|
|
|
434 |
= 3.0.3 =
|
435 |
Upgrade immediately. This release fixes an issue that caused Wordfence to show all your core files
|
436 |
missing under certain conditions. It was usually caused by high load on our scanning server and the
|
3 |
Tags: wordpress, security, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure
|
4 |
Requires at least: 3.3.1
|
5 |
Tested up to: 3.4.1
|
6 |
+
Stable tag: 3.0.6
|
7 |
|
8 |
Wordfence Security is a free enterprise class security plugin that includes a firewall, virus scanning, real-time traffic with geolocation and more.
|
9 |
|
152 |
5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
|
153 |
|
154 |
== Changelog ==
|
155 |
+
= 3.0.6 =
|
156 |
+
* Improved malware and phishing URL detection.
|
157 |
+
* Upgraded to Wordfence API version 1.9
|
158 |
+
* Fixed issue that caused large files to slow or crash a scan.
|
159 |
+
* Added workaround for PHP's broken filesize() function on 32 bit systems.
|
160 |
+
* Added an improved test mode for URL scanner for better unit testing on our end.
|
161 |
+
* Suppressed warnings issued when a reverse DNS lookup fails.
|
162 |
+
* Added improved debug output to becomeAdmin() function in scans to help diagnose scans not starting.
|
163 |
+
|
164 |
= 3.0.5 =
|
165 |
* Fixed "The key used to start a scan has expired." error and added data to help diagnose future issues like this.
|
166 |
* Removed HTTPHeaders from wfHits table which was using a lot of disk space and not used much.
|
440 |
* Initial public release of Wordfence.
|
441 |
|
442 |
== Upgrade Notice ==
|
443 |
+
= 3.0.6 =
|
444 |
+
Upgrade immediately. Improves malware URL detection by 20% or more.
|
445 |
+
|
446 |
= 3.0.3 =
|
447 |
Upgrade immediately. This release fixes an issue that caused Wordfence to show all your core files
|
448 |
missing under certain conditions. It was usually caused by high load on our scanning server and the
|
wfscan.php
CHANGED
@@ -73,6 +73,7 @@ class wfScan {
|
|
73 |
ini_set('max_execution_time', 1800); //30 mins
|
74 |
wordfence::status(4, 'info', "Becoming admin for scan");
|
75 |
self::becomeAdmin();
|
|
|
76 |
|
77 |
$isFork = ($_GET['isFork'] == '1' ? true : false);
|
78 |
|
@@ -153,10 +154,14 @@ class wfScan {
|
|
153 |
exit();
|
154 |
}
|
155 |
public static function becomeAdmin(){
|
|
|
156 |
global $wpdb;
|
|
|
157 |
$ws = $wpdb->get_results("SELECT ID, user_login FROM $wpdb->users");
|
|
|
158 |
$users = array();
|
159 |
foreach($ws as $user){
|
|
|
160 |
$userDat = get_userdata($user->ID);
|
161 |
array_push($users, array(
|
162 |
'id' => $user->ID,
|
@@ -164,8 +169,11 @@ class wfScan {
|
|
164 |
'level' => $userDat->user_level
|
165 |
));
|
166 |
}
|
|
|
167 |
usort($users, 'wfScan::usort');
|
|
|
168 |
wp_set_current_user($users[0]['id'], $users[0]['user_login']);
|
|
|
169 |
}
|
170 |
public static function usort($b, $a){
|
171 |
if($a['level'] == $b['level']){ return 0; }
|
73 |
ini_set('max_execution_time', 1800); //30 mins
|
74 |
wordfence::status(4, 'info', "Becoming admin for scan");
|
75 |
self::becomeAdmin();
|
76 |
+
wordfence::status(4, 'info', "Done become admin");
|
77 |
|
78 |
$isFork = ($_GET['isFork'] == '1' ? true : false);
|
79 |
|
154 |
exit();
|
155 |
}
|
156 |
public static function becomeAdmin(){
|
157 |
+
wordfence::status('4', 'info', "Starting become admin");
|
158 |
global $wpdb;
|
159 |
+
wordfence::status('4', 'info', "About to query");
|
160 |
$ws = $wpdb->get_results("SELECT ID, user_login FROM $wpdb->users");
|
161 |
+
wordfence::status('4', 'info', "Done query");
|
162 |
$users = array();
|
163 |
foreach($ws as $user){
|
164 |
+
wordfence::status('4', 'info', "Processing user");
|
165 |
$userDat = get_userdata($user->ID);
|
166 |
array_push($users, array(
|
167 |
'id' => $user->ID,
|
169 |
'level' => $userDat->user_level
|
170 |
));
|
171 |
}
|
172 |
+
wordfence::status('4', 'info', "Done users and about to sort");
|
173 |
usort($users, 'wfScan::usort');
|
174 |
+
wordfence::status('4', 'info', "Done sort and setting user");
|
175 |
wp_set_current_user($users[0]['id'], $users[0]['user_login']);
|
176 |
+
wordfence::status('4', 'info', "Done setting user");
|
177 |
}
|
178 |
public static function usort($b, $a){
|
179 |
if($a['level'] == $b['level']){ return 0; }
|
wordfence.php
CHANGED
@@ -4,10 +4,10 @@ Plugin Name: Wordfence Security
|
|
4 |
Plugin URI: http://wordfence.com/
|
5 |
Description: Wordfence Security - Anti-virus and Firewall security plugin for WordPress
|
6 |
Author: Mark Maunder
|
7 |
-
Version: 3.0.
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
-
define('WORDFENCE_VERSION', '3.0.
|
11 |
if(! defined('WORDFENCE_VERSIONONLY_MODE')){
|
12 |
if((int) @ini_get('memory_limit') < 64){
|
13 |
@ini_set('memory_limit', '64M'); //Some hosts have ini set at as little as 32 megs. 64 is the min sane amount of memory.
|
4 |
Plugin URI: http://wordfence.com/
|
5 |
Description: Wordfence Security - Anti-virus and Firewall security plugin for WordPress
|
6 |
Author: Mark Maunder
|
7 |
+
Version: 3.0.6
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
+
define('WORDFENCE_VERSION', '3.0.6');
|
11 |
if(! defined('WORDFENCE_VERSIONONLY_MODE')){
|
12 |
if((int) @ini_get('memory_limit') < 64){
|
13 |
@ini_set('memory_limit', '64M'); //Some hosts have ini set at as little as 32 megs. 64 is the min sane amount of memory.
|