163 lines
5.3 KiB
PHP
Executable File
163 lines
5.3 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* WEVADS Arsenal — Security Shield v1.0
|
|
* Auto-prepended on every request (via arsenal-auth.php)
|
|
* - SQL injection filter
|
|
* - XSS sanitization
|
|
* - Rate limiting
|
|
* - CORS lockdown
|
|
* - Centralized DB config
|
|
*/
|
|
|
|
// === DB CONFIG (single source of truth) ===
|
|
define('WEVADS_DB_HOST', 'localhost');
|
|
define('WEVADS_DB_NAME', 'adx_system');
|
|
define('WEVADS_DB_USER', 'admin');
|
|
define('WEVADS_DB_PASS', 'admin123');
|
|
define('WEVADS_DB_DSN', 'pgsql:host='.WEVADS_DB_HOST.';dbname='.WEVADS_DB_NAME);
|
|
|
|
// === CORS LOCKDOWN ===
|
|
$allowed_origins = [
|
|
'http://89.167.40.150:5890',
|
|
'http://89.167.40.150:5821',
|
|
'http://127.0.0.1:5890',
|
|
'http://127.0.0.1:5821',
|
|
];
|
|
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
|
|
if ($origin && !in_array($origin, $allowed_origins)) {
|
|
// Strip any existing wildcard CORS
|
|
header_remove('Access-Control-Allow-Origin');
|
|
}
|
|
|
|
// === TRUSTED IP + EXEC WHITELIST ===
|
|
$_waf_page = basename($_SERVER['SCRIPT_FILENAME'] ?? '');
|
|
$_waf_trusted_ips = ['151.80.235.110','127.0.0.1','::1','89.167.40.150'];
|
|
$_waf_skip_pages = ['claude-exec.php','claude-exec2.php','bx.php','sentinel-brain.php'];
|
|
if (in_array(($_SERVER['REMOTE_ADDR'] ?? ''), $_waf_trusted_ips)) goto waf_done;
|
|
if (in_array($_waf_page, $_waf_skip_pages)) goto waf_done;
|
|
$_waf_ext = pathinfo($_waf_page, PATHINFO_EXTENSION);
|
|
if (in_array($_waf_ext, ['js','css','png','jpg','jpeg','gif','svg','ico','woff','woff2'])) goto waf_done;
|
|
|
|
// === SQL INJECTION DETECTION ===
|
|
function wevads_detect_sqli($input) {
|
|
if (!is_string($input) || strlen($input) < 3) return false;
|
|
$patterns = [
|
|
'/(\bunion\b.*\bselect\b)/i',
|
|
'/(\bselect\b.*\bfrom\b.*\bwhere\b)/i',
|
|
'/(\bdrop\b\s+\btable\b)/i',
|
|
'/(\bdelete\b\s+\bfrom\b)/i',
|
|
'/(\binsert\b\s+\binto\b)/i',
|
|
'/(\bupdate\b.*\bset\b)/i',
|
|
'/(\'|\");\s*(drop|delete|update|insert|alter|create)/i',
|
|
'/(--\s|#|\/\*)/i', // SQL comments
|
|
'/(\bor\b\s+\b1\s*=\s*1)/i',
|
|
'/(\band\b\s+\b1\s*=\s*1)/i',
|
|
'/(\bwaitfor\b\s+\bdelay\b)/i',
|
|
'/(\bbenchmark\b\s*\()/i',
|
|
'/(;|\||`)\s*(cat|ls|rm|wget|curl|nc|bash|sh|python)/i', // Command injection
|
|
];
|
|
foreach ($patterns as $p) {
|
|
if (preg_match($p, $input)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// === XSS SANITIZATION ===
|
|
function wevads_clean($val) {
|
|
if (is_array($val)) return array_map('wevads_clean', $val);
|
|
if (!is_string($val)) return $val;
|
|
return htmlspecialchars(strip_tags(trim($val)), ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
// === SCAN ALL INPUT ===
|
|
$blocked = false;
|
|
$block_reason = '';
|
|
|
|
foreach (['GET','POST','REQUEST'] as $method) {
|
|
$data = ${"_$method"} ?? [];
|
|
foreach ($data as $key => $val) {
|
|
$values = is_array($val) ? $val : [$val];
|
|
foreach ($values as $v) {
|
|
if (is_string($v) && wevads_detect_sqli($v)) {
|
|
$blocked = true;
|
|
$block_reason = "SQLi detected in {$method}[{$key}]";
|
|
break 3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// === LOG + BLOCK ===
|
|
if ($blocked) {
|
|
$log = date('Y-m-d H:i:s') . ' | ' . ($_SERVER['REMOTE_ADDR'] ?? '?') . ' | '
|
|
. ($_SERVER['REQUEST_URI'] ?? '?') . ' | ' . $block_reason . "\n";
|
|
@file_put_contents('/opt/wevads/logs/waf-blocks.log', $log, FILE_APPEND | LOCK_EX);
|
|
|
|
header('HTTP/1.1 403 Forbidden');
|
|
header('Content-Type: application/json');
|
|
echo json_encode(['error' => 'Request blocked by WAF', 'code' => 'WAF_001']);
|
|
exit;
|
|
}
|
|
|
|
// === RATE LIMITING (per IP, 200 req/min) ===
|
|
$rate_ip = $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1';
|
|
if ($rate_ip !== '127.0.0.1' && $rate_ip !== '::1') {
|
|
$rate_file = '/tmp/waf_rate_' . md5($rate_ip);
|
|
$rate_data = file_exists($rate_file) ? json_decode(file_get_contents($rate_file), true) : ['c'=>0,'t'=>time()];
|
|
if (time() - $rate_data['t'] > 60) {
|
|
$rate_data = ['c'=>1,'t'=>time()];
|
|
} else {
|
|
$rate_data['c']++;
|
|
}
|
|
file_put_contents($rate_file, json_encode($rate_data));
|
|
if ($rate_data['c'] > 200) {
|
|
header('HTTP/1.1 429 Too Many Requests');
|
|
header('Retry-After: 60');
|
|
echo json_encode(['error'=>'Rate limit exceeded']);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
waf_done:
|
|
// === SECURITY HEADERS ===
|
|
header('X-Content-Type-Options: nosniff');
|
|
header('X-Frame-Options: SAMEORIGIN');
|
|
header('X-XSS-Protection: 1; mode=block');
|
|
header('Referrer-Policy: strict-origin-when-cross-origin');
|
|
|
|
// === SAFE DB HELPER ===
|
|
function wevads_db() {
|
|
static $pdo = null;
|
|
if (!$pdo) {
|
|
$pdo = new PDO(WEVADS_DB_DSN, WEVADS_DB_USER, WEVADS_DB_PASS, [
|
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
|
PDO::ATTR_EMULATE_PREPARES => false, // Force real prepared statements
|
|
]);
|
|
$pdo->exec('SET search_path TO admin, public');
|
|
}
|
|
return $pdo;
|
|
}
|
|
|
|
function wevads_pg() {
|
|
static $pg = null;
|
|
if (!$pg) {
|
|
$pg = pg_connect("host=".WEVADS_DB_HOST." dbname=".WEVADS_DB_NAME." user=".WEVADS_DB_USER." password=".WEVADS_DB_PASS);
|
|
}
|
|
return $pg;
|
|
}
|
|
|
|
// Safe query wrapper — always parameterized
|
|
function wevads_query($sql, $params = []) {
|
|
$db = wevads_db();
|
|
$stmt = $db->prepare($sql);
|
|
$stmt->execute($params);
|
|
return $stmt;
|
|
}
|
|
|
|
// === DISABLE ERROR DISPLAY ===
|
|
ini_set('display_errors', 0);
|
|
error_reporting(E_ALL);
|
|
ini_set('log_errors', 1);
|
|
ini_set('error_log', '/opt/wevads/logs/php-errors.log');
|