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.
176 lines
11 KiB
PHP
176 lines
11 KiB
PHP
<?php
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
$argus_active_page = 'scanner';
|
|
include ARGUS_WPD_DIR . 'admin/views/partials/header.php';
|
|
|
|
$scan_type_labels = array(
|
|
Argus_Scan_History::TYPE_QUICK => __( 'Quick Scan', 'argus-wordpress-defence' ),
|
|
Argus_Scan_History::TYPE_FULL => __( 'Full Scan', 'argus-wordpress-defence' ),
|
|
Argus_Scan_History::TYPE_SCHEDULED_INCREMENTAL => __( 'Scheduled (Quick)', 'argus-wordpress-defence' ),
|
|
Argus_Scan_History::TYPE_SCHEDULED_FULL => __( 'Scheduled (Full)', 'argus-wordpress-defence' ),
|
|
);
|
|
?>
|
|
|
|
<h1 class="argus-wpd-page-title"><?php esc_html_e( 'Scanner', 'argus-wordpress-defence' ); ?></h1>
|
|
<p style="color:var(--muted);font-size:13px;margin:0 0 20px;"><?php esc_html_e( 'ARGUS regularly checks your WordPress installation for suspicious files, integrity changes, and known security risks.', 'argus-wordpress-defence' ); ?></p>
|
|
|
|
<?php if ( ! empty( $scan_notice ) ) : ?>
|
|
<div class="notice notice-success" style="padding:14px 18px;margin:0 0 20px;"><p style="margin:0"><?php echo esc_html( $scan_notice ); ?></p></div>
|
|
<?php endif; ?>
|
|
|
|
<div class="argus-wpd-metric-grid">
|
|
<div class="argus-wpd-metric-card">
|
|
<div class="argus-wpd-metric-label"><?php esc_html_e( 'Last Scan Status', 'argus-wordpress-defence' ); ?></div>
|
|
<div class="argus-wpd-metric-value" style="color:<?php echo ( $malware_open > 0 || $integrity_open > 0 ) ? 'var(--rose)' : 'var(--emerald)'; ?>"><?php echo ( $malware_open > 0 || $integrity_open > 0 ) ? esc_html__( 'Issues', 'argus-wordpress-defence' ) : esc_html__( 'Clean', 'argus-wordpress-defence' ); ?></div>
|
|
<div class="argus-wpd-metric-sub"><?php echo $scan_status['last_full_scan'] ? esc_html( human_time_diff( $scan_status['last_full_scan'] ) . ' ' . __( 'ago', 'argus-wordpress-defence' ) ) : esc_html__( 'No scan yet', 'argus-wordpress-defence' ); ?></div>
|
|
</div>
|
|
<div class="argus-wpd-metric-card">
|
|
<div class="argus-wpd-metric-label"><?php esc_html_e( 'Files Checked', 'argus-wordpress-defence' ); ?></div>
|
|
<div class="argus-wpd-metric-value"><?php echo esc_html( number_format_i18n( $scan_status['files_scanned'] ) ); ?></div>
|
|
<div class="argus-wpd-metric-sub"><?php esc_html_e( 'Last full scan', 'argus-wordpress-defence' ); ?></div>
|
|
</div>
|
|
<div class="argus-wpd-metric-card">
|
|
<div class="argus-wpd-metric-label"><?php esc_html_e( 'Findings', 'argus-wordpress-defence' ); ?></div>
|
|
<div class="argus-wpd-metric-value"><?php echo esc_html( number_format_i18n( $malware_open + $integrity_open ) ); ?></div>
|
|
<div class="argus-wpd-metric-sub"><?php esc_html_e( 'Currently open', 'argus-wordpress-defence' ); ?></div>
|
|
</div>
|
|
<div class="argus-wpd-metric-card">
|
|
<div class="argus-wpd-metric-label"><?php esc_html_e( 'Next Scan', 'argus-wordpress-defence' ); ?></div>
|
|
<div class="argus-wpd-metric-value" style="font-size:22px;"><?php echo $scan_status['next_scan'] ? esc_html( human_time_diff( $scan_status['next_scan'] ) ) : esc_html__( 'Not scheduled', 'argus-wordpress-defence' ); ?></div>
|
|
<div class="argus-wpd-metric-sub"><?php esc_html_e( 'Automatic, daily', 'argus-wordpress-defence' ); ?></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="argus-wpd-panel">
|
|
<h2><?php esc_html_e( 'Run a scan now', 'argus-wordpress-defence' ); ?></h2>
|
|
<form method="post" class="argus-wpd-inline-form">
|
|
<?php wp_nonce_field( 'argus_wpd_run_scan', 'argus_wpd_scan_nonce' ); ?>
|
|
<button type="submit" name="scan_type" value="quick" class="button"><?php esc_html_e( 'Quick Scan', 'argus-wordpress-defence' ); ?></button>
|
|
<button type="submit" name="scan_type" value="full" class="button button-primary"><?php esc_html_e( 'Full Scan', 'argus-wordpress-defence' ); ?></button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="argus-wpd-panel">
|
|
<h2><?php esc_html_e( 'Scan History', 'argus-wordpress-defence' ); ?></h2>
|
|
<?php if ( empty( $scan_history ) ) : ?>
|
|
<p class="argus-wpd-empty"><?php esc_html_e( 'No scans recorded yet.', 'argus-wordpress-defence' ); ?></p>
|
|
<?php else : ?>
|
|
<table class="widefat striped">
|
|
<thead>
|
|
<tr>
|
|
<th><?php esc_html_e( 'Date', 'argus-wordpress-defence' ); ?></th>
|
|
<th><?php esc_html_e( 'Scan Type', 'argus-wordpress-defence' ); ?></th>
|
|
<th><?php esc_html_e( 'Duration', 'argus-wordpress-defence' ); ?></th>
|
|
<th><?php esc_html_e( 'Result', 'argus-wordpress-defence' ); ?></th>
|
|
<th><?php esc_html_e( 'Findings', 'argus-wordpress-defence' ); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ( $scan_history as $run ) : ?>
|
|
<?php
|
|
$duration_secs = max( 0, strtotime( $run->finished_at . ' UTC' ) - strtotime( $run->started_at . ' UTC' ) );
|
|
?>
|
|
<tr>
|
|
<td><?php echo esc_html( wp_date( 'd M Y, H:i', strtotime( $run->started_at . ' UTC' ) ) ); ?></td>
|
|
<td><?php echo esc_html( $scan_type_labels[ $run->scan_type ] ?? ucfirst( $run->scan_type ) ); ?></td>
|
|
<td><?php echo esc_html( $duration_secs < 1 ? '<1s' : $duration_secs . 's' ); ?></td>
|
|
<td><span style="color:<?php echo 'clean' === $run->result ? 'var(--emerald)' : 'var(--rose)'; ?>;font-weight:600;"><?php echo 'clean' === $run->result ? esc_html__( 'Clean', 'argus-wordpress-defence' ) : esc_html__( 'Issues Found', 'argus-wordpress-defence' ); ?></span></td>
|
|
<td><?php echo esc_html( number_format_i18n( $run->findings_count ) ); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php
|
|
$page = $history_page;
|
|
$total_pages = $history_total_pages;
|
|
$base_url = remove_query_arg( 'scan_paged' );
|
|
$argus_page_param = 'scan_paged';
|
|
include ARGUS_WPD_DIR . 'admin/views/partials/pagination.php';
|
|
unset( $argus_page_param );
|
|
?>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="argus-wpd-scan-grid">
|
|
<div class="argus-wpd-panel">
|
|
<h2><?php esc_html_e( 'File Integrity', 'argus-wordpress-defence' ); ?></h2>
|
|
<div class="argus-wpd-scan-fact-row">
|
|
<span class="k"><?php esc_html_e( 'Status', 'argus-wordpress-defence' ); ?></span>
|
|
<span class="v" style="color:<?php echo $integrity_open > 0 ? 'var(--rose)' : 'var(--emerald)'; ?>"><?php echo $integrity_open > 0 ? esc_html__( 'ISSUES FOUND', 'argus-wordpress-defence' ) : esc_html__( 'VERIFIED', 'argus-wordpress-defence' ); ?></span>
|
|
</div>
|
|
<div class="argus-wpd-scan-fact-row">
|
|
<span class="k"><?php esc_html_e( 'Open findings', 'argus-wordpress-defence' ); ?></span>
|
|
<span class="v"><?php echo esc_html( number_format_i18n( $integrity_open ) ); ?></span>
|
|
</div>
|
|
<div class="argus-wpd-scan-fact-row">
|
|
<span class="k"><?php esc_html_e( 'Last full scan', 'argus-wordpress-defence' ); ?></span>
|
|
<span class="v"><?php echo $scan_status['last_full_scan'] ? esc_html( human_time_diff( $scan_status['last_full_scan'] ) . ' ' . __( 'ago', 'argus-wordpress-defence' ) ) : esc_html__( 'Never', 'argus-wordpress-defence' ); ?></span>
|
|
</div>
|
|
<div class="argus-wpd-scan-fact-row">
|
|
<span class="k"><?php esc_html_e( 'Files scanned', 'argus-wordpress-defence' ); ?></span>
|
|
<span class="v"><?php echo esc_html( number_format_i18n( $scan_status['files_scanned'] ) ); ?></span>
|
|
</div>
|
|
<div class="argus-wpd-scan-fact-row">
|
|
<span class="k"><?php esc_html_e( 'Next scheduled scan', 'argus-wordpress-defence' ); ?></span>
|
|
<span class="v"><?php echo $scan_status['next_scan'] ? esc_html( human_time_diff( $scan_status['next_scan'] ) ) : esc_html__( 'Not scheduled', 'argus-wordpress-defence' ); ?></span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="argus-wpd-panel">
|
|
<h2><?php esc_html_e( 'Malware', 'argus-wordpress-defence' ); ?></h2>
|
|
<div class="argus-wpd-scan-fact-row">
|
|
<span class="k"><?php esc_html_e( 'Status', 'argus-wordpress-defence' ); ?></span>
|
|
<span class="v" style="color:<?php echo $malware_open > 0 ? 'var(--rose)' : 'var(--emerald)'; ?>"><?php echo $malware_open > 0 ? esc_html__( 'THREATS FOUND', 'argus-wordpress-defence' ) : esc_html__( 'CLEAN', 'argus-wordpress-defence' ); ?></span>
|
|
</div>
|
|
<div class="argus-wpd-scan-fact-row">
|
|
<span class="k"><?php esc_html_e( 'Open findings', 'argus-wordpress-defence' ); ?></span>
|
|
<span class="v"><?php echo esc_html( number_format_i18n( $malware_open ) ); ?></span>
|
|
</div>
|
|
<div class="argus-wpd-scan-fact-row">
|
|
<span class="k"><?php esc_html_e( 'Uploads PHP-execution lock', 'argus-wordpress-defence' ); ?></span>
|
|
<?php if ( 'active' === $lockdown_status ) : ?>
|
|
<span class="v" style="color:var(--emerald)"><?php esc_html_e( 'ACTIVE', 'argus-wordpress-defence' ); ?></span>
|
|
<?php elseif ( 'not_writable' === $lockdown_status || 'failed_write' === $lockdown_status ) : ?>
|
|
<span class="v" style="color:var(--rose)"><?php esc_html_e( 'NOT ACTIVE', 'argus-wordpress-defence' ); ?></span>
|
|
<?php else : ?>
|
|
<span class="v" style="color:var(--faint)"><?php esc_html_e( 'UNKNOWN', 'argus-wordpress-defence' ); ?></span>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php if ( 'active' !== $lockdown_status ) : ?>
|
|
<p style="color:var(--amber);font-size:11.5px;margin:10px 0 0;line-height:1.5;">
|
|
<?php
|
|
if ( 'not_writable' === $lockdown_status || 'failed_write' === $lockdown_status ) {
|
|
esc_html_e( 'ARGUS could not write the protective .htaccess rule -- wp-content/uploads is not writable by PHP on this host. This is a real, unmitigated gap: fix directory permissions so ARGUS can lock uploads against PHP execution.', 'argus-wordpress-defence' );
|
|
} else {
|
|
esc_html_e( 'Status not yet determined -- a scan has not run since this check was added.', 'argus-wordpress-defence' );
|
|
}
|
|
?>
|
|
</p>
|
|
<?php endif; ?>
|
|
<div class="argus-wpd-scan-fact-row">
|
|
<span class="k"><?php esc_html_e( 'Quarantined items', 'argus-wordpress-defence' ); ?></span>
|
|
<span class="v"><?php echo esc_html( number_format_i18n( $quarantine_review_count ) ); ?></span>
|
|
</div>
|
|
<p style="color:var(--faint);font-size:12px;margin:14px 0 0;line-height:1.6;">
|
|
<?php esc_html_e( 'A PHP file found in wp-content/uploads is moved into a protected quarantine store on sight, and the uploads directory is locked against PHP execution entirely -- the same technique used by other established WordPress security plugins.', 'argus-wordpress-defence' ); ?>
|
|
<a href="<?php echo esc_url( admin_url( 'admin.php?page=argus-wpd-quarantine' ) ); ?>" style="color:var(--cyan);font-weight:600;text-decoration:none"><?php esc_html_e( 'Manage quarantine', 'argus-wordpress-defence' ); ?> →</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ( $malware_open > 0 || $integrity_open > 0 ) : ?>
|
|
<div class="argus-wpd-panel">
|
|
<p style="margin:0;font-size:13px;color:var(--muted);">
|
|
<?php esc_html_e( 'Scanner findings appear on the', 'argus-wordpress-defence' ); ?>
|
|
<a href="<?php echo esc_url( admin_url( 'admin.php?page=argus-wpd-findings' ) ); ?>" style="color:var(--cyan);font-weight:600;text-decoration:none"><?php esc_html_e( 'Findings page', 'argus-wordpress-defence' ); ?></a>,
|
|
<?php esc_html_e( 'with full explanations and one-click remediation where available.', 'argus-wordpress-defence' ); ?>
|
|
</p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php include ARGUS_WPD_DIR . 'admin/views/partials/footer.php'; ?>
|