Version Description
- Fix: WordPress language files no longer flagged as changed.
- Improvement: Accept wildcards in "Immediately block IP's that access these URLs."
- Fix: Fixed bug when multiple authors have published posts, /?author=N scans show an author archive page.
- Fix: Fixed issue with IPv6 mapped IPv4 addresses not being treated as IPv4.
- Improvement: Added WordPress version and various constants to Diagnostics report.
- Fix: Fixed bug with Windows users unable to save Firewall config.
- Improvement: Include option for IIS on Windows in Firewall config process, and recommend manual php.ini change only.
- Fix: Made the 'administrator email address' admin notice dismissable.
Download this release
Release Info
Developer | wfmatt |
Plugin | Wordfence Security – Firewall & Malware Scan |
Version | 6.1.5 |
Comparing to | |
See all releases |
Code changes from version 6.1.4 to 6.1.5
- css/main.css +1 -1
- js/tourTip.js +8 -0
- lib/menu_diagnostic.php +90 -0
- lib/menu_options.php +4 -5
- lib/wfCache.php +1 -1
- lib/wfUtils.php +25 -3
- lib/wordfenceClass.php +25 -7
- lib/wordfenceHash.php +106 -81
- lib/wordfenceScanner.php +53 -15
- readme.txt +27 -17
- vendor/wordfence/wf-waf/src/init.php +3 -1
- vendor/wordfence/wf-waf/src/lib/parser/lexer.php +12 -0
- vendor/wordfence/wf-waf/src/lib/parser/parser.php +70 -11
- vendor/wordfence/wf-waf/src/lib/parser/sqli.php +0 -12
- vendor/wordfence/wf-waf/src/lib/rules.php +50 -5
- vendor/wordfence/wf-waf/src/lib/storage/file.php +16 -2
- vendor/wordfence/wf-waf/src/lib/waf.php +12 -10
- waf/bootstrap.php +9 -1
- wordfence.php +2 -2
css/main.css
CHANGED
@@ -518,7 +518,7 @@ h3.wfConfigHeading {
|
|
518 |
.wfOnOffSwitch-checkbox:checked + .wfOnOffSwitch-label .wfOnOffSwitch-switch {
|
519 |
right: 0 !important ;
|
520 |
}
|
521 |
-
#wordfenceConfigWarning {
|
522 |
clear: left;
|
523 |
margin-top: 5px;
|
524 |
}
|
518 |
.wfOnOffSwitch-checkbox:checked + .wfOnOffSwitch-label .wfOnOffSwitch-switch {
|
519 |
right: 0 !important ;
|
520 |
}
|
521 |
+
#wordfenceConfigWarning, #wordfenceAdminEmailWarning {
|
522 |
clear: left;
|
523 |
margin-top: 5px;
|
524 |
}
|
js/tourTip.js
CHANGED
@@ -25,6 +25,14 @@ window['wordfenceExt'] = {
|
|
25 |
function(){ jQuery('#wordfenceAutoUpdateChoice').fadeOut(); }
|
26 |
);
|
27 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
removeFromCache: function(postID){
|
29 |
this.ajax('wordfence_removeFromCache', {
|
30 |
id: postID
|
25 |
function(){ jQuery('#wordfenceAutoUpdateChoice').fadeOut(); }
|
26 |
);
|
27 |
},
|
28 |
+
adminEmailChoice: function(choice) {
|
29 |
+
this.ajax('wordfence_adminEmailChoice', {
|
30 |
+
choice: choice
|
31 |
+
},
|
32 |
+
function(res){ jQuery('#wordfenceAdminEmailWarning').fadeOut(); },
|
33 |
+
function(){ jQuery('#wordfenceAdminEmailWarning').fadeOut(); }
|
34 |
+
);
|
35 |
+
},
|
36 |
removeFromCache: function(postID){
|
37 |
this.ajax('wordfence_removeFromCache', {
|
38 |
id: postID
|
lib/menu_diagnostic.php
CHANGED
@@ -87,6 +87,96 @@ $w = new wfConfig();
|
|
87 |
</tr>
|
88 |
</tbody>
|
89 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
<tbody class="thead">
|
91 |
<tr>
|
92 |
<th colspan="<?php echo $cols ?>">WordPress Plugins</th>
|
87 |
</tr>
|
88 |
</tbody>
|
89 |
|
90 |
+
<tbody class="thead">
|
91 |
+
<tr>
|
92 |
+
<th colspan="<?php echo $cols ?>">WordPress</th>
|
93 |
+
</tr>
|
94 |
+
</tbody>
|
95 |
+
<tbody>
|
96 |
+
<?php
|
97 |
+
require(ABSPATH . 'wp-includes/version.php');
|
98 |
+
$postRevisions = (defined('WP_POST_REVISIONS') ? WP_POST_REVISIONS : true);
|
99 |
+
$wordPressValues = array(
|
100 |
+
'WordPress Version' => array('description' => '', 'value' => $wp_version),
|
101 |
+
'WP_DEBUG' => array('description' => 'WordPress debug mode', 'value' => (defined('WP_DEBUG') && WP_DEBUG ? 'On' : 'Off')),
|
102 |
+
'WP_DEBUG_LOG' => array('description' => 'WordPress error logging override', 'value' => defined('WP_DEBUG_LOG') ? (WP_DEBUG_LOG ? 'Enabled' : 'Disabled') : '(not set)'),
|
103 |
+
'WP_DEBUG_DISPLAY' => array('description' => 'WordPress error display override', 'value' => defined('WP_DEBUG_DISPLAY') ? (WP_DEBUG_LOG ? 'Enabled' : 'Disabled') : '(not set)'),
|
104 |
+
'SCRIPT_DEBUG' => array('description' => 'WordPress script debug mode', 'value' => (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? 'On' : 'Off')),
|
105 |
+
'SAVEQUERIES' => array('description' => 'WordPress query debug mode', 'value' => (defined('SAVEQUERIES') && SAVEQUERIES ? 'On' : 'Off')),
|
106 |
+
'DB_CHARSET' => 'Database character set',
|
107 |
+
'DB_COLLATE' => 'Database collation',
|
108 |
+
'WP_SITEURL' => 'Explicitly set site URL',
|
109 |
+
'WP_HOME' => 'Explicitly set blog URL',
|
110 |
+
'WP_CONTENT_DIR' => array('description' => '"wp-content" folder is in default location', 'value' => (realpath(WP_CONTENT_DIR) === realpath(ABSPATH . 'wp-content') ? 'Yes' : 'No')),
|
111 |
+
'WP_CONTENT_URL' => 'URL to the "wp-content" folder',
|
112 |
+
'WP_PLUGIN_DIR' => array('description' => '"plugins" folder is in default location', 'value' => (realpath(WP_PLUGIN_DIR) === realpath(ABSPATH . 'wp-content/plugins') ? 'Yes' : 'No')),
|
113 |
+
'WP_LANG_DIR' => array('description' => '"languages" folder is in default location', 'value' => (realpath(WP_LANG_DIR) === realpath(ABSPATH . 'wp-content/languages') ? 'Yes' : 'No')),
|
114 |
+
'WPLANG' => 'Language choice',
|
115 |
+
'UPLOADS' => 'Custom upload folder location',
|
116 |
+
'TEMPLATEPATH' => array('description' => 'Theme template folder override', 'value' => (defined('TEMPLATEPATH') && realpath(get_template_directory()) !== realpath(TEMPLATEPATH) ? 'Overridden' : '(not set)')),
|
117 |
+
'STYLESHEETPATH' => array('description' => 'Theme stylesheet folder override', 'value' => (defined('STYLESHEETPATH') && realpath(get_stylesheet_directory()) !== realpath(STYLESHEETPATH) ? 'Overridden' : '(not set)')),
|
118 |
+
'AUTOSAVE_INTERVAL' => 'Post editing automatic saving interval',
|
119 |
+
'WP_POST_REVISIONS' => array('description' => 'Post revisions saved by WordPress', 'value' => is_numeric($postRevisions) ? $postRevisions : ($postRevisions ? 'Unlimited' : 'None')),
|
120 |
+
'COOKIE_DOMAIN' => 'WordPress cookie domain',
|
121 |
+
'COOKIEPATH' => 'WordPress cookie path',
|
122 |
+
'SITECOOKIEPATH' => 'WordPress site cookie path',
|
123 |
+
'ADMIN_COOKIE_PATH' => 'WordPress admin cookie path',
|
124 |
+
'PLUGINS_COOKIE_PATH' => 'WordPress plugins cookie path',
|
125 |
+
'WP_ALLOW_MULTISITE' => array('description' => 'Multisite/network ability enabled', 'value' => (defined('WP_ALLOW_MULTISITE') && WP_ALLOW_MULTISITE ? 'Yes' : 'No')),
|
126 |
+
'NOBLOGREDIRECT' => 'URL redirected to if the visitor tries to access a nonexistent blog',
|
127 |
+
'CONCATENATE_SCRIPTS' => array('description' => 'Concatenate JavaScript files', 'value' => (defined('CONCATENATE_SCRIPTS') && CONCATENATE_SCRIPTS ? 'Yes' : 'No')),
|
128 |
+
'WP_MEMORY_LIMIT' => 'WordPress memory limit',
|
129 |
+
'WP_MAX_MEMORY_LIMIT' => 'Administrative memory limit',
|
130 |
+
'WP_CACHE' => array('description' => 'Built-in caching', 'value' => (defined('WP_CACHE') && WP_CACHE ? 'Enabled' : 'Disabled')),
|
131 |
+
'CUSTOM_USER_TABLE' => array('description' => 'Custom "users" table', 'value' => (defined('CUSTOM_USER_TABLE') ? 'Set' : '(not set)')),
|
132 |
+
'CUSTOM_USER_META_TABLE' => array('description' => 'Custom "usermeta" table', 'value' => (defined('CUSTOM_USER_META_TABLE') ? 'Set' : '(not set)')),
|
133 |
+
'FS_CHMOD_DIR' => array('description' => 'Overridden permissions for a new folder', 'value' => defined('FS_CHMOD_DIR') ? decoct(FS_CHMOD_DIR) : '(not set)'),
|
134 |
+
'FS_CHMOD_FILE' => array('description' => 'Overridden permissions for a new file', 'value' => defined('FS_CHMOD_FILE') ? decoct(FS_CHMOD_FILE) : '(not set)'),
|
135 |
+
'ALTERNATE_WP_CRON' => array('description' => 'Alternate WP cron', 'value' => (defined('ALTERNATE_WP_CRON') && ALTERNATE_WP_CRON ? 'Enabled' : 'Disabled')),
|
136 |
+
'DISABLE_WP_CRON' => array('description' => 'WP cron status', 'value' => (defined('DISABLE_WP_CRON') && DISABLE_WP_CRON ? 'Disabled' : 'Enabled')),
|
137 |
+
'WP_CRON_LOCK_TIMEOUT' => 'Cron running frequency lock',
|
138 |
+
'EMPTY_TRASH_DAYS' => array('description' => 'Interval the trash is automatically emptied at in days', 'value' => (EMPTY_TRASH_DAYS > 0 ? EMPTY_TRASH_DAYS : 'Never')),
|
139 |
+
'WP_ALLOW_REPAIR' => array('description' => 'Automatic database repair', 'value' => (defined('WP_ALLOW_REPAIR') && WP_ALLOW_REPAIR ? 'Enabled' : 'Disabled')),
|
140 |
+
'DO_NOT_UPGRADE_GLOBAL_TABLES' => array('description' => 'Do not upgrade global tables', 'value' => (defined('DO_NOT_UPGRADE_GLOBAL_TABLES') && DO_NOT_UPGRADE_GLOBAL_TABLES ? 'Yes' : 'No')),
|
141 |
+
'DISALLOW_FILE_EDIT' => array('description' => 'Disallow plugin/theme editing', 'value' => (defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT ? 'Yes' : 'No')),
|
142 |
+
'DISALLOW_FILE_MOD' => array('description' => 'Disallow plugin/theme update and installation', 'value' => (defined('DISALLOW_FILE_MOD') && DISALLOW_FILE_MOD ? 'Yes' : 'No')),
|
143 |
+
'IMAGE_EDIT_OVERWRITE' => array('description' => 'Overwrite image edits when restoring the original', 'value' => (defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ? 'Yes' : 'No')),
|
144 |
+
'FORCE_SSL_ADMIN' => array('description' => 'Force SSL for administrative logins', 'value' => (defined('FORCE_SSL_ADMIN') && FORCE_SSL_ADMIN ? 'Yes' : 'No')),
|
145 |
+
'WP_HTTP_BLOCK_EXTERNAL' => array('description' => 'Block external URL requests', 'value' => (defined('WP_HTTP_BLOCK_EXTERNAL') && WP_HTTP_BLOCK_EXTERNAL ? 'Yes' : 'No')),
|
146 |
+
'WP_ACCESSIBLE_HOSTS' => 'Whitelisted hosts',
|
147 |
+
'WP_AUTO_UPDATE_CORE' => array('description' => 'Automatic WP Core updates', 'value' => defined('WP_AUTO_UPDATE_CORE') ? (is_bool(WP_AUTO_UPDATE_CORE) ? (WP_AUTO_UPDATE_CORE ? 'Everything' : 'None') : WP_AUTO_UPDATE_CORE) : 'Default'),
|
148 |
+
);
|
149 |
+
|
150 |
+
foreach ($wordPressValues as $settingName => $settingData):
|
151 |
+
$escapedName = esc_html($settingName);
|
152 |
+
$escapedDescription = '';
|
153 |
+
$escapedValue = '(not set)';
|
154 |
+
if (is_array($settingData)) {
|
155 |
+
$escapedDescription = esc_html($settingData['description']);
|
156 |
+
if (isset($settingData['value'])) {
|
157 |
+
$escapedValue = esc_html($settingData['value']);
|
158 |
+
}
|
159 |
+
}
|
160 |
+
else {
|
161 |
+
$escapedDescription = esc_html($settingData);
|
162 |
+
if (defined($settingName)) {
|
163 |
+
$escapedValue = esc_html(constant($settingName));
|
164 |
+
}
|
165 |
+
}
|
166 |
+
?>
|
167 |
+
<tr>
|
168 |
+
<td><strong><?php echo $escapedName ?></strong></td>
|
169 |
+
<td><?php echo $escapedDescription ?></td>
|
170 |
+
<td><?php echo $escapedValue ?></td>
|
171 |
+
</tr>
|
172 |
+
<?php endforeach ?>
|
173 |
+
</tbody>
|
174 |
+
<tbody class="empty-row">
|
175 |
+
<tr>
|
176 |
+
<td colspan="<?php echo $cols ?>"></td>
|
177 |
+
</tr>
|
178 |
+
</tbody>
|
179 |
+
|
180 |
<tbody class="thead">
|
181 |
<tr>
|
182 |
<th colspan="<?php echo $cols ?>">WordPress Plugins</th>
|
lib/menu_options.php
CHANGED
@@ -885,11 +885,10 @@ $w = new wfConfig();
|
|
885 |
value="<?php $w->f( 'bannedURLs' ); ?>" size="40"/></td>
|
886 |
</tr>
|
887 |
<tr>
|
888 |
-
<th colspan="2" style="color: #999;">Separate multiple URL's with commas.
|
889 |
-
repeatedly probing your site for a known vulnerability
|
890 |
-
them
|
891 |
-
|
892 |
-
/bannedPage.html, /dont-access/this/URL/
|
893 |
<br/><br/></th>
|
894 |
</tr>
|
895 |
|
885 |
value="<?php $w->f( 'bannedURLs' ); ?>" size="40"/></td>
|
886 |
</tr>
|
887 |
<tr>
|
888 |
+
<th colspan="2" style="color: #999;">Separate multiple URL's with commas. Asterisks are wildcards,
|
889 |
+
but use with care. If you see an attacker repeatedly probing your site for a known vulnerability
|
890 |
+
you can use this to immediately block them. All URL's must start with a '/' without quotes and
|
891 |
+
must be relative. e.g. /badURLone/, /bannedPage.html, /dont-access/this/URL/, /starts/with-*
|
|
|
892 |
<br/><br/></th>
|
893 |
</tr>
|
894 |
|
lib/wfCache.php
CHANGED
@@ -513,7 +513,7 @@ class wfCache {
|
|
513 |
$excludedURLs = "";
|
514 |
if(wfConfig::get('bannedURLs', false)){
|
515 |
foreach(explode(',', wfConfig::get('bannedURLs', false)) as $URL){
|
516 |
-
$excludedURLs .= "RewriteCond
|
517 |
}
|
518 |
}
|
519 |
|
513 |
$excludedURLs = "";
|
514 |
if(wfConfig::get('bannedURLs', false)){
|
515 |
foreach(explode(',', wfConfig::get('bannedURLs', false)) as $URL){
|
516 |
+
$excludedURLs .= "RewriteCond %{REQUEST_URI} !" . wfUtils::patternToRegex($URL, '', '') . "\n\t";
|
517 |
}
|
518 |
}
|
519 |
|
lib/wfUtils.php
CHANGED
@@ -8,7 +8,8 @@ class wfUtils {
|
|
8 |
private static $lastDisplayErrors = false;
|
9 |
public static function patternToRegex($pattern, $mod = 'i', $sep = '/') {
|
10 |
$pattern = preg_quote(trim($pattern), $sep);
|
11 |
-
|
|
|
12 |
}
|
13 |
public static function makeTimeAgo($secs, $noSeconds = false) {
|
14 |
if($secs < 1){
|
@@ -274,8 +275,8 @@ class wfUtils {
|
|
274 |
}
|
275 |
|
276 |
// IPv4 mapped IPv6
|
277 |
-
if (preg_match('/^((
|
278 |
-
$octets = explode('.', $matches[
|
279 |
return "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" . chr($octets[0]) . chr($octets[1]) . chr($octets[2]) . chr($octets[3]);
|
280 |
}
|
281 |
|
@@ -512,6 +513,10 @@ class wfUtils {
|
|
512 |
$j = preg_replace('/:\d+$/', '', $j); //Strip off port
|
513 |
}
|
514 |
if (self::isValidIP($j)) {
|
|
|
|
|
|
|
|
|
515 |
if (self::isPrivateAddress($j)) {
|
516 |
$privates[] = array($j, $var);
|
517 |
} else {
|
@@ -530,6 +535,10 @@ class wfUtils {
|
|
530 |
$j = preg_replace('/:\d+$/', '', $j); //Strip off port
|
531 |
}
|
532 |
if(self::isValidIP($j)){
|
|
|
|
|
|
|
|
|
533 |
if(self::isPrivateAddress($j)){
|
534 |
$privates[] = array($j, $var);
|
535 |
} else {
|
@@ -547,6 +556,10 @@ class wfUtils {
|
|
547 |
$item = preg_replace('/:\d+$/', '', $item); //Strip off port
|
548 |
}
|
549 |
if(self::isValidIP($item)){
|
|
|
|
|
|
|
|
|
550 |
if(self::isPrivateAddress($item)){
|
551 |
$privates[] = array($item, $var);
|
552 |
} else {
|
@@ -560,6 +573,15 @@ class wfUtils {
|
|
560 |
return false;
|
561 |
}
|
562 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
563 |
public static function extractHostname($str){
|
564 |
if(preg_match('/https?:\/\/([a-zA-Z0-9\.\-]+)(?:\/|$)/i', $str, $matches)){
|
565 |
return strtolower($matches[1]);
|
8 |
private static $lastDisplayErrors = false;
|
9 |
public static function patternToRegex($pattern, $mod = 'i', $sep = '/') {
|
10 |
$pattern = preg_quote(trim($pattern), $sep);
|
11 |
+
$pattern = str_replace(' ', '\s', $pattern);
|
12 |
+
return $sep . '^' . str_replace('\*', '.*', $pattern) . '$' . $sep . $mod;
|
13 |
}
|
14 |
public static function makeTimeAgo($secs, $noSeconds = false) {
|
15 |
if($secs < 1){
|
275 |
}
|
276 |
|
277 |
// IPv4 mapped IPv6
|
278 |
+
if (preg_match('/^(?:\:(?:\:0{1,4}){0,4}\:|(?:0{1,4}\:){5})ffff\:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i', $ip, $matches)) {
|
279 |
+
$octets = explode('.', $matches[1]);
|
280 |
return "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" . chr($octets[0]) . chr($octets[1]) . chr($octets[2]) . chr($octets[3]);
|
281 |
}
|
282 |
|
513 |
$j = preg_replace('/:\d+$/', '', $j); //Strip off port
|
514 |
}
|
515 |
if (self::isValidIP($j)) {
|
516 |
+
if (self::isIPv6MappedIPv4($j)) {
|
517 |
+
$j = self::inet_ntop(self::inet_pton($j));
|
518 |
+
}
|
519 |
+
|
520 |
if (self::isPrivateAddress($j)) {
|
521 |
$privates[] = array($j, $var);
|
522 |
} else {
|
535 |
$j = preg_replace('/:\d+$/', '', $j); //Strip off port
|
536 |
}
|
537 |
if(self::isValidIP($j)){
|
538 |
+
if (self::isIPv6MappedIPv4($j)) {
|
539 |
+
$j = self::inet_ntop(self::inet_pton($j));
|
540 |
+
}
|
541 |
+
|
542 |
if(self::isPrivateAddress($j)){
|
543 |
$privates[] = array($j, $var);
|
544 |
} else {
|
556 |
$item = preg_replace('/:\d+$/', '', $item); //Strip off port
|
557 |
}
|
558 |
if(self::isValidIP($item)){
|
559 |
+
if (self::isIPv6MappedIPv4($item)) {
|
560 |
+
$item = self::inet_ntop(self::inet_pton($item));
|
561 |
+
}
|
562 |
+
|
563 |
if(self::isPrivateAddress($item)){
|
564 |
$privates[] = array($item, $var);
|
565 |
} else {
|
573 |
return false;
|
574 |
}
|
575 |
}
|
576 |
+
|
577 |
+
/**
|
578 |
+
* @param string $ip
|
579 |
+
* @return bool
|
580 |
+
*/
|
581 |
+
public static function isIPv6MappedIPv4($ip) {
|
582 |
+
return preg_match('/^(?:\:(?:\:0{1,4}){0,4}\:|(?:0{1,4}\:){5})ffff\:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/i', $ip) > 0;
|
583 |
+
}
|
584 |
+
|
585 |
public static function extractHostname($str){
|
586 |
if(preg_match('/https?:\/\/([a-zA-Z0-9\.\-]+)(?:\/|$)/i', $str, $matches)){
|
587 |
return strtolower($matches[1]);
|
lib/wordfenceClass.php
CHANGED
@@ -1100,7 +1100,7 @@ SQL
|
|
1100 |
if(wfConfig::get('bannedURLs', false)){
|
1101 |
$URLs = explode(',', wfConfig::get('bannedURLs'));
|
1102 |
foreach($URLs as $URL){
|
1103 |
-
if($_SERVER['REQUEST_URI']
|
1104 |
$wfLog->blockIP($IP, "Accessed a banned URL.");
|
1105 |
$wfLog->do503(3600, "Accessed a banned URL.");
|
1106 |
//exits
|
@@ -1773,6 +1773,15 @@ SQL
|
|
1773 |
}
|
1774 |
return array('ok' => 1);
|
1775 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1776 |
public static function ajax_removeFromCache_callback(){
|
1777 |
$id = $_POST['id'];
|
1778 |
$link = get_permalink($id);
|
@@ -3469,7 +3478,7 @@ HTML;
|
|
3469 |
'activityLogUpdate', 'ticker', 'loadIssues', 'updateIssueStatus', 'deleteIssue', 'updateAllIssues',
|
3470 |
'reverseLookup', 'unlockOutIP', 'loadBlockRanges', 'unblockRange', 'blockIPUARange', 'whois', 'unblockIP',
|
3471 |
'blockIP', 'permBlockIP', 'loadStaticPanel', 'saveConfig', 'downloadHtaccess', 'checkFalconHtaccess',
|
3472 |
-
'updateConfig', 'saveCacheConfig', 'removeFromCache', 'autoUpdateChoice', 'saveCacheOptions', 'clearPageCache',
|
3473 |
'getCacheStats', 'clearAllBlocked', 'killScan', 'saveCountryBlocking', 'saveScanSchedule', 'tourClosed',
|
3474 |
'welcomeClosed', 'startTourAgain', 'downgradeLicense', 'addTwoFactor', 'twoFacActivate', 'twoFacDel',
|
3475 |
'loadTwoFactor', 'loadAvgSitePerf', 'sendTestEmail', 'addCacheExclusion', 'removeCacheExclusion',
|
@@ -3573,7 +3582,11 @@ HTML;
|
|
3573 |
echo '<div id="wordfenceConfigWarning" class="fade error"><p><strong>Wordfence could not get an API key from the Wordfence scanning servers when it activated.</strong> You can try to fix this by going to the Wordfence "options" page and hitting "Save Changes". This will cause Wordfence to retry fetching an API key for you. If you keep seeing this error it usually means your WordPress server can\'t connect to our scanning servers. You can try asking your WordPress host to allow your WordPress server to connect to noc1.wordfence.com.</p></div>';
|
3574 |
}
|
3575 |
public static function adminEmailWarning(){
|
3576 |
-
|
|
|
|
|
|
|
|
|
3577 |
}
|
3578 |
public static function autoUpdateNotice(){
|
3579 |
echo '<div id="wordfenceAutoUpdateChoice" class="fade error"><p><strong>Do you want Wordfence to stay up-to-date automatically?</strong> <a href="#" onclick="wordfenceExt.autoUpdateChoice(\'yes\'); return false;">Yes, enable auto-update.</a> | <a href="#" onclick="wordfenceExt.autoUpdateChoice(\'no\'); return false;">No thanks.</a></p></div>';
|
@@ -3608,7 +3621,7 @@ HTML;
|
|
3608 |
}
|
3609 |
}
|
3610 |
if(! $warningAdded){
|
3611 |
-
if(wfConfig::get('tourClosed') == '1' && (!
|
3612 |
$warningAdded = true;
|
3613 |
if(wfUtils::isAdminPageMU()){
|
3614 |
add_action('network_admin_notices', 'wordfence::adminEmailWarning');
|
@@ -3864,7 +3877,7 @@ document.location.href=$adminURL;
|
|
3864 |
($serverInfo->isCGI() || $serverInfo->isFastCGI())),
|
3865 |
array("litespeed", 'LiteSpeed', $serverInfo->isLiteSpeed()),
|
3866 |
array("nginx", 'NGINX', $serverInfo->isNGINX()),
|
3867 |
-
|
3868 |
);
|
3869 |
$wafActionContent = '<p>To be as secure as possible, the Wordfence Web Application Firewall is designed
|
3870 |
to run via a PHP ini setting called <code>auto_prepend_file</code> in order to ensure it runs before any potentially
|
@@ -4467,7 +4480,10 @@ to your httpd.conf if using Apache, or find documentation on how to disable dire
|
|
4467 |
(isset($_POST['author']) && is_numeric(preg_replace('/[^0-9]/', '', $_POST['author'])))
|
4468 |
)
|
4469 |
) {
|
4470 |
-
|
|
|
|
|
|
|
4471 |
}
|
4472 |
return $query_vars;
|
4473 |
}
|
@@ -5110,7 +5126,7 @@ LIMIT %d", $lastSendTime, $limit));
|
|
5110 |
if (WFWAF_AUTO_PREPEND && !WFWAF_SUBDIRECTORY_INSTALL) {
|
5111 |
echo '<div class="updated is-dismissible"><p>The installation was successful! Your site is protected to the fullest extent!</p></div>';
|
5112 |
} else {
|
5113 |
-
echo '<div class="notice notice-error"><p>The changes have not yet taken effect. If you are using LiteSpeed
|
5114 |
as your web server or CGI/FastCGI interface, you may need to wait a few minutes for the changes to take effect since the
|
5115 |
configuration files are sometimes cached. You also may need to select a different server configuration in order to
|
5116 |
complete this step, but wait for a few minutes before trying. You can try refreshing this page. </p></div>';
|
@@ -5206,6 +5222,7 @@ class wfWAFAutoPrependHelper {
|
|
5206 |
case 'apache-suphp':
|
5207 |
case 'nginx':
|
5208 |
case 'litespeed':
|
|
|
5209 |
if (file_exists($userIniPath)) {
|
5210 |
$backups[] = $userIniPath;
|
5211 |
}
|
@@ -5357,6 +5374,7 @@ $userIniHtaccessDirectives
|
|
5357 |
case 'nginx':
|
5358 |
case 'apache-suphp':
|
5359 |
case 'litespeed':
|
|
|
5360 |
$autoPrependIni = sprintf("; Wordfence WAF
|
5361 |
auto_prepend_file = '%s'
|
5362 |
; END Wordfence WAF
|
1100 |
if(wfConfig::get('bannedURLs', false)){
|
1101 |
$URLs = explode(',', wfConfig::get('bannedURLs'));
|
1102 |
foreach($URLs as $URL){
|
1103 |
+
if(preg_match(wfUtils::patternToRegex($URL, ''), $_SERVER['REQUEST_URI'])){
|
1104 |
$wfLog->blockIP($IP, "Accessed a banned URL.");
|
1105 |
$wfLog->do503(3600, "Accessed a banned URL.");
|
1106 |
//exits
|
1773 |
}
|
1774 |
return array('ok' => 1);
|
1775 |
}
|
1776 |
+
public static function ajax_adminEmailChoice_callback() {
|
1777 |
+
$choice = $_POST['choice'];
|
1778 |
+
wfConfig::set('adminEmailChoice', '1');
|
1779 |
+
if ($choice == 'mine') {
|
1780 |
+
$email = wp_get_current_user()->user_email;
|
1781 |
+
wfConfig::set('alertEmails', $email);
|
1782 |
+
}
|
1783 |
+
return array('ok' => 1);
|
1784 |
+
}
|
1785 |
public static function ajax_removeFromCache_callback(){
|
1786 |
$id = $_POST['id'];
|
1787 |
$link = get_permalink($id);
|
3478 |
'activityLogUpdate', 'ticker', 'loadIssues', 'updateIssueStatus', 'deleteIssue', 'updateAllIssues',
|
3479 |
'reverseLookup', 'unlockOutIP', 'loadBlockRanges', 'unblockRange', 'blockIPUARange', 'whois', 'unblockIP',
|
3480 |
'blockIP', 'permBlockIP', 'loadStaticPanel', 'saveConfig', 'downloadHtaccess', 'checkFalconHtaccess',
|
3481 |
+
'updateConfig', 'saveCacheConfig', 'removeFromCache', 'autoUpdateChoice', 'adminEmailChoice', 'saveCacheOptions', 'clearPageCache',
|
3482 |
'getCacheStats', 'clearAllBlocked', 'killScan', 'saveCountryBlocking', 'saveScanSchedule', 'tourClosed',
|
3483 |
'welcomeClosed', 'startTourAgain', 'downgradeLicense', 'addTwoFactor', 'twoFacActivate', 'twoFacDel',
|
3484 |
'loadTwoFactor', 'loadAvgSitePerf', 'sendTestEmail', 'addCacheExclusion', 'removeCacheExclusion',
|
3582 |
echo '<div id="wordfenceConfigWarning" class="fade error"><p><strong>Wordfence could not get an API key from the Wordfence scanning servers when it activated.</strong> You can try to fix this by going to the Wordfence "options" page and hitting "Save Changes". This will cause Wordfence to retry fetching an API key for you. If you keep seeing this error it usually means your WordPress server can\'t connect to our scanning servers. You can try asking your WordPress host to allow your WordPress server to connect to noc1.wordfence.com.</p></div>';
|
3583 |
}
|
3584 |
public static function adminEmailWarning(){
|
3585 |
+
$url = network_admin_url('admin.php?page=WordfenceSecOpt&wafAction=useMineForAdminEmailAlerts');
|
3586 |
+
$dismissURL = network_admin_url('admin.php?page=WordfenceSecOpt&wafAction=dismissAdminEmailNotice&nonce=' .
|
3587 |
+
rawurlencode(wp_create_nonce('wfDismissAdminEmailWarning')));
|
3588 |
+
echo '<div id="wordfenceAdminEmailWarning" class="fade error"><p><strong>You have not set an administrator email address to receive alerts for Wordfence.</strong> Please <a href="' . self::getMyOptionsURL() . '">click here to go to the Wordfence Options Page</a> and set an email address where you will receive security alerts from this site.</p><p><a class="button button-small" href="#" onclick="wordfenceExt.adminEmailChoice(\'mine\'); return false;"">Use My Email Address</a>
|
3589 |
+
<a class="button button-small wf-dismiss-link" href="#" onclick="wordfenceExt.adminEmailChoice(\'no\'); return false;">Dismiss</a></p></div>';
|
3590 |
}
|
3591 |
public static function autoUpdateNotice(){
|
3592 |
echo '<div id="wordfenceAutoUpdateChoice" class="fade error"><p><strong>Do you want Wordfence to stay up-to-date automatically?</strong> <a href="#" onclick="wordfenceExt.autoUpdateChoice(\'yes\'); return false;">Yes, enable auto-update.</a> | <a href="#" onclick="wordfenceExt.autoUpdateChoice(\'no\'); return false;">No thanks.</a></p></div>';
|
3621 |
}
|
3622 |
}
|
3623 |
if(! $warningAdded){
|
3624 |
+
if(wfConfig::get('tourClosed') == '1' && (!wfConfig::get('alertEmails') && (!wfConfig::get('adminEmailChoice')))){
|
3625 |
$warningAdded = true;
|
3626 |
if(wfUtils::isAdminPageMU()){
|
3627 |
add_action('network_admin_notices', 'wordfence::adminEmailWarning');
|
3877 |
($serverInfo->isCGI() || $serverInfo->isFastCGI())),
|
3878 |
array("litespeed", 'LiteSpeed', $serverInfo->isLiteSpeed()),
|
3879 |
array("nginx", 'NGINX', $serverInfo->isNGINX()),
|
3880 |
+
array("iis", 'Windows (IIS)', $serverInfo->isIIS()),
|
3881 |
);
|
3882 |
$wafActionContent = '<p>To be as secure as possible, the Wordfence Web Application Firewall is designed
|
3883 |
to run via a PHP ini setting called <code>auto_prepend_file</code> in order to ensure it runs before any potentially
|
4480 |
(isset($_POST['author']) && is_numeric(preg_replace('/[^0-9]/', '', $_POST['author'])))
|
4481 |
)
|
4482 |
) {
|
4483 |
+
status_header(404);
|
4484 |
+
nocache_headers();
|
4485 |
+
include(get_404_template());
|
4486 |
+
exit;
|
4487 |
}
|
4488 |
return $query_vars;
|
4489 |
}
|
5126 |
if (WFWAF_AUTO_PREPEND && !WFWAF_SUBDIRECTORY_INSTALL) {
|
5127 |
echo '<div class="updated is-dismissible"><p>The installation was successful! Your site is protected to the fullest extent!</p></div>';
|
5128 |
} else {
|
5129 |
+
echo '<div class="notice notice-error"><p>The changes have not yet taken effect. If you are using LiteSpeed or IIS
|
5130 |
as your web server or CGI/FastCGI interface, you may need to wait a few minutes for the changes to take effect since the
|
5131 |
configuration files are sometimes cached. You also may need to select a different server configuration in order to
|
5132 |
complete this step, but wait for a few minutes before trying. You can try refreshing this page. </p></div>';
|
5222 |
case 'apache-suphp':
|
5223 |
case 'nginx':
|
5224 |
case 'litespeed':
|
5225 |
+
case 'iis':
|
5226 |
if (file_exists($userIniPath)) {
|
5227 |
$backups[] = $userIniPath;
|
5228 |
}
|
5374 |
case 'nginx':
|
5375 |
case 'apache-suphp':
|
5376 |
case 'litespeed':
|
5377 |
+
case 'iis':
|
5378 |
$autoPrependIni = sprintf("; Wordfence WAF
|
5379 |
auto_prepend_file = '%s'
|
5380 |
; END Wordfence WAF
|
lib/wordfenceHash.php
CHANGED
@@ -199,12 +199,11 @@ class wordfenceHash {
|
|
199 |
//exits
|
200 |
}
|
201 |
|
202 |
-
$exclude =
|
203 |
if ($exclude && preg_match($exclude, $realFile)) {
|
204 |
return;
|
205 |
}
|
206 |
|
207 |
-
|
208 |
//Put this after the fork, that way we will at least scan one more file after we fork if it takes us more than 10 seconds to search for the stoppedOnFile
|
209 |
if($this->stoppedOnFile && $file != $this->stoppedOnFile){
|
210 |
return;
|
@@ -230,99 +229,125 @@ class wordfenceHash {
|
|
230 |
if($this->malwareEnabled && $this->isMalwarePrefix($md5)){
|
231 |
$this->possibleMalware[] = array($file, $md5);
|
232 |
}
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
242 |
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
)
|
258 |
);
|
|
|
259 |
}
|
260 |
}
|
261 |
}
|
262 |
-
}
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
'file
|
275 |
-
2
|
276 |
-
'
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
'
|
282 |
-
'
|
283 |
-
'
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
|
|
|
|
|
|
|
|
289 |
)
|
290 |
);
|
|
|
291 |
}
|
292 |
-
}
|
293 |
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
$
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
'file
|
307 |
-
|
308 |
-
|
309 |
-
'
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
'
|
314 |
-
'
|
315 |
-
'
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
|
|
|
|
|
|
|
|
|
|
321 |
)
|
322 |
);
|
|
|
323 |
}
|
324 |
-
}
|
325 |
|
|
|
326 |
}
|
327 |
}
|
328 |
// knownFile means that the file is both part of core or a known plugin or theme AND that we recognize the file's hash.
|
199 |
//exits
|
200 |
}
|
201 |
|
202 |
+
$exclude = wordfenceScanner::getExcludeFilePattern(wordfenceScanner::EXCLUSION_PATTERNS_USER);
|
203 |
if ($exclude && preg_match($exclude, $realFile)) {
|
204 |
return;
|
205 |
}
|
206 |
|
|
|
207 |
//Put this after the fork, that way we will at least scan one more file after we fork if it takes us more than 10 seconds to search for the stoppedOnFile
|
208 |
if($this->stoppedOnFile && $file != $this->stoppedOnFile){
|
209 |
return;
|
229 |
if($this->malwareEnabled && $this->isMalwarePrefix($md5)){
|
230 |
$this->possibleMalware[] = array($file, $md5);
|
231 |
}
|
232 |
+
|
233 |
+
$knownFileExclude = wordfenceScanner::getExcludeFilePattern(wordfenceScanner::EXCLUSION_PATTERNS_KNOWN_FILES);
|
234 |
+
$allowKnownFileScan = true;
|
235 |
+
if ($knownFileExclude) {
|
236 |
+
$allowKnownFileScan = !preg_match($knownFileExclude, $realFile);
|
237 |
+
}
|
238 |
+
|
239 |
+
if ($allowKnownFileScan)
|
240 |
+
{
|
241 |
+
if (isset($this->knownFiles['core'][$file]))
|
242 |
+
{
|
243 |
+
if (strtoupper($this->knownFiles['core'][$file]) == $shac)
|
244 |
+
{
|
245 |
+
$knownFile = 1;
|
246 |
+
} else
|
247 |
+
{
|
248 |
+
if ($this->coreEnabled)
|
249 |
+
{
|
250 |
+
$localFile = ABSPATH . '/' . preg_replace('/^[\.\/]+/', '', $file);
|
251 |
+
$fileContents = @file_get_contents($localFile);
|
252 |
+
if ($fileContents && (!preg_match('/<\?' . 'php[\r\n\s\t]*\/\/[\r\n\s\t]*Silence is golden\.[\r\n\s\t]*(?:\?>)?[\r\n\s\t]*$/s', $fileContents)))
|
253 |
+
{ //<?php
|
254 |
+
if (!$this->isSafeFile($shac))
|
255 |
+
{
|
256 |
|
257 |
+
$this->haveIssues['core'] = true;
|
258 |
+
$this->engine->addIssue(
|
259 |
+
'file',
|
260 |
+
1,
|
261 |
+
'coreModified' . $file . $md5,
|
262 |
+
'coreModified' . $file,
|
263 |
+
'WordPress core file modified: ' . $file,
|
264 |
+
"This WordPress core file has been modified and differs from the original file distributed with this version of WordPress.",
|
265 |
+
array(
|
266 |
+
'file' => $file,
|
267 |
+
'cType' => 'core',
|
268 |
+
'canDiff' => true,
|
269 |
+
'canFix' => true,
|
270 |
+
'canDelete' => false
|
271 |
)
|
272 |
);
|
273 |
+
}
|
274 |
}
|
275 |
}
|
276 |
}
|
277 |
+
} else if (isset($this->knownFiles['plugins'][$file]))
|
278 |
+
{
|
279 |
+
if (in_array($shac, $this->knownFiles['plugins'][$file]))
|
280 |
+
{
|
281 |
+
$knownFile = 1;
|
282 |
+
} else
|
283 |
+
{
|
284 |
+
if ($this->pluginsEnabled)
|
285 |
+
{
|
286 |
+
if (!$this->isSafeFile($shac))
|
287 |
+
{
|
288 |
+
$itemName = $this->knownFiles['plugins'][$file][0];
|
289 |
+
$itemVersion = $this->knownFiles['plugins'][$file][1];
|
290 |
+
$cKey = $this->knownFiles['plugins'][$file][2];
|
291 |
+
$this->haveIssues['plugins'] = true;
|
292 |
+
$this->engine->addIssue(
|
293 |
+
'file',
|
294 |
+
2,
|
295 |
+
'modifiedplugin' . $file . $md5,
|
296 |
+
'modifiedplugin' . $file,
|
297 |
+
'Modified plugin file: ' . $file,
|
298 |
+
"This file belongs to plugin \"$itemName\" version \"$itemVersion\" and has been modified from the file that is distributed by WordPress.org for this version. Please use the link to see how the file has changed. If you have modified this file yourself, you can safely ignore this warning. If you see a lot of changed files in a plugin that have been made by the author, then try uninstalling and reinstalling the plugin to force an upgrade. Doing this is a workaround for plugin authors who don't manage their code correctly. [See our FAQ on www.wordfence.com for more info]",
|
299 |
+
array(
|
300 |
+
'file' => $file,
|
301 |
+
'cType' => 'plugin',
|
302 |
+
'canDiff' => true,
|
303 |
+
'canFix' => true,
|
304 |
+
'canDelete' => false,
|
305 |
+
'cName' => $itemName,
|
306 |
+
'cVersion' => $itemVersion,
|
307 |
+
'cKey' => $cKey
|
308 |
)
|
309 |
);
|
310 |
+
}
|
311 |
}
|
|
|
312 |
|
313 |
+
}
|
314 |
+
} else if (isset($this->knownFiles['themes'][$file]))
|
315 |
+
{
|
316 |
+
if (in_array($shac, $this->knownFiles['themes'][$file]))
|
317 |
+
{
|
318 |
+
$knownFile = 1;
|
319 |
+
} else
|
320 |
+
{
|
321 |
+
if ($this->themesEnabled)
|
322 |
+
{
|
323 |
+
if (!$this->isSafeFile($shac))
|
324 |
+
{
|
325 |
+
$itemName = $this->knownFiles['themes'][$file][0];
|
326 |
+
$itemVersion = $this->knownFiles['themes'][$file][1];
|
327 |
+
$cKey = $this->knownFiles['themes'][$file][2];
|
328 |
+
$this->haveIssues['themes'] = true;
|
329 |
+
$this->engine->addIssue(
|
330 |
+
'file',
|
331 |
+
2,
|
332 |
+
'modifiedtheme' . $file . $md5,
|
333 |
+
'modifiedtheme' . $file,
|
334 |
+
'Modified theme file: ' . $file,
|
335 |
+
"This file belongs to theme \"$itemName\" version \"$itemVersion\" and has been modified from the original distribution. It is common for site owners to modify their theme files, so if you have modified this file yourself you can safely ignore this warning.",
|
336 |
+
array(
|
337 |
+
'file' => $file,
|
338 |
+
'cType' => 'theme',
|
339 |
+
'canDiff' => true,
|
340 |
+
'canFix' => true,
|
341 |
+
'canDelete' => false,
|
342 |
+
'cName' => $itemName,
|
343 |
+
'cVersion' => $itemVersion,
|
344 |
+
'cKey' => $cKey
|
345 |
)
|
346 |
);
|
347 |
+
}
|
348 |
}
|
|
|
349 |
|
350 |
+
}
|
351 |
}
|
352 |
}
|
353 |
// knownFile means that the file is both part of core or a known plugin or theme AND that we recognize the file's hash.
|
lib/wordfenceScanner.php
CHANGED
@@ -3,6 +3,24 @@ require_once('wordfenceConstants.php');
|
|
3 |
require_once('wordfenceClass.php');
|
4 |
require_once('wordfenceURLHoover.php');
|
5 |
class wordfenceScanner {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
//serialized:
|
7 |
protected $path = '';
|
8 |
protected $results = array();
|
@@ -14,7 +32,10 @@ class wordfenceScanner {
|
|
14 |
protected $lastStatusTime = false;
|
15 |
protected $patterns = "";
|
16 |
protected $api = false;
|
17 |
-
protected static $
|
|
|
|
|
|
|
18 |
/** @var wfScanEngine */
|
19 |
protected $scanEngine;
|
20 |
|
@@ -87,29 +108,46 @@ class wordfenceScanner {
|
|
87 |
}
|
88 |
|
89 |
/**
|
90 |
-
*
|
91 |
-
*
|
92 |
*
|
93 |
-
*
|
|
|
94 |
*/
|
95 |
-
public static function getExcludeFilePattern() {
|
96 |
-
if (self::$
|
97 |
-
return self::$
|
98 |
}
|
99 |
-
|
100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
foreach($exParts as &$exPart){
|
102 |
$exPart = preg_quote(trim($exPart), '/');
|
103 |
$exPart = preg_replace('/\\\\\*/', '.*', $exPart);
|
104 |
}
|
105 |
|
106 |
-
self::$excludePattern = '/^(?:' . implode('|', array_filter($exParts)) . ')$/i';
|
107 |
-
self::$
|
108 |
-
}
|
109 |
-
|
|
|
110 |
}
|
111 |
|
112 |
-
return self::$
|
113 |
}
|
114 |
|
115 |
/**
|
@@ -127,7 +165,7 @@ class wordfenceScanner {
|
|
127 |
}
|
128 |
$db = new wfDB();
|
129 |
$lastCount = 'whatever';
|
130 |
-
$excludePattern = self::getExcludeFilePattern();
|
131 |
while(true){
|
132 |
$thisCount = $db->querySingle("select count(*) from " . $db->prefix() . "wfFileMods where oldMD5 != newMD5 and knownFile=0");
|
133 |
if($thisCount == $lastCount){
|
3 |
require_once('wordfenceClass.php');
|
4 |
require_once('wordfenceURLHoover.php');
|
5 |
class wordfenceScanner {
|
6 |
+
/*
|
7 |
+
* Mask to return all patterns in the exclusion list.
|
8 |
+
* @var int
|
9 |
+
*/
|
10 |
+
const EXCLUSION_PATTERNS_ALL = PHP_INT_MAX;
|
11 |
+
/*
|
12 |
+
* Mask for patterns that the user has added.
|
13 |
+
*/
|
14 |
+
const EXCLUSION_PATTERNS_USER = 0x1;
|
15 |
+
/*
|
16 |
+
* Mask for patterns that should be excluded from the known files scan.
|
17 |
+
*/
|
18 |
+
const EXCLUSION_PATTERNS_KNOWN_FILES = 0x2;
|
19 |
+
/*
|
20 |
+
* Mask for patterns that should be excluded from the malware scan.
|
21 |
+
*/
|
22 |
+
const EXCLUSION_PATTERNS_MALWARE = 0x4;
|
23 |
+
|
24 |
//serialized:
|
25 |
protected $path = '';
|
26 |
protected $results = array();
|
32 |
protected $lastStatusTime = false;
|
33 |
protected $patterns = "";
|
34 |
protected $api = false;
|
35 |
+
protected static $excludePatterns = array();
|
36 |
+
protected static $builtinExclusions = array(
|
37 |
+
array('pattern' => 'wp-includes/version.php', 'include' => self::EXCLUSION_PATTERNS_KNOWN_FILES), //Excluded from the known files scan because non-en_US installations will have extra content that fails the check, still in malware scan
|
38 |
+
);
|
39 |
/** @var wfScanEngine */
|
40 |
protected $scanEngine;
|
41 |
|
108 |
}
|
109 |
|
110 |
/**
|
111 |
+
* Return regular expression to exclude files or false if
|
112 |
+
* there is no pattern
|
113 |
*
|
114 |
+
* @param $whichPatterns int Bitmask indicating which patterns to include.
|
115 |
+
* @return string|boolean
|
116 |
*/
|
117 |
+
public static function getExcludeFilePattern($whichPatterns = self::EXCLUSION_PATTERNS_USER) {
|
118 |
+
if (isset(self::$excludePatterns[$whichPatterns])) {
|
119 |
+
return self::$excludePatterns[$whichPatterns];
|
120 |
}
|
121 |
+
|
122 |
+
$exParts = array();
|
123 |
+
if (($whichPatterns & self::EXCLUSION_PATTERNS_USER) > 0)
|
124 |
+
{
|
125 |
+
if (wfConfig::get('scan_exclude', false))
|
126 |
+
{
|
127 |
+
$exParts = explode("\n", wfUtils::cleanupOneEntryPerLine(wfConfig::get('scan_exclude')));
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
foreach (self::$builtinExclusions as $pattern) {
|
132 |
+
if (($pattern['include'] & $whichPatterns) > 0) {
|
133 |
+
$exParts[] = $pattern['pattern'];
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
if (!empty($exParts)) {
|
138 |
foreach($exParts as &$exPart){
|
139 |
$exPart = preg_quote(trim($exPart), '/');
|
140 |
$exPart = preg_replace('/\\\\\*/', '.*', $exPart);
|
141 |
}
|
142 |
|
143 |
+
//self::$excludePattern = '/^(?:' . implode('|', array_filter($exParts)) . ')$/i';
|
144 |
+
self::$excludePatterns[$whichPatterns] = '/(?:' . implode('|', array_filter($exParts)) . ')$/i';
|
145 |
+
}
|
146 |
+
else {
|
147 |
+
self::$excludePatterns[$whichPatterns]= false;
|
148 |
}
|
149 |
|
150 |
+
return self::$excludePatterns[$whichPatterns];
|
151 |
}
|
152 |
|
153 |
/**
|
165 |
}
|
166 |
$db = new wfDB();
|
167 |
$lastCount = 'whatever';
|
168 |
+
$excludePattern = self::getExcludeFilePattern(self::EXCLUSION_PATTERNS_USER & self::EXCLUSION_PATTERNS_MALWARE);
|
169 |
while(true){
|
170 |
$thisCount = $db->querySingle("select count(*) from " . $db->prefix() . "wfFileMods where oldMD5 != newMD5 and knownFile=0");
|
171 |
if($thisCount == $lastCount){
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: mmaunder
|
3 |
Tags: wordpress, security, web application firewall, waf, performance, speed, caching, cache, caching plugin, wordpress cache, wordpress caching, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure, two factor, cellphone sign-in, cellphone signin, cellphone, twofactor, security, secure, htaccess, login, log, users, login alerts, lock, chmod, maintenance, plugin, private, privacy, protection, permissions, 503, base64, injection, code, encode, script, attack, hack, hackers, block, blocked, prevent, prevention, RFI, XSS, CRLF, CSRF, SQL Injection, vulnerability, website security, WordPress security, security log, logging, HTTP log, error log, login security, personal security, infrastructure security, firewall security, front-end security, web server security, proxy security, reverse proxy security, secure website, secure login, two factor security, two factor authentication, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm, woocommerce support, woocommerce caching, IPv6, IP version 6
|
4 |
Requires at least: 3.9
|
5 |
-
Tested up to: 4.5
|
6 |
-
Stable tag: 6.1.
|
7 |
|
8 |
The Wordfence WordPress security plugin provides free enterprise-class WordPress security, protecting your website from hacks and malware.
|
9 |
== Description ==
|
@@ -195,22 +195,32 @@ Designed for every skill level, [The WordPress Security Learning Center](https:/
|
|
195 |
|
196 |
== Changelog ==
|
197 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
= 6.1.4 =
|
199 |
-
Fix: Fixed potential bug with 'stored data not found after a fork. Got type: boolean'.
|
200 |
-
Improvement: Added bulk actions and filters to WAF whitelist table.
|
201 |
-
Improvement: Added a check while in learning mode to verify the response is not 404 before whitelising.
|
202 |
-
Fix: Added index to attackLogTime. wfHits trimmed on runInstall now.
|
203 |
-
Fix: Fixed attack data sync for hosts that cannot use wp-cron.
|
204 |
-
Improvement: Use wftest@wordfence.com as the Diagnostics page default email address.
|
205 |
-
Improvement: When WFWAF_ENABLED is set to false to disable the firewall, show this on the Firewall page.
|
206 |
-
Fix: Prevent warnings when $_SERVER is empty.
|
207 |
-
Fix: Bug fix for illegal string offset.
|
208 |
-
Fix: Hooked up multibyte string functions to binary safe equivalents.
|
209 |
-
Fix: Hooked up reverse IP lookup in Live Traffic.
|
210 |
-
Fix: Add the user the web server (or PHP) is currently running as to Diagnostics page.
|
211 |
-
Improvement: Pause Live Traffic after scrolling past the first entry.
|
212 |
-
Improvement: Move "Permanently block all temporarily blocked IP addresses" button to top of blocked IP list.
|
213 |
-
Fix: Added JSON fallback for PHP installations that don't have JSON enabled.
|
214 |
|
215 |
= 6.1.3 =
|
216 |
* Improvement: Added dismiss button to the Wordfence WAF setup admin notice.
|
2 |
Contributors: mmaunder
|
3 |
Tags: wordpress, security, web application firewall, waf, performance, speed, caching, cache, caching plugin, wordpress cache, wordpress caching, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure, two factor, cellphone sign-in, cellphone signin, cellphone, twofactor, security, secure, htaccess, login, log, users, login alerts, lock, chmod, maintenance, plugin, private, privacy, protection, permissions, 503, base64, injection, code, encode, script, attack, hack, hackers, block, blocked, prevent, prevention, RFI, XSS, CRLF, CSRF, SQL Injection, vulnerability, website security, WordPress security, security log, logging, HTTP log, error log, login security, personal security, infrastructure security, firewall security, front-end security, web server security, proxy security, reverse proxy security, secure website, secure login, two factor security, two factor authentication, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm, woocommerce support, woocommerce caching, IPv6, IP version 6
|
4 |
Requires at least: 3.9
|
5 |
+
Tested up to: 4.5.1
|
6 |
+
Stable tag: 6.1.5
|
7 |
|
8 |
The Wordfence WordPress security plugin provides free enterprise-class WordPress security, protecting your website from hacks and malware.
|
9 |
== Description ==
|
195 |
|
196 |
== Changelog ==
|
197 |
|
198 |
+
= 6.1.5 =
|
199 |
+
* Fix: WordPress language files no longer flagged as changed.
|
200 |
+
* Improvement: Accept wildcards in "Immediately block IP's that access these URLs."
|
201 |
+
* Fix: Fixed bug when multiple authors have published posts, /?author=N scans show an author archive page.
|
202 |
+
* Fix: Fixed issue with IPv6 mapped IPv4 addresses not being treated as IPv4.
|
203 |
+
* Improvement: Added WordPress version and various constants to Diagnostics report.
|
204 |
+
* Fix: Fixed bug with Windows users unable to save Firewall config.
|
205 |
+
* Improvement: Include option for IIS on Windows in Firewall config process, and recommend manual php.ini change only.
|
206 |
+
* Fix: Made the 'administrator email address' admin notice dismissable.
|
207 |
+
|
208 |
= 6.1.4 =
|
209 |
+
* Fix: Fixed potential bug with 'stored data not found after a fork. Got type: boolean'.
|
210 |
+
* Improvement: Added bulk actions and filters to WAF whitelist table.
|
211 |
+
* Improvement: Added a check while in learning mode to verify the response is not 404 before whitelising.
|
212 |
+
* Fix: Added index to attackLogTime. wfHits trimmed on runInstall now.
|
213 |
+
* Fix: Fixed attack data sync for hosts that cannot use wp-cron.
|
214 |
+
* Improvement: Use wftest@wordfence.com as the Diagnostics page default email address.
|
215 |
+
* Improvement: When WFWAF_ENABLED is set to false to disable the firewall, show this on the Firewall page.
|
216 |
+
* Fix: Prevent warnings when $_SERVER is empty.
|
217 |
+
* Fix: Bug fix for illegal string offset.
|
218 |
+
* Fix: Hooked up multibyte string functions to binary safe equivalents.
|
219 |
+
* Fix: Hooked up reverse IP lookup in Live Traffic.
|
220 |
+
* Fix: Add the user the web server (or PHP) is currently running as to Diagnostics page.
|
221 |
+
* Improvement: Pause Live Traffic after scrolling past the first entry.
|
222 |
+
* Improvement: Move "Permanently block all temporarily blocked IP addresses" button to top of blocked IP list.
|
223 |
+
* Fix: Added JSON fallback for PHP installations that don't have JSON enabled.
|
224 |
|
225 |
= 6.1.3 =
|
226 |
* Improvement: Added dismiss button to the Wordfence WAF setup admin notice.
|
vendor/wordfence/wf-waf/src/init.php
CHANGED
@@ -4,7 +4,7 @@ define('WFWAF_VERSION', '1.0.0');
|
|
4 |
define('WFWAF_PATH', dirname(__FILE__) . '/');
|
5 |
define('WFWAF_LIB_PATH', WFWAF_PATH . 'lib/');
|
6 |
define('WFWAF_VIEW_PATH', WFWAF_PATH . 'views/');
|
7 |
-
define('WFWAF_API_URL_SEC', 'https://noc4.wordfence.com/v1.
|
8 |
if (!defined('WFWAF_DEBUG')) {
|
9 |
define('WFWAF_DEBUG', false);
|
10 |
}
|
@@ -12,6 +12,8 @@ if (!defined('WFWAF_ENABLED')) {
|
|
12 |
define('WFWAF_ENABLED', true);
|
13 |
}
|
14 |
|
|
|
|
|
15 |
require_once WFWAF_LIB_PATH . 'waf.php';
|
16 |
require_once WFWAF_LIB_PATH . 'utils.php';
|
17 |
|
4 |
define('WFWAF_PATH', dirname(__FILE__) . '/');
|
5 |
define('WFWAF_LIB_PATH', WFWAF_PATH . 'lib/');
|
6 |
define('WFWAF_VIEW_PATH', WFWAF_PATH . 'views/');
|
7 |
+
define('WFWAF_API_URL_SEC', 'https://noc4.wordfence.com/v1.2/');
|
8 |
if (!defined('WFWAF_DEBUG')) {
|
9 |
define('WFWAF_DEBUG', false);
|
10 |
}
|
12 |
define('WFWAF_ENABLED', true);
|
13 |
}
|
14 |
|
15 |
+
define('WFWAF_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
|
16 |
+
|
17 |
require_once WFWAF_LIB_PATH . 'waf.php';
|
18 |
require_once WFWAF_LIB_PATH . 'utils.php';
|
19 |
|
vendor/wordfence/wf-waf/src/lib/parser/lexer.php
CHANGED
@@ -301,6 +301,18 @@ class wfWAFBaseParser {
|
|
301 |
$this->lexer = $lexer;
|
302 |
}
|
303 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
304 |
/**
|
305 |
* @param wfWAFLexerToken $token
|
306 |
* @param int $type
|
301 |
$this->lexer = $lexer;
|
302 |
}
|
303 |
|
304 |
+
/**
|
305 |
+
* @param wfWAFLexerToken $token
|
306 |
+
* @param mixed $type
|
307 |
+
* @return bool
|
308 |
+
*/
|
309 |
+
protected function isTokenOfType($token, $type) {
|
310 |
+
if (is_array($type)) {
|
311 |
+
return $token && in_array($token->getType(), $type);
|
312 |
+
}
|
313 |
+
return $token && $token->getType() === $type;
|
314 |
+
}
|
315 |
+
|
316 |
/**
|
317 |
* @param wfWAFLexerToken $token
|
318 |
* @param int $type
|
vendor/wordfence/wf-waf/src/lib/parser/parser.php
CHANGED
@@ -50,6 +50,7 @@ class wfWAFRuleParser extends wfWAFBaseParser {
|
|
50 |
$action->getCategory(),
|
51 |
$action->getScore(),
|
52 |
$action->getDescription(),
|
|
|
53 |
$action->getAction(),
|
54 |
$comparisonGroup
|
55 |
);
|
@@ -312,22 +313,38 @@ class wfWAFRuleParser extends wfWAFBaseParser {
|
|
312 |
$subject = array(
|
313 |
$globalToken->getValue() . '.' . $globalToken2->getValue(),
|
314 |
);
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
break;
|
320 |
-
}
|
321 |
-
$paramToken = $this->expectNextToken();
|
322 |
-
$this->expectTokenTypeEquals($paramToken, wfWAFRuleLexer::T_IDENTIFIER);
|
323 |
-
$subject[] = $paramToken->getValue();
|
324 |
}
|
|
|
325 |
if (count($subject) === 1) {
|
326 |
list($subject) = $subject;
|
327 |
}
|
328 |
return $subject;
|
329 |
}
|
330 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
331 |
/**
|
332 |
* @return wfWAFRuleParserURLParam
|
333 |
* @throws wfWAFParserSyntaxError
|
@@ -411,6 +428,17 @@ class wfWAFRuleParser extends wfWAFBaseParser {
|
|
411 |
return $value;
|
412 |
}
|
413 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
414 |
/**
|
415 |
* @param wfWAFLexerToken $token
|
416 |
* @return bool
|
@@ -441,6 +469,7 @@ class wfWAFRuleParserAction {
|
|
441 |
private $category;
|
442 |
private $score;
|
443 |
private $description;
|
|
|
444 |
private $action;
|
445 |
|
446 |
/**
|
@@ -529,6 +558,20 @@ class wfWAFRuleParserAction {
|
|
529 |
$this->description = $description;
|
530 |
}
|
531 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
532 |
/**
|
533 |
* @return mixed
|
534 |
*/
|
@@ -588,7 +631,9 @@ class wfWAFRuleParserURLParam {
|
|
588 |
* @return string
|
589 |
*/
|
590 |
public function renderRule($action) {
|
591 |
-
return sprintf('%s(url=%s, param=%s%s)', $action,
|
|
|
|
|
592 |
$this->getRules() ? ', rules=[' . join(', ', array_map('intval', $this->getRules())) . ']' : '');
|
593 |
}
|
594 |
|
@@ -597,7 +642,21 @@ class wfWAFRuleParserURLParam {
|
|
597 |
* @return mixed
|
598 |
*/
|
599 |
private function renderParam($param) {
|
600 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
601 |
}
|
602 |
|
603 |
/**
|
50 |
$action->getCategory(),
|
51 |
$action->getScore(),
|
52 |
$action->getDescription(),
|
53 |
+
$action->getWhitelist(),
|
54 |
$action->getAction(),
|
55 |
$comparisonGroup
|
56 |
);
|
313 |
$subject = array(
|
314 |
$globalToken->getValue() . '.' . $globalToken2->getValue(),
|
315 |
);
|
316 |
+
$savePoint = $this->index;
|
317 |
+
while (($property = $this->parsePropertyAccessor()) !== false) {
|
318 |
+
$subject[] = $property;
|
319 |
+
$savePoint = $this->index;
|
|
|
|
|
|
|
|
|
|
|
320 |
}
|
321 |
+
$this->index = $savePoint;
|
322 |
if (count($subject) === 1) {
|
323 |
list($subject) = $subject;
|
324 |
}
|
325 |
return $subject;
|
326 |
}
|
327 |
|
328 |
+
/**
|
329 |
+
* @return bool|mixed|string
|
330 |
+
* @throws wfWAFParserSyntaxError
|
331 |
+
*/
|
332 |
+
private function parsePropertyAccessor() {
|
333 |
+
$savePoint = $this->index;
|
334 |
+
$nextToken = $this->nextToken();
|
335 |
+
if ($this->isTokenOfType($nextToken, wfWAFRuleLexer::T_DOT)) {
|
336 |
+
$property = $this->expectNextToken();
|
337 |
+
$this->expectTokenTypeEquals($property, wfWAFRuleLexer::T_IDENTIFIER);
|
338 |
+
return $property->getValue();
|
339 |
+
} else if ($this->isTokenOfType($nextToken, wfWAFRuleLexer::T_OPEN_BRACKET)) {
|
340 |
+
$property = $this->expectLiteral();
|
341 |
+
$this->expectTokenTypeEquals($this->expectNextToken(), wfWAFRuleLexer::T_CLOSE_BRACKET);
|
342 |
+
return $property;
|
343 |
+
}
|
344 |
+
$this->index = $savePoint;
|
345 |
+
return false;
|
346 |
+
}
|
347 |
+
|
348 |
/**
|
349 |
* @return wfWAFRuleParserURLParam
|
350 |
* @throws wfWAFParserSyntaxError
|
428 |
return $value;
|
429 |
}
|
430 |
|
431 |
+
/**
|
432 |
+
* @param wfWAFLexerToken $token
|
433 |
+
* @param string|array $value
|
434 |
+
* @return bool
|
435 |
+
*/
|
436 |
+
private function isIdentifierWithValue($token, $value) {
|
437 |
+
return $token && $token->getType() === wfWAFRuleLexer::T_IDENTIFIER &&
|
438 |
+
(is_array($value) ? in_array($token->getLowerCaseValue(), array_map('strtolower', $value)) :
|
439 |
+
$token->getLowerCaseValue() === strtolower($value));
|
440 |
+
}
|
441 |
+
|
442 |
/**
|
443 |
* @param wfWAFLexerToken $token
|
444 |
* @return bool
|
469 |
private $category;
|
470 |
private $score;
|
471 |
private $description;
|
472 |
+
private $whitelist = 1;
|
473 |
private $action;
|
474 |
|
475 |
/**
|
558 |
$this->description = $description;
|
559 |
}
|
560 |
|
561 |
+
/**
|
562 |
+
* @return mixed
|
563 |
+
*/
|
564 |
+
public function getWhitelist() {
|
565 |
+
return $this->whitelist;
|
566 |
+
}
|
567 |
+
|
568 |
+
/**
|
569 |
+
* @param mixed $whitelist
|
570 |
+
*/
|
571 |
+
public function setWhitelist($whitelist) {
|
572 |
+
$this->whitelist = $whitelist;
|
573 |
+
}
|
574 |
+
|
575 |
/**
|
576 |
* @return mixed
|
577 |
*/
|
631 |
* @return string
|
632 |
*/
|
633 |
public function renderRule($action) {
|
634 |
+
return sprintf('%s(url=%s, param=%s%s)', $action,
|
635 |
+
wfWAFRule::exportString($this->getUrl()),
|
636 |
+
$this->renderParam($this->getParam()),
|
637 |
$this->getRules() ? ', rules=[' . join(', ', array_map('intval', $this->getRules())) . ']' : '');
|
638 |
}
|
639 |
|
642 |
* @return mixed
|
643 |
*/
|
644 |
private function renderParam($param) {
|
645 |
+
if (preg_match('/([a-zA-Z_][\\w_]*?\\.[a-zA-Z_][\\w_]*)(.*)/', $param, $matches)) {
|
646 |
+
list(, $global, $params) = $matches;
|
647 |
+
if (strlen($params) > 0) {
|
648 |
+
if (preg_match_all('/\\[([^\\]]*?)\\]/', $params, $matches)) {
|
649 |
+
$rendered = $global;
|
650 |
+
foreach ($matches[1] as $prop) {
|
651 |
+
$single = "'" . str_replace(array("'", '\\'), array("\\'", "\\\\"), $prop) . "'";
|
652 |
+
$double = '"' . str_replace(array('"', '\\'), array('\\"', "\\\\"), $prop) . '"';
|
653 |
+
$rendered .= sprintf('[%s]', strlen($single) <= strlen($double) ? $single : $double);
|
654 |
+
}
|
655 |
+
return $rendered;
|
656 |
+
}
|
657 |
+
}
|
658 |
+
}
|
659 |
+
return $param;
|
660 |
}
|
661 |
|
662 |
/**
|
vendor/wordfence/wf-waf/src/lib/parser/sqli.php
CHANGED
@@ -2562,18 +2562,6 @@ class wfWAFSQLiParser extends wfWAFBaseParser {
|
|
2562 |
$token->getLowerCaseValue() === wfWAFUtils::strtolower($value));
|
2563 |
}
|
2564 |
|
2565 |
-
/**
|
2566 |
-
* @param wfWAFLexerToken $token
|
2567 |
-
* @param mixed $type
|
2568 |
-
* @return bool
|
2569 |
-
*/
|
2570 |
-
private function isTokenOfType($token, $type) {
|
2571 |
-
if (is_array($type)) {
|
2572 |
-
return $token && in_array($token->getType(), $type);
|
2573 |
-
}
|
2574 |
-
return $token && $token->getType() === $type;
|
2575 |
-
}
|
2576 |
-
|
2577 |
/**
|
2578 |
* @param wfWAFLexerToken $token
|
2579 |
* @return bool
|
2562 |
$token->getLowerCaseValue() === wfWAFUtils::strtolower($value));
|
2563 |
}
|
2564 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2565 |
/**
|
2566 |
* @param wfWAFLexerToken $token
|
2567 |
* @return bool
|
vendor/wordfence/wf-waf/src/lib/rules.php
CHANGED
@@ -25,6 +25,7 @@ class wfWAFRule implements wfWAFRuleInterface {
|
|
25 |
private $category;
|
26 |
private $score;
|
27 |
private $description;
|
|
|
28 |
private $action;
|
29 |
private $comparisonGroup;
|
30 |
/**
|
@@ -39,12 +40,32 @@ class wfWAFRule implements wfWAFRuleInterface {
|
|
39 |
* @param string $category
|
40 |
* @param int $score
|
41 |
* @param string $description
|
|
|
42 |
* @param string $action
|
43 |
* @param wfWAFRuleComparisonGroup $comparisonGroup
|
44 |
* @return wfWAFRule
|
45 |
*/
|
46 |
-
public static function create(
|
47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
}
|
49 |
|
50 |
/**
|
@@ -62,16 +83,18 @@ class wfWAFRule implements wfWAFRuleInterface {
|
|
62 |
* @param string $category
|
63 |
* @param int $score
|
64 |
* @param string $description
|
|
|
65 |
* @param string $action
|
66 |
* @param wfWAFRuleComparisonGroup $comparisonGroup
|
67 |
*/
|
68 |
-
public function __construct($waf, $ruleID, $type, $category, $score, $description, $action, $comparisonGroup) {
|
69 |
$this->setWAF($waf);
|
70 |
$this->setRuleID($ruleID);
|
71 |
$this->setType($type);
|
72 |
$this->setCategory($category);
|
73 |
$this->setScore($score);
|
74 |
$this->setDescription($description);
|
|
|
75 |
$this->setAction($action);
|
76 |
$this->setComparisonGroup($comparisonGroup);
|
77 |
}
|
@@ -80,12 +103,13 @@ class wfWAFRule implements wfWAFRuleInterface {
|
|
80 |
* @return string
|
81 |
*/
|
82 |
public function render() {
|
83 |
-
return sprintf('%s::create($this, %d, %s, %s, %s, %s, %s, %s)', get_class($this),
|
84 |
$this->getRuleID(),
|
85 |
var_export($this->getType(), true),
|
86 |
var_export($this->getCategory(), true),
|
87 |
var_export($this->getScore(), true),
|
88 |
var_export($this->getDescription(), true),
|
|
|
89 |
var_export($this->getAction(), true),
|
90 |
$this->getComparisonGroup()->render()
|
91 |
);
|
@@ -106,7 +130,8 @@ RULE
|
|
106 |
$this->getRuleID() ? 'id=' . (int) $this->getRuleID() : '',
|
107 |
$this->getCategory() ? 'category=' . self::exportString($this->getCategory()) : '',
|
108 |
$this->getScore() > 0 ? 'score=' . (int) $this->getScore() : '',
|
109 |
-
$this->
|
|
|
110 |
)))
|
111 |
);
|
112 |
}
|
@@ -140,6 +165,7 @@ RULE
|
|
140 |
'category' => $this->getCategory(),
|
141 |
'score' => $this->getScore(),
|
142 |
'description' => $this->getDescription(),
|
|
|
143 |
'action' => $this->getAction(),
|
144 |
);
|
145 |
}
|
@@ -214,6 +240,20 @@ RULE
|
|
214 |
$this->description = $description;
|
215 |
}
|
216 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
/**
|
218 |
* @return string
|
219 |
*/
|
@@ -415,6 +455,7 @@ class wfWAFRuleComparison implements wfWAFRuleInterface {
|
|
415 |
'lengthlessthan',
|
416 |
'currentuseris',
|
417 |
'currentuserisnot',
|
|
|
418 |
);
|
419 |
|
420 |
/**
|
@@ -653,6 +694,10 @@ class wfWAFRuleComparison implements wfWAFRuleInterface {
|
|
653 |
return !$this->currentUserIs($subject);
|
654 |
}
|
655 |
|
|
|
|
|
|
|
|
|
656 |
/**
|
657 |
* @return mixed
|
658 |
*/
|
25 |
private $category;
|
26 |
private $score;
|
27 |
private $description;
|
28 |
+
private $whitelist;
|
29 |
private $action;
|
30 |
private $comparisonGroup;
|
31 |
/**
|
40 |
* @param string $category
|
41 |
* @param int $score
|
42 |
* @param string $description
|
43 |
+
* @param int $whitelist
|
44 |
* @param string $action
|
45 |
* @param wfWAFRuleComparisonGroup $comparisonGroup
|
46 |
* @return wfWAFRule
|
47 |
*/
|
48 |
+
public static function create() {
|
49 |
+
$waf = func_get_arg(0);
|
50 |
+
$ruleID = func_get_arg(1);
|
51 |
+
$type = func_get_arg(2);
|
52 |
+
$category = func_get_arg(3);
|
53 |
+
$score = func_get_arg(4);
|
54 |
+
$description = func_get_arg(5);
|
55 |
+
$whitelist = 1;
|
56 |
+
$action = '';
|
57 |
+
$comparisonGroup = null;
|
58 |
+
//Compatibility with old compiled rules
|
59 |
+
if (func_num_args() == 8) { //Pre-whitelist flag
|
60 |
+
$action = func_get_arg(6);
|
61 |
+
$comparisonGroup = func_get_arg(7);
|
62 |
+
}
|
63 |
+
else if (func_num_args() == 9) { //Whitelist flag
|
64 |
+
$whitelist = func_get_arg(6);
|
65 |
+
$action = func_get_arg(7);
|
66 |
+
$comparisonGroup = func_get_arg(8);
|
67 |
+
}
|
68 |
+
return new self($waf, $ruleID, $type, $category, $score, $description, $whitelist, $action, $comparisonGroup);
|
69 |
}
|
70 |
|
71 |
/**
|
83 |
* @param string $category
|
84 |
* @param int $score
|
85 |
* @param string $description
|
86 |
+
* @param int $whitelist
|
87 |
* @param string $action
|
88 |
* @param wfWAFRuleComparisonGroup $comparisonGroup
|
89 |
*/
|
90 |
+
public function __construct($waf, $ruleID, $type, $category, $score, $description, $whitelist, $action, $comparisonGroup) {
|
91 |
$this->setWAF($waf);
|
92 |
$this->setRuleID($ruleID);
|
93 |
$this->setType($type);
|
94 |
$this->setCategory($category);
|
95 |
$this->setScore($score);
|
96 |
$this->setDescription($description);
|
97 |
+
$this->setWhitelist($whitelist);
|
98 |
$this->setAction($action);
|
99 |
$this->setComparisonGroup($comparisonGroup);
|
100 |
}
|
103 |
* @return string
|
104 |
*/
|
105 |
public function render() {
|
106 |
+
return sprintf('%s::create($this, %d, %s, %s, %s, %s, %d, %s, %s)', get_class($this),
|
107 |
$this->getRuleID(),
|
108 |
var_export($this->getType(), true),
|
109 |
var_export($this->getCategory(), true),
|
110 |
var_export($this->getScore(), true),
|
111 |
var_export($this->getDescription(), true),
|
112 |
+
var_export($this->getWhitelist(), true),
|
113 |
var_export($this->getAction(), true),
|
114 |
$this->getComparisonGroup()->render()
|
115 |
);
|
130 |
$this->getRuleID() ? 'id=' . (int) $this->getRuleID() : '',
|
131 |
$this->getCategory() ? 'category=' . self::exportString($this->getCategory()) : '',
|
132 |
$this->getScore() > 0 ? 'score=' . (int) $this->getScore() : '',
|
133 |
+
$this->getDescription() ? 'description=' . self::exportString($this->getDescription()) : '',
|
134 |
+
$this->getWhitelist() == 0 ? 'whitelist=0' : '',
|
135 |
)))
|
136 |
);
|
137 |
}
|
165 |
'category' => $this->getCategory(),
|
166 |
'score' => $this->getScore(),
|
167 |
'description' => $this->getDescription(),
|
168 |
+
'whitelist' => $this->getWhitelist(),
|
169 |
'action' => $this->getAction(),
|
170 |
);
|
171 |
}
|
240 |
$this->description = $description;
|
241 |
}
|
242 |
|
243 |
+
/**
|
244 |
+
* @return int
|
245 |
+
*/
|
246 |
+
public function getWhitelist() {
|
247 |
+
return $this->whitelist;
|
248 |
+
}
|
249 |
+
|
250 |
+
/**
|
251 |
+
* @param string $whitelist
|
252 |
+
*/
|
253 |
+
public function setWhitelist($whitelist) {
|
254 |
+
$this->whitelist = $whitelist;
|
255 |
+
}
|
256 |
+
|
257 |
/**
|
258 |
* @return string
|
259 |
*/
|
455 |
'lengthlessthan',
|
456 |
'currentuseris',
|
457 |
'currentuserisnot',
|
458 |
+
'md5equals',
|
459 |
);
|
460 |
|
461 |
/**
|
694 |
return !$this->currentUserIs($subject);
|
695 |
}
|
696 |
|
697 |
+
public function md5Equals($subject) {
|
698 |
+
return md5((string) $subject) === $this->getExpected();
|
699 |
+
}
|
700 |
+
|
701 |
/**
|
702 |
* @return mixed
|
703 |
*/
|
vendor/wordfence/wf-waf/src/lib/storage/file.php
CHANGED
@@ -482,7 +482,17 @@ class wfWAFStorageFile implements wfWAFStorageInterface {
|
|
482 |
return;
|
483 |
}
|
484 |
|
485 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
486 |
}
|
487 |
|
488 |
/**
|
@@ -1051,7 +1061,11 @@ class wfWAFAttackDataStorageFileEngine {
|
|
1051 |
public function truncate() {
|
1052 |
$defaultHeader = $this->getDefaultHeader();
|
1053 |
$this->close();
|
1054 |
-
|
|
|
|
|
|
|
|
|
1055 |
$this->header = array();
|
1056 |
$this->offsetTable = array();
|
1057 |
$this->open();
|
482 |
return;
|
483 |
}
|
484 |
|
485 |
+
if (WFWAF_IS_WINDOWS) {
|
486 |
+
self::lock($this->configFileHandle, LOCK_UN);
|
487 |
+
fclose($this->configFileHandle);
|
488 |
+
file_put_contents($this->getConfigFile(), self::LOG_FILE_HEADER . serialize($this->data), LOCK_EX);
|
489 |
+
} else {
|
490 |
+
wfWAFStorageFile::atomicFilePutContents($this->getConfigFile(), self::LOG_FILE_HEADER . serialize($this->data));
|
491 |
+
}
|
492 |
+
|
493 |
+
if (WFWAF_IS_WINDOWS) {
|
494 |
+
$this->configFileHandle = fopen($this->getConfigFile(), 'r+');
|
495 |
+
}
|
496 |
}
|
497 |
|
498 |
/**
|
1061 |
public function truncate() {
|
1062 |
$defaultHeader = $this->getDefaultHeader();
|
1063 |
$this->close();
|
1064 |
+
if (WFWAF_IS_WINDOWS) {
|
1065 |
+
file_put_contents($this->getFile(), $defaultHeader, LOCK_EX);
|
1066 |
+
} else {
|
1067 |
+
wfWAFStorageFile::atomicFilePutContents($this->getFile(), $defaultHeader, 'attack');
|
1068 |
+
}
|
1069 |
$this->header = array();
|
1070 |
$this->offsetTable = array();
|
1071 |
$this->open();
|
vendor/wordfence/wf-waf/src/lib/waf.php
CHANGED
@@ -763,18 +763,20 @@ HTML
|
|
763 |
* @var wfWAFRuleComparisonFailure $failedComparison
|
764 |
*/
|
765 |
$rule = $failedRule['rule'];
|
766 |
-
$
|
|
|
767 |
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
|
|
|
|
|
|
775 |
}
|
776 |
-
$this->whitelistRuleForParam($this->getRequest()->getPath(), $failedComparison->getParamKey(),
|
777 |
-
$rule->getRuleID(), $data);
|
778 |
}
|
779 |
}
|
780 |
}
|
763 |
* @var wfWAFRuleComparisonFailure $failedComparison
|
764 |
*/
|
765 |
$rule = $failedRule['rule'];
|
766 |
+
if ($rule->getWhitelist()) {
|
767 |
+
$failedComparison = $failedRule['failedComparison'];
|
768 |
|
769 |
+
$data = array(
|
770 |
+
'timestamp' => time(),
|
771 |
+
'description' => 'Whitelisted while in Learning Mode.',
|
772 |
+
'ip' => $this->getRequest()->getIP(),
|
773 |
+
);
|
774 |
+
if (function_exists('get_current_user_id')) {
|
775 |
+
$data['userID'] = get_current_user_id();
|
776 |
+
}
|
777 |
+
$this->whitelistRuleForParam($this->getRequest()->getPath(), $failedComparison->getParamKey(),
|
778 |
+
$rule->getRuleID(), $data);
|
779 |
}
|
|
|
|
|
780 |
}
|
781 |
}
|
782 |
}
|
waf/bootstrap.php
CHANGED
@@ -224,7 +224,15 @@ try {
|
|
224 |
|
225 |
if (!file_exists(wfWAF::getInstance()->getCompiledRulesFile()) || !filesize(wfWAF::getInstance()->getCompiledRulesFile())) {
|
226 |
try {
|
227 |
-
wfWAF::getInstance()->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
228 |
} catch (wfWAFBuildRulesException $e) {
|
229 |
// Log this somewhere
|
230 |
error_log($e->getMessage());
|
224 |
|
225 |
if (!file_exists(wfWAF::getInstance()->getCompiledRulesFile()) || !filesize(wfWAF::getInstance()->getCompiledRulesFile())) {
|
226 |
try {
|
227 |
+
if (is_writable(wfWAF::getInstance()->getCompiledRulesFile()) &&
|
228 |
+
wfWAF::getInstance()->getStorageEngine()->getConfig('apiKey') !== null &&
|
229 |
+
wfWAF::getInstance()->getStorageEngine()->getConfig('createInitialRulesDelay') < time()
|
230 |
+
) {
|
231 |
+
$event = new wfWAFCronFetchRulesEvent(time() - 60);
|
232 |
+
$event->setWaf(wfWAF::getInstance());
|
233 |
+
$event->fire();
|
234 |
+
wfWAF::getInstance()->getStorageEngine()->setConfig('createInitialRulesDelay', time() + (5 * 60));
|
235 |
+
}
|
236 |
} catch (wfWAFBuildRulesException $e) {
|
237 |
// Log this somewhere
|
238 |
error_log($e->getMessage());
|
wordfence.php
CHANGED
@@ -4,14 +4,14 @@ Plugin Name: Wordfence Security
|
|
4 |
Plugin URI: http://www.wordfence.com/
|
5 |
Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
|
6 |
Author: Wordfence
|
7 |
-
Version: 6.1.
|
8 |
Author URI: http://www.wordfence.com/
|
9 |
Network: true
|
10 |
*/
|
11 |
if(defined('WP_INSTALLING') && WP_INSTALLING){
|
12 |
return;
|
13 |
}
|
14 |
-
define('WORDFENCE_VERSION', '6.1.
|
15 |
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
|
16 |
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
|
17 |
|
4 |
Plugin URI: http://www.wordfence.com/
|
5 |
Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
|
6 |
Author: Wordfence
|
7 |
+
Version: 6.1.5
|
8 |
Author URI: http://www.wordfence.com/
|
9 |
Network: true
|
10 |
*/
|
11 |
if(defined('WP_INSTALLING') && WP_INSTALLING){
|
12 |
return;
|
13 |
}
|
14 |
+
define('WORDFENCE_VERSION', '6.1.5');
|
15 |
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
|
16 |
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
|
17 |
|