|
1 | 1 | <?php |
2 | | -// Function to obtain the client's real IP |
| 2 | + |
| 3 | +/** |
| 4 | + * OPAC Security - Input Validation |
| 5 | + * Implements Parameter Whitelisting and Malicious Pattern Detection |
| 6 | + */ |
| 7 | + |
| 8 | +// Obtain the customer's actual IP address |
3 | 9 | function get_client_ip() |
4 | 10 | { |
5 | | - $keys = [ |
6 | | - 'HTTP_CLIENT_IP', |
7 | | - 'HTTP_X_FORWARDED_FOR', |
8 | | - 'REMOTE_ADDR' |
9 | | - ]; |
| 11 | + $keys = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR']; |
10 | 12 | foreach ($keys as $key) { |
11 | 13 | if (!empty($_SERVER[$key])) { |
12 | | - return $_SERVER[$key]; |
| 14 | + // In case of multiple IPs (proxies), take the first one |
| 15 | + $ip_array = explode(',', $_SERVER[$key]); |
| 16 | + return trim($ip_array[0]); |
13 | 17 | } |
14 | 18 | } |
15 | 19 | return 'IP_desconhecido'; |
16 | 20 | } |
17 | 21 |
|
18 | | -// Validation function against dangerous standards |
| 22 | +// Checks for dangerous patterns in VALUE (SQL Injection, XSS, Path Traversal) |
19 | 23 | function is_malicious($str) |
20 | 24 | { |
| 25 | + // If it is an array, do not check here (it is already handled in the validation loop). |
| 26 | + if (is_array($str)) return false; |
| 27 | + |
21 | 28 | $patterns = [ |
22 | | - '/<script\b/i', |
23 | | - '/(and|or)\s+\d+=\d+/i', |
24 | | - '/[\'"`]\s*(or|and)?\s*\d+=\d+/i', |
25 | | - '/[\'"`]\s*--/', |
26 | | - '/<.*?>/', |
27 | | - '/\b(select|union|insert|delete|update|drop|eval|alert)\b/i' |
| 29 | + '/<script\b/i', // XSS |
| 30 | + '/(and|or)\s+\d+=\d+/i', // Classic SQLi (1=1) |
| 31 | + '/[\'"`]\s*(or|and)?\s*\d+=\d+/i', // SQLi with quotation marks |
| 32 | + '/union\s+select/i', // SQLi Union |
| 33 | + '/information_schema/i', // SQLi Recon |
| 34 | + '/into\s+outfile/i', // SQLi Arquivo |
| 35 | + '/\.\.\//', // Path Traversal (../) |
| 36 | + '/\.\.\\%2F/i', // Path Traversal URL Encoded |
| 37 | + '/etc\/passwd/i', // Access to system files |
| 38 | + '/cmd\.exe/i' // Command execution |
28 | 39 | ]; |
| 40 | + |
29 | 41 | foreach ($patterns as $pattern) { |
30 | 42 | if (preg_match($pattern, $str)) return true; |
31 | 43 | } |
32 | 44 | return false; |
33 | 45 | } |
34 | 46 |
|
35 | | - |
36 | | -// Function that validates entries |
| 47 | +/** |
| 48 | + * Validates all inputs (GET/POST) against a whitelist of known parameters. |
| 49 | + * Blocks unknown keys and malicious values. |
| 50 | + */ |
37 | 51 | function validate_inputs($inputs, $source = 'INPUT') |
38 | 52 | { |
39 | 53 | $ip = get_client_ip(); |
| 54 | + |
| 55 | + // 1. WHITE LIST: Only these parameters are accepted in OPAC. |
| 56 | + // Anything outside of this will be considered suspicious. |
| 57 | + $allowed_params = [ |
| 58 | + // Infrastructure |
| 59 | + 'base', |
| 60 | + 'cipar', |
| 61 | + 'ctx', |
| 62 | + 'lang', |
| 63 | + 'db_path', |
| 64 | + 'modo', |
| 65 | + 'integrada', |
| 66 | + 'lista_bases', |
| 67 | + |
| 68 | + // Search and Navigation |
| 69 | + 'Opcion', |
| 70 | + 'Expresion', |
| 71 | + 'Sub_Expresion', |
| 72 | + 'Sub_Expresiones', |
| 73 | + 'camp', |
| 74 | + 'oper', |
| 75 | + 'pagina', |
| 76 | + 'desde', |
| 77 | + 'count', |
| 78 | + 'resaltar', |
| 79 | + 'Formato', |
| 80 | + 'coleccion', |
| 81 | + 'alcance', |
| 82 | + 'prefijo', |
| 83 | + 'prefijoindice', |
| 84 | + 'campo', |
| 85 | + 'id', |
| 86 | + 'Diccio', |
| 87 | + 'letra', |
| 88 | + 'ira', |
| 89 | + 'posting', |
| 90 | + 'columnas', |
| 91 | + 'facetas', |
| 92 | + 'termosLivres', |
| 93 | + 'search_form', |
| 94 | + |
| 95 | + // Actions and User |
| 96 | + 'cookie', |
| 97 | + 'Accion', |
| 98 | + 'sendto', |
| 99 | + 'mfn', |
| 100 | + 'k', // k = permalink |
| 101 | + 'login', |
| 102 | + 'password', |
| 103 | + 'conf_level', |
| 104 | + 'redirect', |
| 105 | + 'existencias', |
| 106 | + |
| 107 | + // Preview |
| 108 | + 'titulo', |
| 109 | + 'titulo_c', |
| 110 | + 'submenu', |
| 111 | + 'mostrar_exp', |
| 112 | + 'home', |
| 113 | + 'Pft', |
| 114 | + 'decodificar', |
| 115 | + 'page', |
| 116 | + 'llamado_desde', |
| 117 | + 'Navegacion', |
| 118 | + 'LastKey', |
| 119 | + 'Seleccionados', |
| 120 | + |
| 121 | + // Session / Admin (if applicable) |
| 122 | + 'sid', |
| 123 | + 'token' |
| 124 | + ]; |
| 125 | + |
40 | 126 | foreach ($inputs as $key => $value) { |
| 127 | + |
| 128 | + // 2. KEY VERIFICATION (PARAMETER NAME) |
| 129 | + if (!in_array($key, $allowed_params)) { |
| 130 | + // Silently attempts or blocks |
| 131 | + error_log("⚠️ [OPAC SEC] IP $ip tried unknown parameter: [$key]"); |
| 132 | + |
| 133 | + // To be rigid and block: |
| 134 | + die("Access Blocked: Invalid parameter detected ($key)."); |
| 135 | + |
| 136 | + // If you prefer to simply ignore the parameter (softer approach): |
| 137 | + // unset($_REQUEST[$key]); |
| 138 | + // continue; |
| 139 | + } |
| 140 | + |
| 141 | + // 3. VALUE VERIFICATION (CONTENT) |
41 | 142 | if (is_array($value)) { |
| 143 | + // Recursive validation for arrays (ex: camp[], Sub_Expresiones[]) |
42 | 144 | foreach ($value as $subval) { |
43 | 145 | if (is_malicious($subval)) { |
44 | | - error_log("⚠️ Blocked IP attack $ip: $source [$key] => $subval"); |
45 | | - die("Invalid input detected.<br><h1> Registered IP: $ip"); |
| 146 | + error_log("⚠️ [OPAC SEC] IP $ip ataque detectado em array [$key]: $subval"); |
| 147 | + die("Conteúdo inválido detectado."); |
46 | 148 | } |
47 | 149 | } |
48 | 150 | } else { |
49 | 151 | if (is_malicious($value)) { |
50 | | - error_log("⚠️ Blocked IP attack $ip: $source [$key] => $value"); |
51 | | - die("Invalid input detected. <h1> Registered IP: $ip"); |
| 152 | + error_log("⚠️ [OPAC SEC] IP $ip ataque detectado em [$key]: $value"); |
| 153 | + die("Conteúdo inválido detectado."); |
52 | 154 | } |
53 | 155 | } |
54 | 156 | } |
55 | 157 | } |
56 | 158 |
|
57 | | -// Apply validation |
58 | | -validate_inputs($_GET, 'GET'); |
59 | | -validate_inputs($_POST, 'POST'); |
60 | | -validate_inputs($_REQUEST, 'REQUEST'); |
| 159 | +// Automatic execution on inclusion |
| 160 | +// If you want to enable it automatically, uncomment the lines below. |
| 161 | +// Otherwise, call validate_inputs($_REQUEST) at the beginning of the main scripts. |
| 162 | +/* |
| 163 | +if (!empty($_GET)) validate_inputs($_GET, 'GET'); |
| 164 | +if (!empty($_POST)) validate_inputs($_POST, 'POST'); |
| 165 | +*/ |
0 commit comments