PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 3.1.0
Defender Security – Malware Scanner, Login Security & Firewall v3.1.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / component / blacklist-lockout.php

blacklist-lockout.php in Defender Security – Malware Scanner, Login Security & Firewall 3.1.0, at src/component/blacklist-lockout.php

379 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WP_Defender\Component;
4
5 use WP_Defender\Component;
6 use WP_Defender\Integrations\MaxMind_Geolocation;
7 use WP_Defender\Model\Setting\Blacklist_Lockout as Model_Blacklist_Lockout;
8
9 class Blacklist_Lockout extends Component {
10 use \WP_Defender\Traits\Country;
11 use \WP_Defender\Traits\IP;
12
13 /**
14 * Queue hooks when this class init.
15 */
16 public function add_hooks() {
17 add_filter( 'defender_ip_lockout_assets', array( &$this, 'output_scripts_data' ) );
18 }
19
20 /**
21 * @param array $data
22 *
23 * @return mixed
24 * @throws \MaxMind\Db\Reader\InvalidDatabaseException
25 */
26 public function output_scripts_data( $data ) {
27 $model = new Model_Blacklist_Lockout();
28 $user_ip = $this->get_user_ip();
29 $exist_geodb = $this->is_geodb_downloaded();
30 // If MaxMind GeoIP DB is downloaded then display the required data.
31 if ( $exist_geodb ) {
32 $current_country = $this->get_current_country( $user_ip );
33 $current_country = $current_country['iso'] ?? false;
34 $country_list = $this->countries_list();
35 $blacklist_countries = array_merge( array( 'all' => __( 'Block all', 'wpdef' ) ), $country_list );
36 $whitelist_countries = array_merge( array( 'all' => __( 'Allow all', 'wpdef' ) ), $country_list );
37 } else {
38 $current_country = false;
39 $blacklist_countries = array();
40 $whitelist_countries = array();
41 }
42 $data['blacklist'] = array(
43 'model' => $model->export(),
44 'summary' => array(
45 'day' => 0,
46 ),
47 'misc' => array(
48 'geo_db_downloaded' => $exist_geodb,
49 'current_country' => $current_country,
50 'blacklist_countries' => $blacklist_countries,
51 'whitelist_countries' => $whitelist_countries,
52 'user_ip' => $user_ip,
53 ),
54 'class' => Model_Blacklist_Lockout::class,
55 );
56
57 return $data;
58 }
59
60 /**
61 * @param string $ip
62 *
63 * @return bool
64 */
65 public function is_country_whitelist( $ip ) {
66 // Check Firewall > IP Banning > Locations section is activated or not.
67 $country = $this->get_current_country( $ip );
68 if ( false === $country ) {
69 return false;
70 }
71 $model = new Model_Blacklist_Lockout();
72 $whitelist = $model->get_country_whitelist();
73 if ( empty( $whitelist ) ) {
74 return false;
75 }
76 if ( ! empty( $country['iso'] ) && in_array( strtoupper( $country['iso'] ), $whitelist, true ) ) {
77 return true;
78 }
79
80 return false;
81 }
82
83 /**
84 * Return the default ips need to whitelisted, e.g. HUB ips.
85 *
86 * @return array
87 */
88 private function get_default_ip_whitelisted() {
89 $ips = array(
90 '18.204.159.253',
91 '54.227.51.40',
92 '18.219.56.14',
93 '45.55.78.242',
94 '35.171.56.101',
95 '192.241.140.159',
96 '104.236.132.222',
97 '192.241.148.185',
98 '34.196.51.17',
99 '35.157.144.199',
100 '159.89.254.12',
101 '127.0.0.1',
102 array_key_exists( 'SERVER_ADDR', $_SERVER )
103 ? $_SERVER['SERVER_ADDR']
104 : ( $_SERVER['LOCAL_ADDR'] ?? null ),
105 );
106
107 return apply_filters( 'ip_lockout_default_whitelist_ip', $ips );
108 }
109
110 /**
111 * @param string $ip
112 * @param array $arr_ips
113 *
114 * @return bool
115 */
116 private function is_ip_in_format( $ip, $arr_ips ) {
117 foreach ( $arr_ips as $wip ) {
118 if ( false === strpos( $wip, '-' ) && false === strpos( $wip, '/' ) && trim( $wip ) === $ip ) {
119 return true;
120 } elseif ( false !== strpos( $wip, '-' ) ) {
121 $ips = explode( '-', $wip );
122 if ( $this->compare_in_range( $ip, $ips[0], $ips[1] ) ) {
123 return true;
124 }
125 } elseif ( false !== strpos( $wip, '/' ) && $this->compare_cidr( $ip, $wip ) ) {
126 return true;
127 }
128 }
129
130 return false;
131 }
132
133 /**
134 * Is IP on Whitelist?
135 *
136 * @param string $ip
137 *
138 * @return bool
139 */
140 public function is_ip_whitelisted( $ip ) {
141 if ( in_array( $ip, $this->get_default_ip_whitelisted(), true ) ) {
142 return true;
143 }
144
145 $blacklist_settings = new Model_Blacklist_Lockout();
146
147 return $this->is_ip_in_format( $ip, $blacklist_settings->get_list( 'allowlist' ) );
148 }
149
150 /**
151 * Is IP on Blocklist?
152 *
153 * @param string $ip
154 *
155 * @return bool
156 */
157 public function is_blacklist( $ip ) {
158 $blacklist_settings = new Model_Blacklist_Lockout();
159
160 return $this->is_ip_in_format( $ip, $blacklist_settings->get_list( 'blocklist' ) );
161 }
162
163 /**
164 * Is country on Blacklist?
165 *
166 * @param string $ip
167 *
168 * @return bool
169 */
170 public function is_country_blacklist( $ip ) {
171 // Check Firewall > IP Banning > Locations section is activated or not.
172 $country = $this->get_current_country( $ip );
173 if ( false === $country ) {
174 return false;
175 }
176 $blacklist_settings = new Model_Blacklist_Lockout();
177 $blacklisted = $blacklist_settings->get_country_blacklist();
178 if ( empty( $blacklisted ) ) {
179 return false;
180 }
181 if ( in_array( 'all', $blacklisted, true ) ) {
182 return true;
183 }
184 if ( ! empty( $country['iso'] ) && in_array( strtoupper( $country['iso'] ), $blacklisted, true ) ) {
185 return true;
186 }
187
188 return false;
189 }
190
191 /**
192 * Validate import file is in right format and usable for IP Lockout.
193 *
194 * @param $file
195 *
196 * @return array|bool
197 */
198 public function verify_import_file( $file ) {
199 $fp = fopen( $file, 'r' );
200 $data = array();
201 while ( ( $line = fgetcsv( $fp ) ) !== false ) { //phpcs:ignore
202 if ( 2 !== count( $line ) ) {
203 return false;
204 }
205
206 if ( ! in_array( $line[1], array( 'allowlist', 'blocklist' ), true ) ) {
207 return false;
208 }
209
210 if ( false === $this->validate_ip( $line[0] ) ) {
211 continue;
212 }
213
214 $data[] = $line;
215 }
216 fclose( $fp );
217
218 return $data;
219 }
220
221 /**
222 * @param Model_Blacklist_Lockout $model
223 * @param string $country_iso
224 *
225 * @return object
226 * @since 2.8.0
227 */
228 public function add_default_whitelisted_country( Model_Blacklist_Lockout $model, $country_iso ) {
229 if ( empty( $model->country_whitelist ) ) {
230 $model->country_whitelist[] = $country_iso;
231 } elseif ( ! in_array( $country_iso, $model->country_whitelist, true ) ) {
232 $model->country_whitelist[] = $country_iso;
233 }
234
235 return $model;
236 }
237
238 /**
239 * Like download_geodb.
240 */
241 public function download_geo_ip() {
242 $url = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz';
243 if ( ! function_exists( 'download_url' ) ) {
244 require_once ABSPATH . 'wp-admin/includes/file.php';
245 }
246 $this->download_by_url( $url );
247 }
248
249 /**
250 * @param string $url
251 *
252 * @return bool
253 */
254 public function download_by_url( $url ) {
255 $tmp = download_url( $url );
256 if ( ! is_wp_error( $tmp ) ) {
257 $phar = new \PharData( $tmp );
258 $path = $this->get_tmp_path() . DIRECTORY_SEPARATOR . 'maxmind';
259 if ( ! is_dir( $path ) ) {
260 wp_mkdir_p( $path );
261 }
262 $phar->extractTo( $path, null, true );
263 $model = new Model_Blacklist_Lockout();
264 $service_geo = wd_di()->get( MaxMind_Geolocation::class );
265 $model->geodb_path = $path . DIRECTORY_SEPARATOR . $phar->current()->getFileName() . DIRECTORY_SEPARATOR . $service_geo->get_db_full_name();
266
267 if ( file_exists( $tmp ) ) {
268 unlink( $tmp );
269 }
270
271 if ( empty( $model->country_whitelist ) ) {
272 $country = $this->get_current_country( $this->get_user_ip() );
273 if ( false === $country ) {
274 return false;
275 }
276 if ( ! empty( $country['iso'] ) ) {
277 $model = $this->add_default_whitelisted_country( $model, $country['iso'] );
278 }
279 }
280 $model->save();
281
282 return true;
283 }
284
285 return false;
286 }
287
288 /**
289 * @param string $license_key
290 *
291 * @return bool|string|\WP_Error
292 */
293 public function get_maxmind_downloaded_url( $license_key ) {
294 $url = "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=$license_key&suffix=tar.gz";
295 if ( ! function_exists( 'download_url' ) ) {
296 require_once ABSPATH . 'wp-admin/includes/file.php';
297 }
298
299 return download_url( $url );
300 }
301
302 /**
303 * Check downloaded GeoDB.
304 *
305 * @return bool
306 */
307 public function is_geodb_downloaded() {
308 $model = new Model_Blacklist_Lockout();
309 // Likely the case after the config import with existed MaxMind license key.
310 if (
311 ! empty( $model->maxmind_license_key )
312 && ( is_null( $model->geodb_path ) || ! is_file( $model->geodb_path ) )
313 ) {
314 $service_geo = wd_di()->get( MaxMind_Geolocation::class );
315 $tmp = $service_geo->get_downloaded_url( $model->maxmind_license_key );
316 if ( ! is_wp_error( $tmp ) ) {
317 $phar = new \PharData( $tmp );
318 $path = $this->get_tmp_path() . DIRECTORY_SEPARATOR . 'maxmind';
319 if ( ! is_dir( $path ) ) {
320 wp_mkdir_p( $path );
321 }
322 $phar->extractTo( $path, null, true );
323 $model->geodb_path = $path . DIRECTORY_SEPARATOR . $phar->current()->getFileName() . DIRECTORY_SEPARATOR . $service_geo->get_db_full_name();
324 // Save because we'll check for a saved path.
325 $model->save();
326
327 if ( file_exists( $tmp ) ) {
328 unlink( $tmp );
329 }
330
331 if ( empty( $model->country_whitelist ) ) {
332 $country = $this->get_current_country( $this->get_user_ip() );
333 if ( false === $country ) {
334 return false;
335 }
336 if ( ! empty( $country['iso'] ) ) {
337 $model = $this->add_default_whitelisted_country( $model, $country['iso'] );
338 }
339 }
340 $model->save();
341 }
342 }
343
344 // Check again.
345 if ( is_null( $model->geodb_path ) || ! is_file( $model->geodb_path ) ) {
346 return false;
347 }
348
349 // Check if the file exists on the site. The file can exist on the same server but for different sites.
350 // For example, after config importing.
351 $path_parts = pathinfo( $model->geodb_path );
352 if ( preg_match( '/(\/wp-content\/.+)/', $path_parts['dirname'], $matches ) ) {
353 $rel_path = $matches[1];
354 $rel_path = ltrim( $rel_path, '/' );
355 $abs_path = ABSPATH . $rel_path;
356 if ( ! is_dir( $abs_path ) ) {
357 wp_mkdir_p( $abs_path );
358 }
359
360 $rel_path = $abs_path . DIRECTORY_SEPARATOR . $path_parts['basename'];
361 if ( file_exists( $rel_path ) ) {
362 return true;
363 } elseif ( ! empty( $model->geodb_path ) && file_exists( $model->geodb_path ) ) {
364 // The case if ABSPATH was changed e.g. in wp-config.php.
365 return true;
366 }
367
368 if ( move_uploaded_file( $model->geodb_path, $rel_path ) ) {
369 $model->geodb_path = $rel_path;
370 $model->save();
371 } else {
372 return false;
373 }
374 }
375
376 return true;
377 }
378 }
379