Automatic WordPress security: local firewall, malware and file-integrity scanning, vulnerability protection, quarantine, scheduled backups, an optional page cache, and automatic global threat intelligence. See README.md for installation, update, and uninstall instructions.
70 lines
2.4 KiB
PHP
70 lines
2.4 KiB
PHP
<?php
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
class Argus_AJAX_Inventory {
|
|
|
|
public static function snapshot() {
|
|
global $wp_filter;
|
|
|
|
if ( empty( $wp_filter ) ) {
|
|
return array();
|
|
}
|
|
|
|
$nopriv_actions = array();
|
|
|
|
foreach ( $wp_filter as $hook_name => $hook_obj ) {
|
|
if ( 0 !== strpos( (string) $hook_name, 'wp_ajax_nopriv_' ) ) {
|
|
continue;
|
|
}
|
|
|
|
$action = substr( (string) $hook_name, strlen( 'wp_ajax_nopriv_' ) );
|
|
$plugin = self::owning_plugin_for_hook( $hook_obj );
|
|
|
|
$nopriv_actions[] = array( 'action' => $action, 'plugin' => $plugin );
|
|
}
|
|
|
|
update_option( 'argus_wpd_ajax_inventory', array( 'checked_at' => current_time( 'mysql', true ), 'nopriv_actions' => $nopriv_actions ), false );
|
|
|
|
if ( ! empty( $nopriv_actions ) ) {
|
|
Argus_Findings::record(
|
|
'ajax_inventory',
|
|
'info',
|
|
array(
|
|
|
|
'what_happened' => 'Unauthenticated-reachable AJAX actions inventoried',
|
|
'why_it_matters' => 'wp_ajax_nopriv_* handlers are callable by anyone, logged in or not -- this is a completely normal, widely-used WordPress mechanism (contact forms, AJAX search, and many other legitimate features all use it), not inherently a problem.',
|
|
'what_argus_found' => sprintf( '%d action(s) found: %s', count( $nopriv_actions ), implode( ', ', array_map( function ( $a ) { return $a['action'] . ( $a['plugin'] ? ' (' . $a['plugin'] . ')' : '' ); }, $nopriv_actions ) ) ),
|
|
'when_it_happened' => current_time( 'mysql' ),
|
|
'why_suspicious' => 'This is an inventory, not a detection -- shown so you know your site\'s full unauthenticated attack surface in one place.',
|
|
'what_could_be_affected' => 'Depends on what each handler does -- review any you don\'t recognize.',
|
|
'what_should_you_do' => 'No action needed unless you see an action name you don\'t recognize from a plugin you don\'t remember installing.',
|
|
),
|
|
array( 'nopriv_actions' => $nopriv_actions )
|
|
);
|
|
}
|
|
|
|
return $nopriv_actions;
|
|
}
|
|
|
|
protected static function owning_plugin_for_hook( $hook_obj ) {
|
|
if ( ! isset( $hook_obj->callbacks ) || ! is_array( $hook_obj->callbacks ) ) {
|
|
return null;
|
|
}
|
|
|
|
foreach ( $hook_obj->callbacks as $priority_group ) {
|
|
foreach ( $priority_group as $cb ) {
|
|
$callback = $cb['function'] ?? null;
|
|
$plugin = Argus_REST_Inventory::owning_plugin( $callback );
|
|
if ( $plugin ) {
|
|
return $plugin;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|