PluginProbe
Patchstack – WordPress & Plugins Security / trunk
Patchstack – WordPress & Plugins Security vtrunk
2.3.7 trunk 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.17 2.1.18 2.1.19 2.1.2 2.1.20 2.1.21 2.1.22 2.1.23 2.1.24 2.1.25 2.1.3 2.1.4 2.1.5 2.1.6 All 49 releases
patchstack / includes / rules.php

rules.php in Patchstack – WordPress & Plugins Security trunk, at includes/rules.php

145 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // Do not allow the file to be called directly.
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * This class is used to pull the firewall/whitelist rules from our API.
10 */
11 class P_Rules extends P_Core {
12
13 /**
14 * Add the actions required to pull the rules.
15 *
16 * @param Patchstack $core
17 * @return void
18 */
19 public function __construct( $core ) {
20 parent::__construct( $core );
21 add_action( 'patchstack_post_firewall_rules', [ $this, 'post_firewall_rules' ] );
22 add_action( 'patchstack_post_dynamic_firewall_rules', [ $this, 'dynamic_firewall_rules' ] );
23 }
24
25 /**
26 * Pull the hardening .htaccess rules from the API.
27 * Then apply it to the .htaccess file after we create a backup.
28 *
29 * @return void
30 */
31 public function post_firewall_rules() {
32 if ( $this->get_option( 'patchstack_license_free', 0 ) == 1 ) {
33 return;
34 }
35
36 // Check if server is supported and if htaccess modifications are disabled.
37 if ( get_site_option( 'patchstack_disable_htaccess', 0 ) || ( defined( 'PS_DISABLE_HTACCESS' ) && PS_DISABLE_HTACCESS ) ) {
38 return;
39 }
40
41 $rules = $this->plugin->htaccess->get_firewall_rule_settings();
42 $settings = json_encode( $rules );
43 $results = $this->plugin->api->post_firewall_rule( [ 'settings' => $settings ] );
44
45 // If no rules returned (empty, or a status code/null from a failed request),
46 // we assume all settings are turned off. Guard against assigning to a string
47 // offset, which is a fatal error on PHP 7.1+.
48 if ( ! is_array( $results ) ) {
49 $results = [ 'rules' => '' ];
50 }
51
52 // We have rules so apply it to the .htaccess file.
53 if ( isset( $results['rules'] ) ) {
54 $this->plugin->htaccess->write_to_htaccess( $results['rules'] );
55 return;
56 }
57 }
58
59 /**
60 * Pull the firewall/whitelist rules from the API.
61 *
62 * @return void
63 */
64 public function dynamic_firewall_rules() {
65 if ( $this->get_option( 'patchstack_license_free', 0 ) == 1 ) {
66 return;
67 }
68
69 // Get the firewall and whitelist rules.
70 $results = $this->plugin->api->post_firewall_rule_json();
71 if ( ! isset( $results['firewall'] ) ) {
72 return;
73 }
74
75 // Separate the new firewall engine rules from the old ones.
76 $newRules = [];
77 $newRulesAP = [];
78 $oldRules = [];
79
80 // Counters for displaying purposes on the API key page.
81 $vPatchCount = 0;
82 $ruleCount = 0;
83
84 // Parse the rules.
85 foreach ( $results['firewall'] as $rule ) {
86 if ( isset( $rule['rule_v2'] ) ) {
87 $rule['rules'] = $rule['rule_v2'];
88 unset( $rule['rule_v2'] );
89
90 // Mark vPatches based on substring.
91 if ( stripos( $rule['title'], ' vulnerabilit' ) !== false && stripos( $rule['title'], 'block ' ) !== false ) {
92 $vPatchCount++;
93 } else {
94 $ruleCount++;
95 }
96
97 // Differentiate between auto prepend rules and regular ones.
98 if ( isset( $rule['ap'] ) && !empty( $rule['ap'] ) ) {
99 $newRulesAP[] = $rule;
100 } else {
101 $newRules[] = $rule;
102 }
103 } else {
104 $ruleCount++;
105 $oldRules[] = $rule;
106 }
107 }
108
109 // Update firewall rules.
110 update_option( 'patchstack_firewall_rules', json_encode( $oldRules ), true );
111 update_option( 'patchstack_firewall_rules_v3', json_encode( $newRules ), true );
112 update_option( 'patchstack_firewall_rules_v3_ap', json_encode( $newRulesAP ), true );
113
114 // Update the counters.
115 update_option( 'patchstack_vpatches_present', $vPatchCount );
116 update_option( 'patchstack_non_vpatches_present', $ruleCount );
117
118 // Separate the new firewall engine rules from the old ones. Only touch the
119 // stored whitelists when the API actually returned them, otherwise a partial
120 // response would wipe the existing whitelist rules.
121 if ( isset( $results['whitelists'] ) && is_array( $results['whitelists'] ) ) {
122 $newRules = [];
123 $oldRules = [];
124 foreach ( $results['whitelists'] as $rule ) {
125 if ( isset( $rule['rule_v2'] ) ) {
126 $rule['rules'] = $rule['rule_v2'];
127 unset( $rule['rule_v2'] );
128 $newRules[] = $rule;
129 } else {
130 $oldRules[] = $rule;
131 }
132 }
133
134 // Update whitelist rules.
135 update_option( 'patchstack_whitelist_rules', json_encode( $oldRules ), true );
136 update_option( 'patchstack_whitelist_rules_v3', json_encode( $newRules ), true );
137 }
138
139 // Update the whitelisted keys.
140 if ( isset( $results['whitelist_keys'] ) ) {
141 update_option( 'patchstack_whitelist_keys_rules', json_encode( $results['whitelist_keys'] ), true );
142 }
143 }
144 }
145