PluginProbe ʕ •ᴥ•ʔ
Really Simple Security – Simple and Performant Security (formerly Really Simple SSL) / 9.5.10
Really Simple Security – Simple and Performant Security (formerly Really Simple SSL) v9.5.10
9.5.11 9.5.10.1 9.5.10 trunk 9.4.0 9.4.1 9.4.2 9.4.3 9.5.0 9.5.0.1 9.5.0.2 9.5.1 9.5.2 9.5.2.2 9.5.2.3 9.5.3 9.5.3.1 9.5.3.2 9.5.4 9.5.5 9.5.6 9.5.7 9.5.8 9.5.9
really-simple-ssl / system-status.php
really-simple-ssl Last commit date
assets 1 month ago core 1 month ago languages 1 month ago lets-encrypt 1 month ago lib 1 month ago mailer 1 month ago modal 1 month ago placeholders 1 month ago progress 1 month ago security 1 month ago settings 1 month ago testssl 1 month ago upgrade 1 month ago .wp-env.json 1 month ago SECURITY.md 1 month ago class-admin.php 1 month ago class-cache.php 1 month ago class-certificate.php 1 month ago class-front-end.php 1 month ago class-installer.php 1 month ago class-mixed-content-fixer.php 1 month ago class-multisite.php 1 month ago class-server.php 1 month ago class-site-health.php 1 month ago class-wp-cli.php 1 month ago compatibility.php 1 month ago force-deactivate.txt 1 month ago functions.php 1 month ago index.php 1 month ago readme.txt 1 month ago rector.php 1 month ago rlrsssl-really-simple-ssl.php 1 month ago rsssl-auto-loader.php 1 month ago sbom.json.gz 1 month ago ssl-test-page.php 1 month ago system-status.php 1 month ago uninstall.php 1 month ago upgrade.php 1 month ago
system-status.php
558 lines
1 <?php
2 # No need for the template engine
3 if ( ! defined( 'WP_USE_THEMES' ) ) {
4 define( 'WP_USE_THEMES', false ); // phpcs:ignore
5 }
6 //we set wp admin to true, so the backend features get loaded.
7 if ( ! defined( 'RSSSL_DOING_SYSTEM_STATUS' ) ) {
8 define( 'RSSSL_DOING_SYSTEM_STATUS', true ); // phpcs:ignore
9 }
10
11 #find the base path
12 if ( ! defined( 'BASE_PATH' ) ) {
13 define( 'BASE_PATH', rsssl_find_wordpress_base_path() . '/' );
14 }
15
16 # Load WordPress Core
17 if ( ! file_exists( BASE_PATH . 'wp-load.php' ) ) {
18 die( 'WordPress not installed here' );
19 }
20 require_once BASE_PATH . 'wp-load.php';
21 require_once ABSPATH . 'wp-includes/class-phpass.php';
22 require_once ABSPATH . 'wp-admin/includes/image.php';
23 require_once ABSPATH . 'wp-admin/includes/plugin.php';
24
25 //by deleting these we make sure these functions run again
26 delete_transient( 'rsssl_testpage' );
27 function rsssl_get_system_status() {
28 $output = '';
29 global $wp_version;
30
31 $output .= "General\n";
32 $output .= 'Domain: ' . site_url() . "\n";
33 $output .= 'Plugin version: ' . rsssl_version . "\n";
34 $output .= 'WordPress version: ' . $wp_version . "\n";
35
36 if ( RSSSL()->certificate->is_valid() ) {
37 $output .= "SSL certificate is valid\n";
38 } else {
39 if ( ! function_exists( 'stream_context_get_params' ) ) {
40 $output .= "stream_context_get_params not available\n";
41 } elseif ( RSSSL()->certificate->detection_failed() ) {
42 $output .= "Not able to detect certificate\n";
43 } else {
44 $output .= "Invalid SSL certificate\n";
45 }
46 }
47
48 $output .= ( rsssl_get_option( 'ssl_enabled' ) ) ? "SSL is enabled\n\n"
49 : "SSL is not yet enabled\n\n";
50
51 $output .= "Options\n";
52 if ( rsssl_get_option( 'mixed_content_fixer' ) ) {
53 $output .= "* Mixed content fixer\n";
54 }
55 $output .= '* WordPress redirect' . rsssl_get_option( 'redirect' ) . "\n";
56
57 if ( rsssl_get_option( 'switch_mixed_content_fixer_hook' ) ) {
58 $output .= "* Use alternative method to fix mixed content\n";
59 }
60 if ( rsssl_get_option( 'dismiss_all_notices' ) ) {
61 $output .= "* Dismiss all Really Simple Security notices\n";
62 }
63 $output .= "\n";
64
65 $output .= "Server information:\n";
66 $output .= 'Server: ' . RSSSL()->server->get_server() . "\n";
67 $output .= 'SSL Type: ' . RSSSL()->admin->ssl_type . "\n";
68
69 if ( function_exists( 'phpversion' ) ) {
70 $output .= 'PHP Version: ' . phpversion() . "\n\n";
71 }
72
73 if ( is_multisite() ) {
74 $output .= "MULTISITE\n";
75 }
76
77 if ( rsssl_is_networkwide_active() ) {
78 $output .= "Really Simple Security network wide activated\n";
79 } elseif ( is_multisite() ) {
80 $output .= "Really Simple Security per site activated\n";
81 }
82
83 $output .= 'SSL Configuration:' . "\n";
84 $domain = RSSSL()->certificate->get_domain();
85 $certinfo = RSSSL()->certificate->get_certinfo( $domain );
86 if ( ! $certinfo ) {
87 $output .= 'SSL certificate not valid' . "\n";
88 }
89
90 $domain_valid = RSSSL()->certificate->is_domain_valid( $certinfo, $domain );
91 if ( ! $domain_valid ) {
92 $output .= "Domain on certificate does not match website's domain" . "\n";
93 }
94
95 $date_valid = RSSSL()->certificate->is_date_valid( $certinfo );
96 if ( ! $date_valid ) {
97 $output .= 'Date on certificate expired or not valid' . "\n";
98 }
99 $filecontents = get_transient( 'rsssl_testpage' );
100 if ( strpos( $filecontents, '#SSL TEST PAGE#' ) !== false ) {
101 $output .= 'SSL test page loaded successfully' . "\n";
102 } else {
103 $output .= 'Could not open testpage' . "\n";
104 }
105 if ( RSSSL()->admin->wpconfig_siteurl_not_fixed ) {
106 $output .= 'siteurl or home url defines found in wp-config.php' . "\n";
107 }
108 if ( RSSSL()->admin->wpconfig_siteurl_not_fixed ) {
109 $output .= 'not able to fix wpconfig siteurl/homeurl.' . "\n";
110 }
111
112 if ( ! is_writable( rsssl_find_wp_config_path() ) ) {
113 $output .= 'wp-config.php not writable<br>';
114 }
115 $output .= 'Detected SSL setup: ' . RSSSL()->admin->ssl_type . "\n";
116 if ( file_exists( RSSSL()->admin->htaccess_file() ) ) {
117 $output .= 'htaccess file exists.' . "\n";
118 if ( ! is_writable( RSSSL()->admin->htaccess_file() ) ) {
119 $output .= 'htaccess file not writable.' . "\n";
120 }
121 } else {
122 $output .= 'no htaccess file available.' . "\n";
123 }
124
125 if ( get_transient( 'rsssl_htaccess_test_success' ) === 'success' ) {
126 $output .= 'htaccess redirect tested successfully.' . "\n";
127 } elseif ( get_transient( 'rsssl_htaccess_test_success' ) === 'error' ) {
128 $output .= 'htaccess redirect test failed.' . "\n";
129 } elseif ( get_transient( 'rsssl_htaccess_test_success' ) === 'no-response' ) {
130 $output .= 'htaccess redirect test failed: no response from server.' . "\n";
131 }
132 $mixed_content_fixer_detected = get_transient( 'rsssl_mixed_content_fixer_detected' );
133 if ( 'no-response' === $mixed_content_fixer_detected ) {
134 $output .= 'Could not connect to webpage to detect mixed content fixer' . "\n";
135 }
136 if ( 'not-found' === $mixed_content_fixer_detected ) {
137 $output .= 'Mixed content marker not found in websource' . "\n";
138 }
139 if ( 'error' === $mixed_content_fixer_detected ) {
140 $output .= 'Mixed content marker not found: unknown error' . "\n";
141 }
142 if ( 'curl-error' === $mixed_content_fixer_detected ) {
143 //Site has has a cURL error
144 $output .= 'Mixed content fixer could not be detected: cURL error' . "\n";
145 }
146 if ( 'found' === $mixed_content_fixer_detected ) {
147 $output .= 'Mixed content fixer successfully detected' . "\n";
148 }
149 if ( ! rsssl_get_option( 'mixed_content_fixer' ) ) {
150 $output .= 'Mixed content fixer not enabled' . "\n";
151 }
152 if ( ! RSSSL()->admin->htaccess_contains_redirect_rules() ) {
153 $output .= '.htaccess does not contain default Really Simple Security redirect.' . "\n";
154 }
155
156 $output .= "\nConstants\n";
157
158 if ( defined( 'RSSSL_FORCE_ACTIVATE' ) ) {
159 $output .= "RSSSL_FORCE_ACTIVATE defined\n";
160 }
161 if ( defined( 'RSSSL_NO_FLUSH' ) ) {
162 $output .= "RSSSL_NO_FLUSH defined\n";
163 }
164 if ( defined( 'RSSSL_DISMISS_ACTIVATE_SSL_NOTICE' ) ) {
165 $output .= "RSSSL_DISMISS_ACTIVATE_SSL_NOTICE defined\n";
166 }
167 if ( defined( 'RSSSL_SAFE_MODE' ) ) {
168 $output .= "RSSSL_SAFE_MODE defined\n";
169 }
170 if ( defined( 'RSSSL_SERVER_OVERRIDE' ) ) {
171 $output .= "RSSSL_SERVER_OVERRIDE defined\n";
172 }
173 if ( defined( 'rsssl_no_rest_api_redirect' ) ) {
174 $output .= "rsssl_no_rest_api_redirect defined\n";
175 }
176 if ( defined( 'rsssl_no_wp_redirect' ) ) {
177 $output .= "rsssl_no_wp_redirect defined\n";
178 }
179 if ( defined( 'RSSSL_CONTENT_FIXER_ON_INIT' ) ) {
180 $output .= "RSSSL_CONTENT_FIXER_ON_INIT defined\n";
181 }
182 if ( defined( 'FORCE_SSL_ADMIN' ) ) {
183 $output .= "FORCE_SSL_ADMIN defined\n";
184 }
185 if ( defined( 'RSSSL_CSP_MAX_REQUESTS' ) ) {
186 $output .= "RSSSL_CSP_MAX_REQUESTS defined\n";
187 }
188 if ( defined( 'RSSSL_DISABLE_CHANGE_LOGIN_URL' ) ) {
189 $output .= "RSSSL_DISABLE_CHANGE_LOGIN_URL defined\n";
190 }
191 if ( defined( 'RSSSL_LEARNING_MODE' ) ) {
192 $output .= "RSSSL_LEARNING_MODE defined\n";
193 }
194 if ( defined( 'RSSSL_DEACTIVATING_ALTERNATE' ) ) {
195 $output .= "RSSSL_DEACTIVATING_ALTERNATE defined\n";
196 }
197 if ( defined( 'RSSSL_UPGRADING_TO_PRO' ) ) {
198 $output .= "RSSSL_UPGRADING_TO_PRO defined\n";
199 }
200
201 if ( ! defined( 'RSSSL_FORCE_ACTIVATE' )
202 && ! defined( 'RSSSL_NO_FLUSH' )
203 && ! defined( 'RSSSL_DISMISS_ACTIVATE_SSL_NOTICE' )
204 && ! defined( 'RSSSL_SAFE_MODE' )
205 && ! defined( 'RSSSL_SERVER_OVERRIDE' )
206 && ! defined( 'rsssl_no_rest_api_redirect' )
207 && ! defined( 'rsssl_no_wp_redirect' )
208 && ! defined( 'RSSSL_CONTENT_FIXER_ON_INIT' )
209 && ! defined( 'FORCE_SSL_ADMIN' )
210 && ! defined( 'RSSSL_CSP_MAX_REQUESTS' )
211 && ! defined( 'RSSSL_DISABLE_CHANGE_LOGIN_URL' )
212 && ! defined( 'RSSSL_LEARNING_MODE' )
213 && ! defined( 'RSSSL_DEACTIVATING_ALTERNATE' )
214 && ! defined( 'RSSSL_UPGRADING_TO_PRO' )
215 ) {
216 $output .= "No constants defined\n";
217 }
218
219 $output .= "\n";
220
221 $output .= "rsssl_options:\n";
222
223 if ( is_multisite() && rsssl_is_networkwide_active() ) {
224 $stored_options = get_site_option( 'rsssl_options', [] );
225 } else {
226 $stored_options = get_option( 'rsssl_options', [] );
227 }
228
229 unset($stored_options['permissions_policy']);
230 unset($stored_options['upgrade_insecure_requests']);
231 unset($stored_options['x_xss_protection']);
232 unset($stored_options['x_content_type_options']);
233 unset($stored_options['x_frame_options']);
234 unset($stored_options['referrer_policy']);
235 unset($stored_options['content_security_policy']);
236 unset($stored_options['xmlrpc_status_lm_enabled_once']);
237 unset($stored_options['csp_status_lm_enabled_once']);
238 unset($stored_options['csp_frame_ancestors_urls']);
239 unset($stored_options['file_change_exclusions']);
240 unset($stored_options['license']);
241 unset($stored_options['cross_origin_opener_policy']);
242 unset($stored_options['cross_origin_resource_policy']);
243 unset($stored_options['cross_origin_embedder_policy']);
244
245
246 $output .= print_r( $stored_options, true ) . "\n\n";
247
248 $output .= "Installed plugins:\n";
249 $output .= rsssl_system_status_get_installed_plugins() . "\n\n";
250
251 if ( rsssl_get_option( 'enable_firewall' ) == 1 ) {
252 $output .= "Blocked regions firewall: \n";
253 $output .= rsssl_system_status_get_blocked_countries_firewall() . "\n\n";
254
255 $output .= "Whitelist firewall: \n";
256 $output .= rsssl_system_status_get_whitelist() . "\n\n";
257
258 $output .= "Blocked IPs firewall: \n";
259 $output .= rsssl_system_status_get_blocked_ips() . "\n\n";
260 }
261
262 if ( rsssl_get_option("enable_limited_login_attempts") == 1 ) {
263 $output .= "Blocked regions LLA: \n";
264 $output .= rsssl_system_status_get_blocked_countries_lla() . "\n\n";
265
266 $output .= "Blocked users LLA: \n";
267 $output .= rsssl_system_status_get_blocked_users_lla() . "\n\n";
268
269 $output .= "Blocked ips LLA: \n";
270 $output .= rsssl_system_status_get_blocked_ips_lla() . "\n\n";
271 }
272
273 if ( rsssl_get_option( 'login_protection_enabled' ) == 1 ) {
274 $output .= "Users with 2FA enabled: \n";
275 $output .= rsssl_system_status_get_2fa_users() . "\n\n";
276 }
277
278 return $output;
279 }
280
281 if ( rsssl_user_can_manage() && isset( $_GET['download'] ) ) {
282 $rsssl_content = rsssl_get_system_status();
283 $rsssl_fsize = function_exists( 'mb_strlen' ) ? mb_strlen( $rsssl_content, '8bit' ) : strlen( $rsssl_content );
284 $rsssl_file_name = 'really-simple-ssl-system-status.txt';
285
286 //direct download
287 header( 'Content-type: application/octet-stream' );
288 header( 'Content-Disposition: attachment; filename="' . $rsssl_file_name . '"' );
289 //open in browser
290 //header("Content-Disposition: inline; filename=\"".$file_name."\"");
291 header( "Content-length: $rsssl_fsize" );
292 header( 'Cache-Control: private', false ); // required for certain browsers
293 header( 'Pragma: public' ); // required
294 header( 'Expires: 0' );
295 header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
296 header( 'Content-Transfer-Encoding: binary' );
297 echo $rsssl_content;
298 }
299
300 function rsssl_find_wordpress_base_path() {
301 $path = __DIR__;
302
303 // Check for Bitnami WordPress installation
304 if ( isset( $_SERVER['DOCUMENT_ROOT'] ) && $_SERVER['DOCUMENT_ROOT'] === '/opt/bitnami/wordpress' ) {
305 return '/opt/bitnami/wordpress';
306 }
307
308 // Go up the directory tree looking for wp-load.php
309 // This file is ALWAYS in the WordPress root
310 $max_depth = 10; // Prevent infinite loops
311 $current_depth = 0;
312
313 while ( ! file_exists( $path . '/wp-load.php' ) ) {
314 if ( ++ $current_depth > $max_depth ) {
315 break;
316 }
317
318 $parent = dirname( $path );
319 if ( $parent === $path ) {
320 // We've reached the filesystem root
321 break;
322 }
323 $path = $parent;
324 }
325
326 // If we found wp-load.php, return the path
327 if ( file_exists( $path . '/wp-load.php' ) ) {
328 return $path;
329 }
330
331 return false;
332 }
333
334 function rsssl_system_status_get_installed_plugins() {
335 if ( ! current_user_can( 'manage_security' ) ) {
336 return;
337 }
338
339 // Load the plugin admin functions
340 if ( ! function_exists( 'get_plugins' ) ) {
341 require_once ABSPATH . 'wp-admin/includes/plugin.php';
342 }
343
344 // Get the list of all installed plugins
345 $all_plugins = get_plugins();
346 $plugin_list = array();
347
348 // Loop through plugins to format the list with name and version
349 foreach ( $all_plugins as $plugin_path => $plugin_data ) {
350 $plugin_list[] = $plugin_data['Name'] . ' (' . $plugin_data['Version'] . ')';
351 }
352
353 // Return the list as a comma-separated string
354 return implode( ', ', $plugin_list );
355 }
356
357 function rsssl_system_status_get_blocked_countries_firewall() {
358
359 if ( ! current_user_can( 'manage_security' ) ) {
360 return;
361 }
362
363 global $wpdb;
364 $table_name = $wpdb->base_prefix . 'rsssl_geo_block';
365 $query_string = $wpdb->prepare(
366 "SELECT iso2_code FROM {$table_name} WHERE data_type = %s AND ip_address is NULL",
367 'country'
368 );
369 // phpcs:ignore
370 $result = $wpdb->get_results( $query_string );
371 $column_results = array_column( $result, 'iso2_code' );
372
373 return implode( ',', $column_results );
374 }
375
376 function rsssl_system_status_get_whitelist() {
377
378 if ( ! current_user_can( 'manage_security' ) ) {
379 return;
380 }
381
382 global $wpdb;
383 $table_name = $wpdb->base_prefix . 'rsssl_geo_block';
384 $query_string = $wpdb->prepare(
385 "SELECT ip_address FROM {$table_name} WHERE data_type = %s",
386 'trusted'
387 );
388 // phpcs:ignore
389 $result = $wpdb->get_results( $query_string );
390 $column_results = array_column( $result, 'ip_address' );
391
392 return implode( ',', $column_results );
393
394 }
395
396 function rsssl_system_status_get_blocked_countries_lla() {
397
398 if ( ! current_user_can( 'manage_security' ) ) {
399 return;
400 }
401
402 global $wpdb;
403 $table_name = $wpdb->base_prefix . 'rsssl_login_attempts';
404
405 // Query to get all the blocked countries from the login attempts table where attempt_type is 'country'
406 $query_string = $wpdb->prepare(
407 "SELECT attempt_value FROM {$table_name} WHERE attempt_type = %s AND status = %s",
408 'country', 'blocked'
409 );
410
411 // phpcs:ignore
412 $result = $wpdb->get_results( $query_string );
413 $column_results = array_column( $result, 'attempt_value' );
414
415 if ( empty( $column_results ) ) {
416 return "No blocked countries found.";
417 }
418
419 return implode( ',', $column_results );
420 }
421
422 function rsssl_system_status_get_blocked_ips() {
423 if ( ! current_user_can( 'manage_security' ) ) {
424 return '';
425 }
426
427 $output = '';
428
429 global $wpdb;
430 $sql = $wpdb->prepare(
431 "SELECT ip_address FROM {$wpdb->base_prefix}rsssl_geo_block WHERE blocked = %d AND data_type = %s",
432 1,
433 '404'
434 );
435
436 $results = $wpdb->get_results( $sql, ARRAY_A );
437
438 if ( empty( $results ) ) {
439 return "No blocked IPs found.";
440 }
441
442 foreach ( $results as $row ) {
443 $output .= $row['ip_address'] . "\n";
444 }
445
446 return $output;
447 }
448
449 function rsssl_system_status_get_blocked_users_lla() {
450 if ( ! current_user_can( 'manage_security' ) ) {
451 return;
452 }
453
454 global $wpdb;
455 $table_name = $wpdb->base_prefix . 'rsssl_login_attempts';
456
457 // Query to get all blocked users from login attempts where attempt_type is 'username'
458 $query_string = $wpdb->prepare(
459 "SELECT attempt_value FROM {$table_name} WHERE attempt_type = %s AND status = %s",
460 'username', 'blocked'
461 );
462
463 // phpcs:ignore
464 $result = $wpdb->get_results( $query_string );
465 $column_results = array_column( $result, 'attempt_value' );
466
467 if ( empty( $column_results ) ) {
468 return "No blocked users found.";
469 }
470
471 return implode( ',', $column_results );
472 }
473
474 function rsssl_system_status_get_blocked_ips_lla() {
475 if ( ! current_user_can( 'manage_security' ) ) {
476 return;
477 }
478
479 global $wpdb;
480 $table_name = $wpdb->base_prefix . 'rsssl_login_attempts';
481
482 // Query to get blocked single IPs (without CIDR notation) from login attempts
483 $query_string = $wpdb->prepare(
484 "SELECT attempt_value FROM {$table_name} WHERE attempt_type = %s AND status = %s AND attempt_value NOT LIKE %s",
485 'source_ip', 'blocked', '%/%'
486 );
487
488 // phpcs:ignore
489 $result = $wpdb->get_results( $query_string );
490 $column_results = array_column( $result, 'attempt_value' );
491
492 if ( empty( $column_results ) ) {
493 return "No blocked users found.";
494 }
495
496 return implode( ',', $column_results );
497 }
498
499 function rsssl_system_status_get_2fa_users() {
500 if ( ! current_user_can( 'manage_security' ) ) {
501 return;
502 }
503
504 global $wpdb;
505
506 // Query to get all users with TOTP or email 2FA status
507 $query = "
508 SELECT user_id, meta_key, meta_value
509 FROM {$wpdb->usermeta}
510 WHERE meta_key IN ('rsssl_two_fa_status_totp', 'rsssl_two_fa_status_email')
511 ";
512
513 // Execute the query
514 $results = $wpdb->get_results( $query );
515
516 // If no results, return a message
517 if ( empty( $results ) ) {
518 return 'No users found with 2FA settings.';
519 }
520
521 // Array to store users and their 2FA methods
522 $users_2fa = array();
523
524 // Organize the 2FA status by user
525 foreach ( $results as $row ) {
526 if ( ! isset( $users_2fa[ $row->user_id ] ) ) {
527 $users_2fa[ $row->user_id ] = array(
528 'rsssl_two_fa_status_totp' => '',
529 'rsssl_two_fa_status_email' => '',
530 );
531 }
532
533 // Update TOTP or email 2FA status
534 $users_2fa[ $row->user_id ][ $row->meta_key ] = $row->meta_value;
535 }
536
537 // Prepare output for users with active 2FA methods
538 $output = array();
539 foreach ( $users_2fa as $user_id => $user_data ) {
540 $user_info = get_userdata( $user_id );
541
542 // Determine the active 2FA method
543 if ( $user_data['rsssl_two_fa_status_totp'] === 'active' ) {
544 $output[] = $user_info->user_login . ' - TOTP';
545 } elseif ( $user_data['rsssl_two_fa_status_email'] === 'active' ) {
546 $output[] = $user_info->user_login . ' - Email';
547 }
548 }
549
550 // If no users are found with 2FA, add a note
551 if ( empty( $output ) ) {
552 return 'No users found with 2FA enabled.';
553 }
554
555 // Return a newline-separated list of users and their 2FA statuses
556 return implode( "\n", $output );
557 }
558