PluginProbe ʕ •ᴥ•ʔ
Advanced Access Manager – Access Governance for WordPress / trunk
Advanced Access Manager – Access Governance for WordPress vtrunk
6.8.4 6.8.5 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13 6.9.14 6.9.15 6.9.16 6.9.17 6.9.18 6.9.19 6.9.2 6.9.20 6.9.21 6.9.22 6.9.23 6.9.24 6.9.25 6.9.26 6.9.27 6.9.28 6.9.29 6.9.3 6.9.30 6.9.31 6.9.32 6.9.33 6.9.34 6.9.35 6.9.36 6.9.37 6.9.38 6.9.39 6.9.4 6.9.41 6.9.42 6.9.43 6.9.44 6.9.45 6.9.46 6.9.47 6.9.48 6.9.49 6.9.5 6.9.51 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.0-alpha.6 7.0.0-alpha.7 7.0.0-beta.1 7.0.0-rc1 7.0.0-rc2 7.0.0-rc3 7.0.1 7.0.10 7.0.11 7.0.2 7.0.3 7.0.4 7.0.5 7.0.6 7.0.7 7.0.8 7.0.9 7.1.0 7.1.1 trunk 3.0 4.0 4.0.1 4.1 4.2 4.3 4.4 4.4.1 4.5 4.6 4.6.1 4.6.2 4.7 4.7.1 4.7.2 4.7.5 4.7.6 4.8 4.8.1 4.9 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.5.1 4.9.5.2 5.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1 5.1.1 5.10 5.11 5.2 5.2.1 5.2.5 5.2.6 5.2.7 5.3 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.4 5.4.1 5.4.2 5.4.3 5.4.3.1 5.4.3.2 5.5 5.5.1 5.5.2 5.6 5.6.1 5.6.1.1 5.7 5.7.1 5.7.2 5.7.3 5.8 5.8.1 5.8.2 5.8.3 5.9 5.9.1 5.9.1.1 5.9.2 5.9.2.1 5.9.3 5.9.4 5.9.5 5.9.6 5.9.6.1 5.9.6.2 5.9.6.3 5.9.7 5.9.7.1 5.9.7.2 5.9.7.3 5.9.8 5.9.8.1 5.9.9 5.9.9.1 6.0.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.1.0 6.1.1 6.2.0 6.2.1 6.2.2 6.3.0 6.3.1 6.3.2 6.3.3 6.4.0 6.4.1 6.4.2 6.4.3 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.6.0 6.6.1 6.6.2 6.6.3 6.6.4 6.7.0 6.7.1 6.7.2 6.7.3 6.7.4 6.7.5 6.7.6 6.7.7 6.7.8 6.7.9 6.8.0 6.8.1 6.8.2 6.8.3
advanced-access-manager / application / Restful / SecurityAudit.php
advanced-access-manager / application / Restful Last commit date
AccessDeniedRedirect.php 1 year ago AdminToolbar.php 1 year ago ApiRoute.php 1 year ago BackendMenu.php 1 year ago BackwardCompatibility.php 1 year ago Capability.php 1 year ago Configs.php 5 months ago Content.php 1 year ago Identity.php 1 year ago Jwt.php 5 months ago LoginRedirect.php 1 year ago LogoutRedirect.php 1 year ago Metabox.php 1 year ago Mu.php 1 year ago NotFoundRedirect.php 1 year ago Policies.php 1 year ago Roles.php 1 year ago SecureLogin.php 1 year ago SecurityAudit.php 1 year ago ServiceTrait.php 1 year ago Settings.php 1 year ago Urls.php 1 year ago Users.php 1 year ago Widgets.php 1 year ago
SecurityAudit.php
353 lines
1 <?php
2
3 /**
4 * ======================================================================
5 * LICENSE: This file is subject to the terms and conditions defined in *
6 * file 'license.txt', which is part of this source code package. *
7 * ======================================================================
8 */
9
10 /**
11 * RESTful API for the security audit service
12 *
13 * @package AAM
14 * @version 7.0.0
15 */
16 class AAM_Restful_SecurityAudit
17 {
18
19 use AAM_Restful_ServiceTrait;
20
21 /**
22 * Necessary permissions to access endpoint
23 *
24 * @version 7.0.0
25 */
26 const PERMISSIONS = [
27 'aam_manager',
28 'aam_trigger_audit'
29 ];
30
31 /**
32 * Single instance of itself
33 *
34 * @var AAM_Restful_SecurityAudit
35 *
36 * @access private
37 * @static
38 *
39 * @version 7.0.0
40 */
41 private static $_instance = null;
42
43 /**
44 * Constructor
45 *
46 * @return void
47 * @access protected
48 *
49 * @version 7.0.0
50 */
51 protected function __construct()
52 {
53 // Register API endpoint
54 add_action('rest_api_init', function() {
55 // Create new support message
56 $this->_register_route('/audit', [
57 'methods' => WP_REST_Server::CREATABLE,
58 'callback' => array($this, 'run_step'),
59 'args' => array(
60 'step' => array(
61 'description' => 'Security audit step',
62 'type' => 'string',
63 'required' => true
64 ),
65 'reset' => [
66 'description' => 'Wether reset already existing results or not',
67 'type' => 'boolean',
68 'default' => false
69 ]
70 )
71 ], self::PERMISSIONS, false);
72
73 // Get complete report
74 $this->_register_route('/audit/report', [
75 'methods' => WP_REST_Server::READABLE,
76 'callback' => array($this, 'generate_report')
77 ], self::PERMISSIONS, false);
78
79 // Share complete report
80 $this->_register_route('/audit/summary', [
81 'methods' => WP_REST_Server::READABLE,
82 'callback' => array($this, 'prepare_summary')
83 ], self::PERMISSIONS, false);
84 });
85 }
86
87 /**
88 * Run the current step
89 *
90 * @param WP_REST_Request $request
91 *
92 * @return WP_REST_Response
93 * @access public
94 *
95 * @version 7.0.0
96 */
97 public function run_step(WP_REST_Request $request)
98 {
99 try {
100 $response = AAM_Service_SecurityAudit::get_instance()->execute(
101 $request->get_param('step'),
102 $request->get_param('reset')
103 );
104 } catch (Exception $ex) {
105 $response = $this->_prepare_error_response($ex);
106 }
107
108 return rest_ensure_response($response);
109 }
110
111 /**
112 * Generate report
113 *
114 * @param WP_REST_Request $request
115 *
116 * @return WP_REST_Response
117 * @access public
118 *
119 * @version 7.0.0
120 */
121 public function generate_report(WP_REST_Request $request)
122 {
123 try {
124 $report_type = $request->get_header('accept');
125
126 if ($report_type === 'text/csv') {
127 header('Content-Type: text/csv; charset=utf-8');
128
129 $this->_generate_csv_report();
130
131 $response = new WP_REST_Response(null, 200);
132 } else {
133 $response = rest_ensure_response($this->_generate_json_report());
134 }
135
136 } catch (Exception $ex) {
137 $response = rest_ensure_response($this->_prepare_error_response($ex));
138 }
139
140 return $response;
141 }
142
143 /**
144 * Prepare executive audit summary
145 *
146 * @return WP_REST_Response
147 * @access public
148 *
149 * @version 7.0.0
150 */
151 public function prepare_summary()
152 {
153 $repository = AAM_Addon_Repository::get_instance();
154
155 // Step #1. Prepare the audit report
156 $payload = json_encode([
157 'license' => $repository->get_premium_license_key(),
158 'instance' => wp_hash('aam', 'nonce'),
159 'report' => $this->_generate_shareable_results()
160 ]);
161
162 // Step #2. Upload the report
163 $result = wp_remote_post('https://api.aamportal.com/audit/summary', [
164 'body' => $payload,
165 'timeout' => 30,
166 'data_format' => 'body',
167 'headers' => [
168 'Content-Type' => 'application/json'
169 ]
170 ]);
171
172 // Get HTTP code
173 $http_code = wp_remote_retrieve_response_code($result);
174
175 // Check for errors in the response. This is hard error handling
176 if (is_wp_error($result)) {
177 throw new RuntimeException(esc_js($result->get_error_message()));
178 }
179
180 // Get the response from the server
181 $result = json_decode(wp_remote_retrieve_body($result), true);
182
183 // Store the copy of the executive summary, but only if success
184 if ($http_code === 200) {
185 AAM::api()->db->write(
186 AAM_Service_SecurityAudit::DB_SUMMARY_OPTION,
187 $result,
188 false
189 );
190 }
191
192 // Prepare the response to UI
193 $response = [
194 'status'=> $http_code == 200 ? 'success' : 'failure'
195 ];
196
197 if ($http_code === 200) {
198 $response['results'] = $result;
199 } elseif (!empty($result['reason'])) {
200 $response['reason'] = $result['reason'];
201 } else {
202 $response['reason'] = __(
203 'Hm, something went wrong. Please try again later.',
204 'advanced-access-manager'
205 );
206 }
207
208 return rest_ensure_response($response);
209 }
210
211 /**
212 * Generate CSV version of the report
213 *
214 * @return void
215 * @access private
216 *
217 * @version 7.0.0
218 */
219 private function _generate_csv_report()
220 {
221 $service = AAM_Service_SecurityAudit::get_instance();
222
223 // Open output buffer for CSV content & set header
224 $report = fopen('php://output', 'w');
225 fputcsv($report, [ 'Issue', 'Type', 'Category' ]);
226
227 $data = $service->read();
228 $checks = $service->get_steps();
229
230 foreach($data as $check_id => $check_result) {
231 $check = $checks[$check_id];
232 $executor = $checks[$check_id]['executor'];
233
234 if (!empty($check_result['issues'])) {
235 foreach($check_result['issues'] as $issue) {
236 fputcsv($report, [
237 call_user_func("{$executor}::issue_to_message", $issue),
238 $issue['type'],
239 isset($check['category']) ? $check['category'] : $check_id
240 ]);
241 }
242 }
243 }
244
245 // Close output buffer
246 fclose($report);
247 }
248
249 /**
250 * Prepare shareable audit results
251 *
252 * Aggregating data and removing unnecessary information
253 *
254 * @return array
255 * @access private
256 *
257 * @version 7.0.0
258 */
259 private function _generate_shareable_results()
260 {
261 $results = [];
262 $service = AAM_Service_SecurityAudit::get_instance();
263 $checks = $service->get_steps();
264
265 foreach($service->read() as $check => $data) {
266 if (!empty($data['is_completed']) && !empty($data['issues'])) {
267 $executor = $checks[$check]['executor'];
268 $shareable = call_user_func(
269 "{$executor}::issues_to_shareable", $data
270 );
271
272 if (!empty($shareable)) {
273 $results[$check] = $shareable;
274 }
275 }
276 }
277
278 return [
279 'results' => $results,
280 'plugins' => $this->_get_plugin_list()
281 ];
282 }
283
284 /**
285 * Get list of all installed plugins
286 *
287 * @return array
288 * @access private
289 *
290 * @version 7.0.0
291 */
292 private function _get_plugin_list()
293 {
294 if (!function_exists('get_plugins')) {
295 require_once(ABSPATH . 'wp-admin/includes/plugin.php');
296 }
297
298 // Get all installed plugins
299 $plugins = get_plugins();
300
301 // Initialize an array to store the plugin information
302 $result = [];
303
304 // Loop through each plugin and check its status
305 foreach ($plugins as $plugin_path => $plugin) {
306 $result[] = [
307 'name' => $plugin['Name'],
308 'version' => $plugin['Version'],
309 'is_active' => is_plugin_active($plugin_path),
310 'plugin_path' => $plugin_path
311 ];
312 }
313
314 return $result;
315 }
316
317 /**
318 * Generate JSON version of the report
319 *
320 * @return string
321 * @access private
322 *
323 * @version 7.0.0
324 */
325 private function _generate_json_report()
326 {
327 $report = [];
328 $service = AAM_Service_SecurityAudit::get_instance();
329 $data = $service->read();
330 $checks = $service->get_steps();
331
332 foreach($data as $check_id => $check_result) {
333 $check = $checks[$check_id];
334 $exec = $checks[$check_id]['executor'];
335
336 if (!empty($check_result['issues'])) {
337 foreach($check_result['issues'] as $issue) {
338 $msg = call_user_func("{$exec}::issue_to_message", $issue);
339 $cat = isset($check['category']) ? $check['category'] : $check_id;
340
341 array_push($report, [
342 'issue' => $msg,
343 'type' => $issue['type'],
344 'category' => $cat
345 ]);
346 }
347 }
348 }
349
350 return $report;
351 }
352
353 }