PluginProbe
The WP Remote WordPress Plugin / 6.72
The WP Remote WordPress Plugin v6.72
6.72 6.69 6.65 6.62 6.48 6.47 4.87 4.97 5.05 5.09 5.16 5.22 5.24 5.25 5.38 5.41 5.42 5.45 5.47 5.53 5.56 5.65 5.68 5.72 5.73 All 53 releases
wpremote / protect / lp.php

lp.php in The WP Remote WordPress Plugin 6.72, at protect/lp.php

277 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH') && !defined('MCDATAPATH')) exit;
3
4 if (!class_exists('WPRProtectLP_V672')) :
5 class WPRProtectLP_V672 {
6 private $ip;
7 private $time;
8 private $ipstore;
9 private $logger;
10 private $brand_name;
11
12 private $mode = WPRProtectLP_V672::MODE_DISABLED;
13 private $captcha_limit = 3;
14 private $temp_block_limit = 10;
15 private $block_all_limit = 100;
16 private $failed_login_gap = 1800;
17 private $success_login_gap = 1800;
18 private $all_blocked_gap = 1800;
19
20 private $category = WPRProtectLP_V672::CATEGORY_ALLOWED;
21 private $username = '';
22 private $message = '';
23
24 private static $instance;
25
26 const TABLE_NAME = 'lp_requests';
27 const UNBLOCK_IP_TRANSIENT_PREFIX = 'bvlp_unblock_ip';
28
29 const MODE_DISABLED = 1;
30 const MODE_AUDIT = 2;
31 const MODE_PROTECT = 3;
32
33 const LOGIN_STATUS_FAILURE = 1;
34 const LOGIN_STATUS_SUCCESS = 2;
35 const LOGIN_STATUS_BLOCKED = 3;
36
37 const CATEGORY_CAPTCHA_BLOCK = 1;
38 const CATEGORY_TEMP_BLOCK = 2;
39 const CATEGORY_ALL_BLOCKED = 3;
40 const CATEGORY_UNBLOCKED = 4;
41 const CATEGORY_BLACKLISTED = 5;
42 const CATEGORY_BYPASSED = 6;
43 const CATEGORY_ALLOWED = 7;
44 const CATEGORY_PRIVATEIP = 8;
45
46 private function __construct($request, $config, $brand_name) {
47 $this->ip = $request->getIP();
48 $this->brand_name = $brand_name;
49 $this->ipstore = new WPRProtectIpstore_V672();
50 $this->logger = new WPRProtectLogger_V672(WPRProtectLP_V672::TABLE_NAME);
51 $this->time = strtotime(gmdate("Y-m-d H:i:s"));
52
53 if (is_array($config)) {
54 if (array_key_exists('mode', $config) && is_int($config['mode'])) {
55 $this->mode = $config['mode'];
56 }
57
58 if (array_key_exists('captchalimit', $config) && is_int($config['captchalimit'])) {
59 $this->captcha_limit = $config['captchalimit'];
60 }
61
62 if (array_key_exists('tempblocklimit', $config) && is_int($config['tempblocklimit'])) {
63 $this->temp_block_limit = $config['tempblocklimit'];
64 }
65
66 if (array_key_exists('blockalllimit', $config) && is_int($config['blockalllimit'])) {
67 $this->block_all_limit = $config['blockalllimit'];
68 }
69
70 if (array_key_exists('failedlogingap', $config) && is_int($config['failedlogingap'])) {
71 $this->failed_login_gap = $config['failedlogingap'];
72 }
73
74 if (array_key_exists('successlogingap', $config) && is_int($config['successlogingap'])) {
75 $this->success_login_gap = $config['successlogingap'];
76 }
77
78 if (array_key_exists('allblockedgap', $config) && is_int($config['allblockedgap'])) {
79 $this->all_blocked_gap = $config['allblockedgap'];
80 }
81 }
82 }
83
84 public static function getInstance($request, $config, $brand_name) {
85 if (!isset(self::$instance)) {
86 self::$instance = new self($request, $config, $brand_name);
87 }
88
89 return self::$instance;
90 }
91
92 public static function uninstall() {
93 WPRProtect_V672::$db->dropBVTable(WPRProtectLP_V672::TABLE_NAME);
94 }
95
96 public function init() {
97 if ($this->isActive()) {
98 add_filter('authenticate', array($this, 'loginInit'), 30, 3);
99 add_action('wp_login', array($this, 'loginSuccess'));
100 add_action('wp_login_failed', array($this, 'loginFailed'));
101 }
102 }
103
104 private function getCaptchaLink() {
105 $account = WPRAccount::apiPublicAccount(WPRProtect_V672::$settings);
106
107 $url = $account->authenticatedUrl('/captcha/solve');
108 $url .= "&adminurl=".base64_encode(get_admin_url());
109
110 return $url;
111 }
112
113 private function getAllowLoginsTransient() {
114 return WPRProtect_V672::$settings->getTransient('bvlp_allow_logins');
115 }
116
117 private function getBlockLoginsTransient() {
118 return WPRProtect_V672::$settings->getTransient('bvlp_block_logins');
119 }
120
121 private function terminateTemplate() {
122 $templates = array (
123 1 => "<p>Too many failed attempts, You are barred from logging into this site.</p>" .
124 "<a href=" . esc_url($this->getCaptchaLink()) . " class='btn btn-default'>Click here</a>" .
125 " to unblock yourself.",
126 2 => "You cannot login to this site for 30 minutes because of too many failed login attempts.",
127 3 => "<p>Logins to this site are currently blocked.</p><a href=" . esc_url($this->getCaptchaLink()) .
128 " class='btn btn-default'>Click here</a> to unblock yourself.",
129 5 => "Your IP is blacklisted."
130 );
131
132 return "
133 <div style='height: 98vh;'>
134 <div style='text-align: center; padding: 10% 0; font-family: Arial, Helvetica, sans-serif;'>
135 <div><p><img src=". plugins_url('/../img/icon.png', __FILE__) . "><h2>Login Protection</h2><h3>powered by</h3><h2>"
136 . esc_html($this->brand_name) . " Firewall</h2></p><div>
137 <p>" . $templates[$this->category] . "</p>
138 <p>Reference ID: " . esc_html(WPRInfo::getRequestID()) . "</p>
139 </div>
140 </div>";
141 }
142
143 private function isProtecting() {
144 return $this->mode === WPRProtectLP_V672::MODE_PROTECT;
145 }
146
147 private function isActive() {
148 return $this->mode !== WPRProtectLP_V672::MODE_DISABLED;
149 }
150
151 private function isBlacklistedIP() {
152 return $this->ipstore->isLPIPBlacklisted($this->ip);
153 }
154
155 private function isWhitelistedIP() {
156 return $this->ipstore->isLPIPWhitelisted($this->ip);
157 }
158
159 private function isUnBlockedIP() {
160 $transient_name = WPRProtectLP_V672::UNBLOCK_IP_TRANSIENT_PREFIX . $this->ip;
161 $attempts = WPRProtect_V672::$settings->getTransient($transient_name);
162
163 if ($attempts && $attempts > 0) {
164 WPRProtect_V672::$settings->setTransient($transient_name, $attempts - 1, 600 * $attempts);
165 return true;
166 }
167
168 return false;
169 }
170
171 private function isLoginBlocked() {
172 if ($this->getAllowLoginsTransient() ||
173 ($this->getLoginCount(WPRProtectLP_V672::LOGIN_STATUS_FAILURE, null, $this->all_blocked_gap) < $this->block_all_limit)) {
174 return false;
175 }
176
177 return true;
178 }
179
180 private function log($status) {
181 $data = array (
182 "ip" => $this->ip,
183 "status" => $status,
184 "time" => $this->time,
185 "category" => $this->category,
186 "username" => $this->username,
187 "request_id" => WPRInfo::getRequestID(),
188 "message" => $this->message
189 );
190
191 $this->logger->log($data);
192 }
193
194 private function terminateLogin() {
195 $this->message = 'Login Blocked';
196 $this->log(WPRProtectLP_V672::LOGIN_STATUS_BLOCKED);
197 if ($this->isProtecting()) {
198 header("Cache-Control: no-cache, no-store, must-revalidate");
199 header("Pragma: no-cache");
200 header("Expires: 0");
201 header('HTTP/1.0 403 Forbidden');
202 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Already Escaped
203 die($this->terminateTemplate());
204 exit;
205 }
206 }
207
208 public function loginInit($user, $username = '', $password = '') {
209 if ($this->isUnBlockedIP()) {
210 $this->category = WPRProtectLP_V672::CATEGORY_UNBLOCKED;
211 } else {
212 $failed_attempts = $this->getLoginCount(WPRProtectLP_V672::LOGIN_STATUS_FAILURE,
213 $this->ip, $this->failed_login_gap);
214
215 if ($this->isWhitelistedIP()) {
216 $this->category = WPRProtectLP_V672::CATEGORY_BYPASSED;
217 } elseif (WPRProtectUtils_V672::isPrivateIP($this->ip)) {
218 $this->category = WPRProtectLP_V672::CATEGORY_PRIVATEIP;
219 } elseif ($this->isBlacklistedIP()) {
220 $this->category = WPRProtectLP_V672::CATEGORY_BLACKLISTED;
221 $this->terminateLogin();
222 } elseif ($this->isKnownLogin()) {
223 $this->category = WPRProtectLP_V672::CATEGORY_BYPASSED;
224 } elseif ($this->isLoginBlocked()) {
225 $this->category = WPRProtectLP_V672::CATEGORY_ALL_BLOCKED;
226 $this->terminateLogin();
227 } elseif ($failed_attempts >= $this->temp_block_limit) {
228 $this->category = WPRProtectLP_V672::CATEGORY_TEMP_BLOCK;
229 $this->terminateLogin();
230 } elseif ($failed_attempts >= $this->captcha_limit) {
231 $this->category = WPRProtectLP_V672::CATEGORY_CAPTCHA_BLOCK;
232 $this->terminateLogin();
233 }
234 }
235
236 if (!empty($user) && !empty($password) && is_wp_error($user)) {
237 $this->message = $user->get_error_code();
238 }
239
240 return $user;
241 }
242
243 public function loginFailed($username) {
244 $this->username = $username;
245 $this->log(WPRProtectLP_V672::LOGIN_STATUS_FAILURE);
246 }
247
248 public function loginSuccess($username) {
249 $this->username = $username;
250 $this->message = 'Login Success';
251 $this->log(WPRProtectLP_V672::LOGIN_STATUS_SUCCESS);
252 }
253
254 private function isKnownLogin() {
255 return $this->getLoginCount(WPRProtectLP_V672::LOGIN_STATUS_SUCCESS,
256 $this->ip, $this->success_login_gap) > 0;
257 }
258
259 private function getLoginCount($status, $ip, $gap) {
260 $table = WPRProtect_V672::$db->getBVTable(WPRProtectLP_V672::TABLE_NAME);
261 $query_str = "SELECT COUNT(*) as count from `$table` WHERE status=%d && time > %d";
262 $query_args = array($status, ($this->time - $gap));
263
264 $query = WPRProtect_V672::$db->prepare($query_str, $query_args);
265 if ($ip) {
266 $query .= WPRProtect_V672::$db->prepare(" && ip=%s", $ip);
267 }
268
269 $rows = WPRProtect_V672::$db->getResult($query);
270 if (!$rows) {
271 return 0;
272 }
273
274 return intval($rows[0]['count']);
275 }
276 }
277 endif;