One Hat Cyber Team
Your IP :
104.23.197.102
Server IP :
172.67.218.182
Server :
Linux 128-201-239-36.cprapid.com 3.10.0-1160.41.1.el7.x86_64 #1 SMP Tue Aug 31 14:52:47 UTC 2021 x86_64
Server Software :
Apache
PHP Version :
7.4.33
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
home
/
juscatamarca
/
public_html
/
wp-content
/
jurado
/
Edit File:
ajax_buscar.php
<?php declare(strict_types=1); /** * Endpoint AJAX – Juicio por Jurados * Devuelve JSON puro (sin WordPress). * Hardened: validación request, DNI estricto, headers, anti abuso básico. */ // ================== SECURITY HEADERS ================== header('Content-Type: application/json; charset=utf-8'); header('X-Content-Type-Options: nosniff'); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Pragma: no-cache'); header('Referrer-Policy: no-referrer'); header('Access-Control-Allow-Origin: https://juscatamarca.gob.ar'); // ajustá si hace falta header('Vary: Origin'); ini_set('display_errors', '0'); error_reporting(0); // ================== QUICK REQUEST GUARDS ================== if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') { http_response_code(405); echo json_encode(['ok' => false, 'error' => 'Método no permitido.'], JSON_UNESCAPED_UNICODE); exit; } // Evita requests enormes (anti abuso). Ajustá si querés. $contentLength = (int)($_SERVER['CONTENT_LENGTH'] ?? 0); if ($contentLength > 2048) { // 2KB sobra para un DNI http_response_code(413); echo json_encode(['ok' => false, 'error' => 'Solicitud demasiado grande.'], JSON_UNESCAPED_UNICODE); exit; } // Si querés exigir AJAX (opcional). Si te rompe algo, comentá este bloque. $xhr = $_SERVER['HTTP_X_REQUESTED_WITH'] ?? ''; if (strcasecmp($xhr, 'XMLHttpRequest') !== 0) { http_response_code(400); echo json_encode(['ok' => false, 'error' => 'Solicitud inválida.'], JSON_UNESCAPED_UNICODE); exit; } // ================== BASIC RATE LIMIT (OPCIONAL) ================== // Simple (file-based). Si tu hosting no permite escribir, comentá todo este bloque. function rateLimit(string $key, int $maxHits, int $windowSeconds): bool { $dir = sys_get_temp_dir() . '/jurado_rl'; if (!is_dir($dir)) @mkdir($dir, 0700, true); $file = $dir . '/' . preg_replace('/[^a-zA-Z0-9_\-]/', '_', $key) . '.json'; $now = time(); $data = ['ts' => $now, 'hits' => 0]; if (is_file($file)) { $raw = @file_get_contents($file); $decoded = json_decode((string)$raw, true); if (is_array($decoded) && isset($decoded['ts'], $decoded['hits'])) { $data = $decoded; } } // Si expiró ventana, resetea if (($now - (int)$data['ts']) > $windowSeconds) { $data = ['ts' => $now, 'hits' => 0]; } $data['hits'] = (int)$data['hits'] + 1; // Persistir @file_put_contents($file, json_encode($data), LOCK_EX); // True si pasa, false si bloquea return $data['hits'] <= $maxHits; } $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; if (!rateLimit('ip_' . $ip, 30, 60)) { // 30 requests por minuto por IP http_response_code(429); echo json_encode(['ok' => false, 'error' => 'Demasiadas consultas. Probá en 1 minuto.'], JSON_UNESCAPED_UNICODE); exit; } // ================== DB CONFIG ================== const DB_HOST = 'localhost'; const DB_NAME = 'juscatamarca_eleccionesjura_2026'; const DB_USER = 'juscatamarca_juiciojurado2026'; const DB_PASS = ')}]GnMq&]+d['; const DB_CHARSET = 'utf8mb4'; // ================== DB CONN ================== function db(): PDO { static $pdo = null; if ($pdo instanceof PDO) return $pdo; $dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET; $pdo = new PDO($dsn, DB_USER, DB_PASS, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, // + seguro ]); // Fuerza charset (por si acaso) $pdo->exec("SET NAMES " . DB_CHARSET); return $pdo; } // ================== HELPERS ================== function onlyDigits(string $s): string { return preg_replace('/\D+/', '', $s) ?? ''; } function jsonOut(array $payload, int $code = 200): void { http_response_code($code); echo json_encode($payload, JSON_UNESCAPED_UNICODE); exit; } // ================== INPUT ================== $rawDni = (string)($_POST['dni'] ?? ''); $rawDni = trim($rawDni); // Si vienen caracteres raros (html/script), lo cortamos antes de “limpiar” // (porque si limpias y seguís, el atacante prueba cosas igual) if ($rawDni !== '' && preg_match('/[<>]/', $rawDni)) { jsonOut(['ok' => false, 'error' => 'DNI inválido.'], 400); } $dni = onlyDigits($rawDni); // Validación estricta: 7 a 9 dígitos, nada más. if (!preg_match('/^\d{7,9}$/', $dni)) { jsonOut([ 'ok' => false, 'error' => 'DNI inválido. Ingresá solo números (7 a 9 dígitos), sin puntos ni espacios.' ], 400); } try { // ================== 1) LISTAS SEGUNDA–SEXTA ================== $sql1 = " SELECT circunscripcion, lugar, dni, apellido, nombre FROM preseleccionados_2026 WHERE dni = :dni LIMIT 1 "; $st1 = db()->prepare($sql1); $st1->execute([':dni' => $dni]); $row = $st1->fetch(); if ($row) { $circ = (string)($row['circunscripcion'] ?? ''); $lugar = (string)($row['lugar'] ?? '-'); jsonOut([ 'ok' => true, 'status' => 'SI', 'dni' => $dni, 'apellido' => (string)($row['apellido'] ?? ''), 'nombre' => (string)($row['nombre'] ?? ''), 'circunscripcion' => $circ . ' (' . $lugar . ')' ]); } // ================== 2) PRIMERA (PADRÓN) ================== $sql2 = " SELECT apellido, nombre, dpto FROM padron_primaria_2026 WHERE dni = :dni LIMIT 1 "; $st2 = db()->prepare($sql2); $st2->execute([':dni' => $dni]); $padron = $st2->fetch(); if ($padron) { $dpto = (string)($padron['dpto'] ?? '-'); jsonOut([ 'ok' => true, 'status' => 'SI', 'dni' => $dni, 'apellido' => (string)($padron['apellido'] ?? ''), 'nombre' => (string)($padron['nombre'] ?? ''), 'circunscripcion' => 'PRIMERA (' . $dpto . ')' ]); } // ================== NO FIGURA ================== jsonOut([ 'ok' => true, 'status' => 'NO', 'dni' => $dni ]); } catch (Throwable $e) { // Log interno (opcional). Si no querés logs, borrá esto. // error_log('[JURADO AJAX] ' . $e->getMessage()); jsonOut([ 'ok' => false, 'error' => 'Error interno del servidor. Intentá más tarde.' ], 500); }
Simpan