Shield Security for WordPress - Version 14.0.2

Version Description

Download this release

Release Info

Developer paultgoodchild
Plugin Icon 128x128 Shield Security for WordPress
Version 14.0.2
Comparing to
See all releases

Code changes from version 14.0.1 to 14.0.2

cl.json CHANGED
@@ -85,6 +85,30 @@
85
  "title": "Various bugs and errors",
86
  "description": [
87
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  }
89
  ]
90
  },
85
  "title": "Various bugs and errors",
86
  "description": [
87
  ]
88
+ },
89
+ {
90
+ "type": "improved",
91
+ "title": "Integration with some 3rd party membership plugins + 2FA.",
92
+ "description": [],
93
+ "patch": "14.0.2"
94
+ },
95
+ {
96
+ "type": "fixed",
97
+ "title": "Alert displayed that U2F isn't support when U2F isn't in-use.",
98
+ "description": [],
99
+ "patch": "14.0.2"
100
+ },
101
+ {
102
+ "type": "fixed",
103
+ "title": "A rare issue which Custom MFA login triggering an HTTP 402 error!",
104
+ "description": [],
105
+ "patch": "14.0.2"
106
+ },
107
+ {
108
+ "type": "fixed",
109
+ "title": "Options Search dialog failed to open (can't find-as-you-type yet).",
110
+ "description": [],
111
+ "patch": "14.0.2"
112
  }
113
  ]
114
  },
config/deprecated/user_management.php CHANGED
@@ -401,13 +401,6 @@
401
  "type": "integer",
402
  "default": 0,
403
  "transferable": false
404
- },
405
- {
406
- "key": "hard_suspended_userids",
407
- "section": "section_non_ui",
408
- "transferable": false,
409
- "type": "array",
410
- "default": []
411
  }
412
  ],
413
  "definitions": {
401
  "type": "integer",
402
  "default": 0,
403
  "transferable": false
 
 
 
 
 
 
 
404
  }
405
  ],
406
  "definitions": {
icwp-wpsf.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://shsec.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
- * Version: 14.0.1
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://shsec.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
+ * Version: 14.0.2
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
plugin-spec.php CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "properties": {
3
- "version": "14.0.1",
4
- "release_timestamp": 1644226200,
5
- "build": "202202.0701",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
1
  {
2
  "properties": {
3
+ "version": "14.0.2",
4
+ "release_timestamp": 1644423882,
5
+ "build": "202202.0902",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
plugin.json CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "properties": {
3
- "version": "14.0.1",
4
- "release_timestamp": 1644226200,
5
- "build": "202202.0701",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
1
  {
2
  "properties": {
3
+ "version": "14.0.2",
4
+ "release_timestamp": 1644423882,
5
+ "build": "202202.0902",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
readme.txt CHANGED
@@ -8,7 +8,7 @@ Requires at least: 3.7
8
  Requires PHP: 7.0
9
  Recommended PHP: 7.4
10
  Tested up to: 5.9
11
- Stable tag: 14.0.1
12
 
13
  No-Nonsense Security Hardening that protects WordPress against hackers, malicious bots, and spammers (no captchas!). Now with exclusive ShieldNET Technology.
14
 
8
  Requires PHP: 7.0
9
  Recommended PHP: 7.4
10
  Tested up to: 5.9
11
+ Stable tag: 14.0.2
12
 
13
  No-Nonsense Security Hardening that protects WordPress against hackers, malicious bots, and spammers (no captchas!). Now with exclusive ShieldNET Technology.
14
 
resources/css/plugin.css CHANGED
@@ -1741,4 +1741,7 @@ button.btn.action {
1741
 
1742
  .ui-dialog-titlebar .ui-dialog-titlebar-close {
1743
  float: right;
 
 
 
1744
  }
1741
 
1742
  .ui-dialog-titlebar .ui-dialog-titlebar-close {
1743
  float: right;
1744
+ }
1745
+ button.bs-placeholder {
1746
+ display: none;
1747
  }
resources/js/plugin.js CHANGED
@@ -369,6 +369,10 @@ jQuery( document ).ready( function () {
369
  jQuery( '.select2picker.static' ).select2( {
370
  width: 'resolve'
371
  } );
 
 
 
 
372
 
373
  jQuery( '#IpReviewSelect' ).select2( {
374
  minimumInputLength: 2,
369
  jQuery( '.select2picker.static' ).select2( {
370
  width: 'resolve'
371
  } );
372
+ jQuery( '.shield-options-search' ).selectpicker( {
373
+ title: 'Find Any Shield Option',
374
+ width: 'auto'
375
+ } );
376
 
377
  jQuery( '#IpReviewSelect' ).select2( {
378
  minimumInputLength: 2,
resources/js/shield/login2fa.js CHANGED
@@ -4,6 +4,7 @@ jQuery( document ).ready( function () {
4
  let $theForm = jQuery( 'form#loginform' );
5
  let userID = jQuery( 'input[type=hidden]#wp_user_id' ).val();
6
  let loginNonce = jQuery( 'input[type=hidden]#login_nonce' ).val();
 
7
 
8
  jQuery( 'input[type=text]:first', $theForm ).focus();
9
 
@@ -103,42 +104,42 @@ jQuery( document ).ready( function () {
103
  } );
104
  }
105
 
106
- u2fApi.isSupported()
107
- .then( function ( supported ) {
108
-
109
- let $u2fStart = jQuery( 'input#btn_u2f_start' );
110
-
111
- if ( supported ) {
112
-
113
- $u2fStart.on( 'click', function () {
114
-
115
- u2fApi.sign( JSON.parse( atob( $u2fStart.data( 'signs' ) ) ) )
116
- .then( function ( response ) {
117
- jQuery( '<input>' ).attr( {
118
- type: 'hidden',
119
- name: 'u2f_signs',
120
- value: $u2fStart.data( 'signs' )
121
- } ).appendTo( $theForm );
122
- jQuery( '<input>' ).attr( {
123
- type: 'hidden',
124
- name: $u2fStart.data( 'input_otp' ),
125
- value: JSON.stringify( response )
126
- } ).appendTo( $theForm );
127
- /** Automatically submit the form for U2F **/
128
- $theForm[ 0 ].requestSubmit();
129
- } )
130
- .catch( function ( response ) {
131
- alert( 'U2F authentication failed. Reload the page to retry.' );
132
- } );
133
- } );
134
-
135
- }
136
- else {
137
- $u2fStart.prop( 'disabled', true );
138
- $u2fStart.val( "U2F Authentication isn't supported on this browser." );
139
- alert( "U2F Authentication isn't supported on this browser." );
140
- }
141
- } )
142
- .catch();
143
 
144
  } );
4
  let $theForm = jQuery( 'form#loginform' );
5
  let userID = jQuery( 'input[type=hidden]#wp_user_id' ).val();
6
  let loginNonce = jQuery( 'input[type=hidden]#login_nonce' ).val();
7
+ let $u2fStart = jQuery( 'input#btn_u2f_start' );
8
 
9
  jQuery( 'input[type=text]:first', $theForm ).focus();
10
 
104
  } );
105
  }
106
 
107
+ if ( $u2fStart.length === 1 ) {
108
+ u2fApi.isSupported()
109
+ .then( function ( supported ) {
110
+
111
+ if ( supported ) {
112
+
113
+ $u2fStart.on( 'click', function () {
114
+
115
+ u2fApi.sign( JSON.parse( atob( $u2fStart.data( 'signs' ) ) ) )
116
+ .then( function ( response ) {
117
+ jQuery( '<input>' ).attr( {
118
+ type: 'hidden',
119
+ name: 'u2f_signs',
120
+ value: $u2fStart.data( 'signs' )
121
+ } ).appendTo( $theForm );
122
+ jQuery( '<input>' ).attr( {
123
+ type: 'hidden',
124
+ name: $u2fStart.data( 'input_otp' ),
125
+ value: JSON.stringify( response )
126
+ } ).appendTo( $theForm );
127
+ /** Automatically submit the form for U2F **/
128
+ $theForm[ 0 ].requestSubmit();
129
+ } )
130
+ .catch( function ( response ) {
131
+ alert( 'U2F authentication failed. Reload the page to retry.' );
132
+ } );
133
+ } );
134
+
135
+ }
136
+ else {
137
+ $u2fStart.prop( 'disabled', true );
138
+ $u2fStart.val( 'U2F Not Supported' );
139
+ alert( "U2F Authentication isn't supported on this web browser." );
140
+ }
141
+ } )
142
+ .catch();
143
+ }
144
 
145
  } );
resources/js/shield/notbot.js CHANGED
@@ -39,7 +39,7 @@ if ( typeof Shield_Antibot === typeof undefined && typeof shield_vars_notbotjs !
39
  sendReq();
40
  }
41
  }
42
- window.setTimeout( fire, 30000 );
43
  };
44
 
45
  /**
39
  sendReq();
40
  }
41
  }
42
+ window.setTimeout( fire, 60000 );
43
  };
44
 
45
  /**
src/lib/src/Controller/Controller.php CHANGED
@@ -460,6 +460,9 @@ class Controller extends DynPropertiesClass {
460
  ( new Ajax\Init() )
461
  ->setCon( $this )
462
  ->execute();
 
 
 
463
  }
464
 
465
  private function processShieldNonceActions() {
@@ -520,9 +523,6 @@ class Controller extends DynPropertiesClass {
520
  $this->getSiteInstallationId();
521
  $this->getAdminNotices();
522
  $this->initCrons();
523
- ( new Shield\Controller\Assets\Enqueue() )
524
- ->setCon( $this )
525
- ->execute();
526
  ( new Utilities\CaptureMyUpgrade() )
527
  ->setCon( $this )
528
  ->execute();
460
  ( new Ajax\Init() )
461
  ->setCon( $this )
462
  ->execute();
463
+ ( new Shield\Controller\Assets\Enqueue() )
464
+ ->setCon( $this )
465
+ ->execute();
466
  }
467
 
468
  private function processShieldNonceActions() {
523
  $this->getSiteInstallationId();
524
  $this->getAdminNotices();
525
  $this->initCrons();
 
 
 
526
  ( new Utilities\CaptureMyUpgrade() )
527
  ->setCon( $this )
528
  ->execute();
src/lib/src/Modules/Base/Options.php CHANGED
@@ -213,6 +213,12 @@ class Options {
213
  case 'text':
214
  $value = (string)$value;
215
  break;
 
 
 
 
 
 
216
  default:
217
  break;
218
  }
213
  case 'text':
214
  $value = (string)$value;
215
  break;
216
+ case 'array':
217
+ case 'multiple_select':
218
+ if ( !is_array( $value ) ) {
219
+ $value = (array)$value;
220
+ }
221
+ break;
222
  default:
223
  break;
224
  }
src/lib/src/Modules/IPs/Lib/Bots/NotBot/NotBotHandler.php CHANGED
@@ -8,7 +8,7 @@ use FernleafSystems\Wordpress\Services\Services;
8
 
9
  class NotBotHandler extends ExecOnceModConsumer {
10
 
11
- const LIFETIME = 120;
12
  const SLUG = 'notbot';
13
 
14
  private $useCookies;
@@ -57,12 +57,12 @@ class NotBotHandler extends ExecOnceModConsumer {
57
 
58
  public function registerAsNotBot() :bool {
59
  if ( $this->useCookies ) {
60
- $ts = Services::Request()->ts() +
61
- apply_filters( 'shield/notbot_cookie_life', self::LIFETIME );
62
  Services::Response()->cookieSet(
63
  $this->getMod()->prefix( self::SLUG ),
64
  sprintf( '%sz%s', $ts, $this->getHashForVisitorTS( $ts ) ),
65
- self::LIFETIME
66
  );
67
  }
68
  $this->getCon()->fireEvent( 'bottrack_notbot' );
8
 
9
  class NotBotHandler extends ExecOnceModConsumer {
10
 
11
+ const LIFETIME = 300;
12
  const SLUG = 'notbot';
13
 
14
  private $useCookies;
57
 
58
  public function registerAsNotBot() :bool {
59
  if ( $this->useCookies ) {
60
+ $cookieLife = apply_filters( 'shield/notbot_cookie_life', self::LIFETIME );
61
+ $ts = Services::Request()->ts() + $cookieLife;
62
  Services::Response()->cookieSet(
63
  $this->getMod()->prefix( self::SLUG ),
64
  sprintf( '%sz%s', $ts, $this->getHashForVisitorTS( $ts ) ),
65
+ $cookieLife
66
  );
67
  }
68
  $this->getCon()->fireEvent( 'bottrack_notbot' );
src/lib/src/Modules/Insights/Lib/SideMenuBuilder.php CHANGED
@@ -224,8 +224,8 @@ class SideMenuBuilder {
224
  'body' => __( 'Use Search to find any option within the entire plugin' ),
225
  ],
226
  'data' => [
227
- 'toggle' => 'modal',
228
- 'target' => '#SearchDialog',
229
  ],
230
  ];
231
  }
224
  'body' => __( 'Use Search to find any option within the entire plugin' ),
225
  ],
226
  'data' => [
227
+ 'bs-toggle' => 'modal',
228
+ 'bs-target' => '#SearchDialog',
229
  ],
230
  ];
231
  }
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentRequestCapture.php CHANGED
@@ -17,7 +17,8 @@ use FernleafSystems\Wordpress\Services\Services;
17
  class LoginIntentRequestCapture extends Shield\Modules\Base\Common\ExecOnceModConsumer {
18
 
19
  protected function canRun() :bool {
20
- return $this->getCon()->getShieldAction() === 'wp_login_2fa_verify'
 
21
  && !Services::WpUsers()->isUserLoggedIn();
22
  }
23
 
@@ -69,7 +70,7 @@ class LoginIntentRequestCapture extends Shield\Modules\Base\Common\ExecOnceModCo
69
  $pageRender->setMod( $mod )
70
  ->setWpUser( $user );
71
  $pageRender->login_nonce = $req->request( 'login_nonce', false, '' );
72
- $pageRender->redirect_to = $req->request( 'redirect_to', false, $req->getPath() );
73
  $pageRender->rememberme = $req->request( 'rememberme' );
74
  $pageRender->msg_error = __( 'Could not verify your 2FA codes', 'wp-simple-firewall' );
75
  $pageRender->render(); // die();
17
  class LoginIntentRequestCapture extends Shield\Modules\Base\Common\ExecOnceModConsumer {
18
 
19
  protected function canRun() :bool {
20
+ return Services::Request()->isPost()
21
+ && $this->getCon()->getShieldAction() === 'wp_login_2fa_verify'
22
  && !Services::WpUsers()->isUserLoggedIn();
23
  }
24
 
70
  $pageRender->setMod( $mod )
71
  ->setWpUser( $user );
72
  $pageRender->login_nonce = $req->request( 'login_nonce', false, '' );
73
+ $pageRender->redirect_to = $req->request( 'redirect_to', false, '' );
74
  $pageRender->rememberme = $req->request( 'rememberme' );
75
  $pageRender->msg_error = __( 'Could not verify your 2FA codes', 'wp-simple-firewall' );
76
  $pageRender->render(); // die();
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/LoginRequestCapture.php CHANGED
@@ -55,7 +55,7 @@ class LoginRequestCapture extends Shield\Modules\Base\Common\ExecOnceModConsumer
55
  ->setWpUser( $user );
56
  $pageRender->login_nonce = $loginNonce;
57
  $pageRender->interim_login = $req->request( 'interim-login' );
58
- $pageRender->redirect_to = $req->request( 'redirect_to', false, $req->getPath() );
59
  $pageRender->rememberme = $req->request( 'rememberme' );
60
  $pageRender->render(); // die();
61
  }
55
  ->setWpUser( $user );
56
  $pageRender->login_nonce = $loginNonce;
57
  $pageRender->interim_login = $req->request( 'interim-login' );
58
+ $pageRender->redirect_to = $req->request( 'redirect_to', false, '' );
59
  $pageRender->rememberme = $req->request( 'rememberme' );
60
  $pageRender->render(); // die();
61
  }
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/MfaController.php CHANGED
@@ -16,7 +16,7 @@ class MfaController extends Shield\Modules\Base\Common\ExecOnceModConsumer {
16
  private $providers;
17
 
18
  protected function run() {
19
- add_action( 'init', [ $this, 'onWpInit' ] ); // Login Intent handling
20
  add_action( 'wp_loaded', [ $this, 'onWpLoaded' ] ); // Profile handling
21
  add_filter( 'login_message', [ $this, 'onLoginMessage' ], 11 );
22
  }
16
  private $providers;
17
 
18
  protected function run() {
19
+ add_action( 'init', [ $this, 'onWpInit' ], 9 ); // Login Intent handling
20
  add_action( 'wp_loaded', [ $this, 'onWpLoaded' ] ); // Profile handling
21
  add_filter( 'login_message', [ $this, 'onLoginMessage' ], 11 );
22
  }
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Render/RenderBase.php CHANGED
@@ -95,13 +95,13 @@ abstract class RenderBase {
95
  if ( !empty( $referQuery ) ) {
96
  parse_str( $referQuery, $referQueryItems );
97
  if ( !empty( $referQueryItems[ 'redirect_to' ] ) ) {
98
- $redirectTo = esc_url( $referQueryItems[ 'redirect_to' ] );
99
  }
100
  }
101
- }
102
 
103
- if ( !empty( $redirectTo ) ) {
104
- $redirectTo = esc_url( $this->redirect_to );
 
105
  }
106
 
107
  $cancelHref = $req->post( 'cancel_href', '' );
@@ -117,6 +117,11 @@ abstract class RenderBase {
117
  'rememberme' => esc_attr( $this->rememberme ),
118
  'redirect_to' => esc_attr( esc_url( $redirectTo ) ),
119
  'cancel_href' => esc_attr( esc_url( $cancelHref ) ),
 
 
 
 
 
120
  ] );
121
  $fields[ 'wp_user_id' ] = $this->getWpUser()->ID;
122
  return $fields;
95
  if ( !empty( $referQuery ) ) {
96
  parse_str( $referQuery, $referQueryItems );
97
  if ( !empty( $referQueryItems[ 'redirect_to' ] ) ) {
98
+ $redirectTo = $referQueryItems[ 'redirect_to' ];
99
  }
100
  }
 
101
 
102
+ if ( empty( $redirectTo ) ) {
103
+ $redirectTo = $req->getPath();
104
+ }
105
  }
106
 
107
  $cancelHref = $req->post( 'cancel_href', '' );
117
  'rememberme' => esc_attr( $this->rememberme ),
118
  'redirect_to' => esc_attr( esc_url( $redirectTo ) ),
119
  'cancel_href' => esc_attr( esc_url( $cancelHref ) ),
120
+ /**
121
+ * This server produced HTTP 402 error if the request to the login form didn't include wp-submit
122
+ * https://secure.helpscout.net/conversation/1781553925/1153
123
+ */
124
+ 'wp-submit' => 'Complete Login',
125
  ] );
126
  $fields[ 'wp_user_id' ] = $this->getWpUser()->ID;
127
  return $fields;
templates/twig/components/search/dialog.twig CHANGED
@@ -1,7 +1,7 @@
1
  <div class="modal fade"
2
  role="dialog"
3
  id="SearchDialog"
4
- tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"
5
  >
6
  <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
7
  <div class="modal-content">
1
  <div class="modal fade"
2
  role="dialog"
3
  id="SearchDialog"
4
+ tabindex="-1" aria-labelledby="ShieldOptionsSearch" aria-hidden="true"
5
  >
6
  <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
7
  <div class="modal-content">
templates/twig/components/search/options.twig CHANGED
@@ -1,8 +1,8 @@
1
  {% if vars.search_select is defined %}
2
- <select class="selectpicker" data-live-search="true"
3
- title="Search For Plugin Option"
4
  data-size="10"
5
- data-header=""
6
  onchange="location = this.value;"
7
  style="max-width: 100%; width: 100%"
8
  >
1
  {% if vars.search_select is defined %}
2
+ <select class="shield-options-search" data-live-search="true"
3
+ title="Search for options"
4
  data-size="10"
5
+ data-header="Search for options"
6
  onchange="location = this.value;"
7
  style="max-width: 100%; width: 100%"
8
  >
templates/twig/components/wplogin_replica/login_body.twig CHANGED
@@ -17,10 +17,12 @@
17
  {{ provider|raw }}
18
  {% endfor %}
19
 
20
- <p style="margin-bottom: 18px">
21
- <input type="checkbox" value="Y" name="skip_mfa" id="skip_mfa" />
22
- {{ strings.skip_mfa }}
23
- </p>
 
 
24
 
25
  <p>
26
  <input type="submit" name="wp-submit"
17
  {{ provider|raw }}
18
  {% endfor %}
19
 
20
+ {% if flags.can_skip_mfa %}
21
+ <p style="margin-bottom: 18px">
22
+ <input type="checkbox" value="Y" name="skip_mfa" id="skip_mfa" />
23
+ {{ strings.skip_mfa }}
24
+ </p>
25
+ {% endif %}
26
 
27
  <p>
28
  <input type="submit" name="wp-submit"