PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 3.0.1
Defender Security – Malware Scanner, Login Security & Firewall v3.0.1
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 / controller / firewall-logs.php

firewall-logs.php in Defender Security – Malware Scanner, Login Security & Firewall 3.0.1, at src/controller/firewall-logs.php

614 lines 15.2 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\Controller;
4
5 use Calotes\Component\Request;
6 use Calotes\Component\Response;
7 use Calotes\Helper\HTTP;
8 use Valitron\Validator;
9 use WP_Defender\Component\Table_Lockout;
10 use WP_Defender\Controller;
11 use WP_Defender\Model\Lockout_Log;
12 use WP_Defender\Model\Setting\Blacklist_Lockout;
13 use WP_Defender\Model\Setting\User_Agent_Lockout;
14 use WP_Defender\Traits\Formats;
15 use WP_Defender\Component\User_Agent;
16
17 class Firewall_Logs extends Controller {
18 use Formats;
19
20 /**
21 * @var string
22 */
23 protected $slug = 'wdf-ip-lockout';
24
25 public function __construct() {
26 $this->register_routes();
27 add_action( 'defender_enqueue_assets', array( &$this, 'enqueue_assets' ) );
28 }
29
30 /**
31 * @param Request $request
32 *
33 * @return Response
34 * @throws \Exception
35 * @defender_route
36 */
37 public function bulk( Request $request ) {
38 $data = $request->get_data(
39 array(
40 'action' => array(
41 'type' => 'string',
42 'sanitize' => 'sanitize_text_field',
43 ),
44 'ids' => array(
45 'type' => 'array',
46 ),
47 )
48 );
49 $ids = $data['ids'];
50 $ips = array();
51 if ( is_array($ids) || $ids instanceof \Countable ? count( $ids ) : 0 ) {
52 foreach ( $ids as $id ) {
53 $model = Lockout_Log::find_by_id( $id );
54 if ( is_object( $model ) ) {
55 $bl = wd_di()->get( Blacklist_Lockout::class );
56 switch ( $data['action'] ) {
57 case 'ban':
58 $bl->remove_from_list( $model->ip, 'allowlist' );
59 $bl->add_to_list( $model->ip, 'blocklist' );
60 $ips[ $model->ip ] = $model->ip;
61 break;
62 case 'allowlist':
63 $bl->remove_from_list( $model->ip, 'blocklist' );
64 $bl->add_to_list( $model->ip, 'allowlist' );
65 $ips[ $model->ip ] = $model->ip;
66 break;
67 case 'delete':
68 $ips[ $model->ip ] = $model->ip;
69 $model->delete();
70 break;
71 default:
72 break;
73 }
74 }
75 }
76 }
77
78 switch ( $data['action'] ) {
79 case 'allowlist':
80 $messages = sprintf(
81 /* translators: ... */
82 __(
83 'IP %1$s has been added to your allowlist. You can control your allowlist in <a href="%2$s">IP Lockouts.</a>',
84 'wpdef'
85 ),
86 implode( ', ', $ips ),
87 network_admin_url( 'admin.php?page=wdf-ip-lockout&view=blocklist' )
88 );
89 break;
90 case 'ban':
91 $messages = sprintf(
92 /* translators: ... */
93 __(
94 'IP %1$s has been added to your blocklist You can control your blocklist in <a href="%2$s">IP Lockouts.</a>',
95 'wpdef'
96 ),
97 implode( ', ', $ips ),
98 network_admin_url( 'admin.php?page=wdf-ip-lockout&view=blocklist' )
99 );
100 break;
101 case 'delete':
102 $messages = sprintf(
103 /* translators: ... */
104 __( 'IP %s has been deleted', 'wpdef' ),
105 implode( ', ', $ips )
106 );
107 break;
108
109 }
110
111 return new Response(
112 true,
113 array(
114 'message' => $messages,
115 )
116 );
117 }
118
119 /**
120 * @param Request $request
121 *
122 * @return Response
123 * @throws \Exception
124 * @defender_route
125 */
126 public function export_as_csv( Request $request ) {
127 $filters = array(
128 'from' => strtotime( 'midnight', strtotime( HTTP::get( 'date_from', strtotime( '-7 days midnight' ) ) ) ),
129 'to' => strtotime( 'tomorrow', strtotime( HTTP::get( 'date_to', strtotime( 'tomorrow' ) ) ) ),
130 'type' => HTTP::get( 'term', '' ),
131 'ip' => HTTP::get( 'ip', '' ),
132 'ban_status' => HTTP::get( 'ban_status', '' ),
133 );
134
135 if ( 'all' === $filters['type'] ) {
136 $filters['type'] = '';
137 }
138
139 if ( 'all' === $filters['ban_status'] ) {
140 $filters['ban_status'] = '';
141 }
142
143 // User can export the number of logs that are set.
144 $per_page = isset( $_GET['per_page'] ) ? sanitize_text_field( $_GET['per_page'] ) : 20;
145
146 if ( -1 === (int) $per_page ) {
147 $per_page = false;
148 }
149
150 $paged = isset( $_GET['paged'] ) ? sanitize_text_field( $_GET['paged'] ) : 1;
151 $logs = Lockout_Log::query_logs( $filters, $paged, 'date', 'desc', $per_page );
152
153 $tl_component = new Table_Lockout();
154
155 $ua_component = wd_di()->get( User_Agent::class );
156
157 $filename = 'wdf-lockout-logs-export-' . gmdate( 'ymdHis' ) . '.csv';
158
159 header( 'Expires: 0' );
160 header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
161 header( 'Cache-Control: private', false );
162 header( 'Content-Type: application/octet-stream' );
163 header( 'Content-Disposition: attachment; filename="' . $filename . '";' );
164 header( 'Content-Transfer-Encoding: binary' );
165
166 extension_loaded( 'zlib' ) ? ob_start( 'ob_gzhandler' ) : ob_start();
167
168 $fp = fopen( 'php://output', 'w' );
169 $headers = array(
170 __( 'Log', 'wpdef' ),
171 __( 'Date / Time', 'wpdef' ),
172 __( 'Type', 'wpdef' ),
173 __( 'IP address', 'wpdef' ),
174 __( 'IP Status', 'wpdef' ),
175 __( 'User Agent Status', 'wpdef' ),
176 );
177 fputcsv( $fp, $headers );
178
179 $flush_limit = Lockout_Log::INFINITE_SCROLL_SIZE;
180 foreach ( $logs as $key => $log ) {
181 $item = array(
182 $log->log,
183 $this->get_date( $log->date ),
184 $tl_component->get_type( $log->type ),
185 $log->ip,
186 $tl_component->get_ip_status_text( $log->ip ),
187 $ua_component->get_status_text( $log->type, $log->tried ),
188 );
189 fputcsv( $fp, $item );
190
191 if ( 0 === $key % $flush_limit ) {
192 ob_flush();
193 flush();
194 }
195 }
196
197 fclose( $fp );
198 exit();
199 }
200
201 /**
202 * Get formatted date.
203 *
204 * @param $date
205 *
206 * @return string
207 */
208 public function get_date( $date ) {
209 if ( strtotime( '-24 hours' ) > $date ) {
210 return $this->format_date_time( gmdate( 'Y-m-d H:i:s', $date ) );
211 } else {
212 return human_time_diff( $date, time() ) . ' ' . __( 'ago', 'wpdef' ); // phpcs:ignore
213 }
214 }
215
216 /**
217 * @param Request $request
218 *
219 * @return Response
220 * @throws \Exception
221 * @defender_route
222 */
223 public function toggle_ip_to_list( Request $request ) {
224 $data = $request->get_data(
225 array(
226 'ip' => array(
227 'type' => 'string',
228 'sanitize' => 'sanitize_text_field',
229 ),
230 'list' => array(
231 'type' => 'string',
232 'sanitize' => 'sanitize_text_field',
233 ),
234 'ban_status' => array(
235 'type' => 'string',
236 'sanitize' => 'sanitize_text_field',
237 ),
238 )
239 );
240
241 $ip = $data['ip'];
242 $list = $data['list'];
243
244 $model = wd_di()->get( Blacklist_Lockout::class );
245 if ( $model->is_ip_in_list( $ip, $list ) ) {
246 $model->remove_from_list( $ip, $list );
247 /* translators: ... */
248 $message = __(
249 'IP %1$s has been removed from your %2$s You can control your %3$s in <a href="%4$s">IP Lockouts.</a>',
250 'wpdef'
251 );
252 } else {
253 $model->add_to_list( $ip, $list );
254 /* translators: ... */
255 $message = __(
256 'IP %1$s has been added to your %2$s You can control your %3$s in <a href="%4$s">IP Lockouts.</a>',
257 'wpdef'
258 );
259 }
260 $filter_data = $request->get_data(
261 array(
262 'date_from' => array(
263 'type' => 'string',
264 'sanitize' => 'sanitize_text_field',
265 ),
266 'date_to' => array(
267 'type' => 'string',
268 'sanitize' => 'sanitize_text_field',
269 ),
270 'ip_filter' => array(
271 'type' => 'string',
272 'sanitize' => 'sanitize_text_field',
273 ),
274 'type' => array(
275 'type' => 'string',
276 'sanitize' => 'sanitize_text_field',
277 ),
278 'paged' => array(
279 'type' => 'int',
280 'sanitize' => 'sanitize_text_field',
281 ),
282 'per_page' => array(
283 'type' => 'int',
284 'sanitize' => 'sanitize_text_field',
285 ),
286 )
287 );
288 $logs = Lockout_Log::get_logs_and_format(
289 array(
290 'from' => strtotime( $filter_data['date_from'] . ' 00:00:00' ),
291 'to' => strtotime( $filter_data['date_to'] . ' 23:59:59' ),
292 'ip' => $filter_data['ip_filter'],
293 // If this is all, then we set to null to exclude it from the filter.
294 'type' => 'all' === $filter_data['type'] ? '' : $filter_data['type'],
295 ),
296 $filter_data['paged'],
297 'id',
298 'desc',
299 $filter_data['per_page']
300 );
301
302 return new Response(
303 true,
304 array(
305 'message' => sprintf(
306 $message,
307 $data['ip'],
308 $data['list'],
309 $data['list'],
310 network_admin_url( 'admin.php?page=wdf-ip-lockout&view=blocklist' )
311 ),
312 'logs' => $logs,
313 )
314 );
315 }
316
317 /**
318 * @param Request $request
319 *
320 * @return Response
321 * @throws \Exception
322 * @defender_route
323 */
324 public function toggle_ua_to_list( Request $request ) {
325 $data = $request->get_data(
326 array(
327 'ua' => array(
328 'type' => 'string',
329 'sanitize' => 'sanitize_text_field',
330 ),
331 'list' => array(
332 'type' => 'string',
333 'sanitize' => 'sanitize_text_field',
334 ),
335 'scenario' => array(
336 'type' => 'string',
337 'sanitize' => 'sanitize_text_field',
338 ),
339 )
340 );
341
342 $ua = $data['ua'];
343 $list = $data['list'];
344 $action = $data['scenario'];
345 $model = wd_di()->get( User_Agent_Lockout::class );
346
347 if ( 'remove' === $action && $model->is_ua_in_list( $ua, $list ) ) {
348 $model->remove_from_list( $ua, $list );
349 /* translators: ... */
350 $message = __(
351 'User agent <strong>%1$s</strong> has been removed from your %2$s You can control your %3$s in <a href="%4$s">User Agent Banning.</a>',
352 'wpdef'
353 );
354 } elseif ( 'add' === $action && ! $model->is_ua_in_list( $ua, $list ) ) {
355 $model->add_to_list( $ua, $list );
356 /* translators: ... */
357 $message = __(
358 'User agent <strong>%1$s</strong> has been added to your %2$s You can control your %3$s in <a href="%4$s">User Agent Banning.</a>',
359 'wpdef'
360 );
361 } else {
362 return new Response(
363 false,
364 array(
365 'message' => __( 'Wrong result.', 'wpdef' ),
366 )
367 );
368 }
369
370 $filter_data = $request->get_data(
371 array(
372 'date_from' => array(
373 'type' => 'string',
374 'sanitize' => 'sanitize_text_field',
375 ),
376 'date_to' => array(
377 'type' => 'string',
378 'sanitize' => 'sanitize_text_field',
379 ),
380 'ip_filter' => array(
381 'type' => 'string',
382 'sanitize' => 'sanitize_text_field',
383 ),
384 'type' => array(
385 'type' => 'string',
386 'sanitize' => 'sanitize_text_field',
387 ),
388 'paged' => array(
389 'type' => 'int',
390 'sanitize' => 'sanitize_text_field',
391 ),
392 'per_page' => array(
393 'type' => 'int',
394 'sanitize' => 'sanitize_text_field',
395 ),
396 )
397 );
398 $logs = Lockout_Log::get_logs_and_format(
399 array(
400 'from' => strtotime( $filter_data['date_from'] . ' 00:00:00' ),
401 'to' => strtotime( $filter_data['date_to'] . ' 23:59:59' ),
402 'ip' => $filter_data['ip_filter'],
403 // If this is all, then we set to null to exclude it from the filter.
404 'type' => 'all' === $filter_data['type'] ? '' : $filter_data['type'],
405 ),
406 $filter_data['paged'],
407 'id',
408 'desc',
409 $filter_data['per_page']
410 );
411
412 return new Response(
413 true,
414 array(
415 'message' => sprintf(
416 $message,
417 $data['ua'],
418 $data['list'],
419 $data['list'],
420 network_admin_url( 'admin.php?page=wdf-ip-lockout&view=ua-lockout' )
421 ),
422 'logs' => $logs,
423 )
424 );
425 }
426
427 /**
428 * Query the logs and display on frontend.
429 *
430 * @param Request $request
431 *
432 * @return Response
433 * @defender_route
434 */
435 public function query_logs( Request $request ) {
436 $data = $request->get_data(
437 array(
438 'date_from' => array(
439 'type' => 'string',
440 'sanitize' => 'sanitize_text_field',
441 ),
442 'date_to' => array(
443 'type' => 'string',
444 'sanitize' => 'sanitize_text_field',
445 ),
446 'ip' => array(
447 'type' => 'string',
448 'sanitize' => 'sanitize_text_field',
449 ),
450 'type' => array(
451 'type' => 'string',
452 'sanitize' => 'sanitize_text_field',
453 ),
454 'paged' => array(
455 'type' => 'int',
456 'sanitize' => 'sanitize_text_field',
457 ),
458 'sort' => array(
459 'type' => 'string',
460 'sanitize' => 'sanitize_text_field',
461 ),
462 'ban_status' => array(
463 'type' => 'string',
464 'sanitize' => 'sanitize_text_field',
465 ),
466 )
467 );
468
469 // Validate.
470 $v = new Validator( $data, array() );
471 $v->rule( 'required', array( 'date_from', 'date_to' ) );
472 $v->rule( 'date', array( 'date_from', 'date_to' ) );
473 if ( ! $v->validate() ) {
474 return new Response(
475 false,
476 array(
477 'message' => __( 'Wrong start and end date', 'wpdef' ),
478 )
479 );
480 }
481 $sort = $data['sort'] ?? Table_Lockout::SORT_DESC;
482 switch ( $sort ) {
483 case 'ip':
484 $order = 'desc';
485 $order_by = 'ip';
486 break;
487 case 'oldest':
488 $order = 'asc';
489 $order_by = 'id';
490 break;
491 case 'user_agent':
492 $order = 'asc';
493 $order_by = 'user_agent';
494 break;
495 default:
496 $order = 'desc';
497 $order_by = 'id';
498 break;
499 }
500 $data = $this->retrieve_logs(
501 array(
502 'from' => strtotime( $data['date_from'] . ' 00:00:00' ),
503 'to' => strtotime( $data['date_to'] . ' 23:59:59' ),
504 'ip' => $data['ip'],
505 // If this is all, then we set to null to exclude it from the filter.
506 'type' => 'all' === $data['type'] ? '' : $data['type'],
507 'ban_status' => 'all' === $data['ban_status'] ? '' : $data['ban_status'],
508 ),
509 $data['paged'],
510 $order,
511 $order_by
512 );
513
514 return new Response(
515 true,
516 $data
517 );
518 }
519
520 public function enqueue_assets() {
521 if ( ! $this->is_page_active() ) {
522 return;
523 }
524 wp_enqueue_script( 'def-momentjs', defender_asset_url( '/assets/js/vendor/moment/moment.min.js' ) );
525 wp_enqueue_script(
526 'def-daterangepicker',
527 defender_asset_url( '/assets/js/vendor/daterangepicker/daterangepicker.js' )
528 );
529 wp_localize_script(
530 'def-iplockout',
531 'lockout_logs',
532 array_merge( $this->data_frontend(), $this->dump_routes_and_nonces() )
533 );
534 }
535
536 /**
537 * All the variables that we will show on frontend, both in the main page, or dashboard widget.
538 *
539 * @return array
540 */
541 public function data_frontend() {
542 $def_filters = array( 'misc' => wd_di()->get( Table_Lockout::class )->get_filters() );
543 $init_filters = array(
544 'from' => strtotime( '-30 days' ),
545 'to' => time(),
546 'type' => '',
547 'ip' => '',
548 'ban_status' => '',
549 );
550
551 return array_merge( $this->retrieve_logs( $init_filters, 1 ), $def_filters );
552 }
553
554 /**
555 * @param array $filters
556 * @param int $paged
557 * @param string $order
558 * @param string $order_by
559 *
560 * @return array
561 */
562 private function retrieve_logs( $filters, $paged = 1, $order = 'desc', $order_by = 'id' ) {
563 // User can set the number of logs to retrieve per page.
564 $per_page = isset( $_POST['per_page'] ) && 0 !== (int) $_POST['per_page']
565 ? sanitize_text_field( $_POST['per_page'] )
566 : 20;
567
568 $conditions = array( 'ban_status' => $filters['ban_status'] );
569
570 $count = Lockout_Log::count( $filters['from'], $filters['to'], $filters['type'], $filters['ip'], $conditions );
571 $logs = Lockout_Log::get_logs_and_format( $filters, $paged, $order_by, $order, $per_page );
572
573 if( -1 === (int) $per_page ) {
574 $per_page = Lockout_Log::INFINITE_SCROLL_SIZE;
575 }
576
577 return array(
578 'count' => $count,
579 'logs' => $logs,
580 'per_page' => $per_page,
581 'total_pages' => ceil( $count / $per_page ),
582 );
583 }
584
585 /**
586 * Export the data of this module, we will use this for export to HUB, create a preset etc.
587 */
588 public function to_array() {}
589
590 /**
591 * Import the data of other source into this, it can be when HUB trigger the import, or user apply a preset.
592 *
593 * @param array $data
594 */
595 public function import_data( $data ) {}
596
597 /**
598 * Remove all settings, configs generated in this container runtime.
599 */
600 public function remove_settings() {}
601
602 /**
603 * Remove all data.
604 */
605 public function remove_data() {}
606
607 /**
608 * @return array
609 */
610 public function export_strings() {
611 return array();
612 }
613 }
614