Filtrando ataques de inyección de SQL, la regla para Cloudflare

Cada tanto alguien se las ingenia para atacar el blog de alguna forma diferente, yo me divierto investigando qué hacen, cómo contraatacar y aprender en el proceso.

El último método de ataque "molesto" son los intentos de inyección de SQL en las páginas de este blog. Algo muy común en sitios con PHP, pero que con un par de líneas se resuelve. Aun así este "atacante" está decidido a repetir los mismos ataques una y otra vez aunque no obtenga resultado alguno.

Aquí les dejo un método para filtrarlos ANTES de que lleguen a tu servidor.

El origen argentino

Lo interesante de estos ataques es que en su totalidad provienen de IPs argentinas. ¿El atacante es local? No es importante, yo creo que, como tiene identificado que el blog es argentino utiliza IPs locales para que yo no las filtre.

Una de mis reglas básicas de Cloudflare es filtrar "países de mierda", funciona de maravillas ¿Quién quiere tráfico de China o de la India en un blog como este? Es un recurso barato y que Cloudflare permite resolver con una simple regla.

Ahora bien ¿Quién querría banear IPs argentinos si la mayor parte de sus lectores son de su propio país? Desde ese punto de vista es lógico que, para atacar este sitio, se busquen rangos de IPs que el dueño no se atreva a bloquear (vale, yo los bloqueo igual, pero eso lo explico más adelante 😅)

¿Cómo es que usan IPs de Argentina? Es fácil, la cantidad enorme de idiotas que instalan aplicaciones como MagisTV básicamente le entregan máquinas bobas gratis a los spammers y atacantes, estos equipos se alquilan por muy poco dinero de a millones, los dueños de esas máquinas "secuestradas" no tienen idea de que sus conexiones a Internet son usadas por terceros, creen que porque pueden ver películas o series sólo obtienen beneficios y que es "gratis".

Estas máquinas hacen de proxy de atacantes para sitios de Argentina, lo mismo sucede para IPs de Colombia, o de Brasil o de prácticamente todo el mundo, donde más está difundido este tipo de apps "piratas" (que se instalan con un APK que no sale de la tienda de Google usualmente) es desde donde más se ataca. De hecho, normalmente agrego a Brasil en la lista de "países de mierda" justamente por esto.

Bloqueando en el blog

Hace ya un tiempo que tengo un identificador de ataques de este tipo, leo los strings de entrada POST y GET, busco los clásicos ataques e inyecciones, los registro.

En un primer momento sólo lo usaba para conocer y loguear, pero hace un par de meses hice algunos cambios y creé los baneos temporales.

De esta forma este tipo de ataques, usando el IP de un pobre diablo, no bloquean permanentemente un IP sino que dura un día o dos (lo puse configurable).

Pero cada ataque implica que mi servidor tiene que hacer el trabajo de analizar la entrada, agregar el bloqueo, etc. No deja de ser un "costo" a nivel hosting. 

Si te saturan con cientos de miles de ataques alguno puede llegar a pasar (uno que no tenga contemplado) o, por ejemplo, en todo sitio cuando lo atacado es el buscador o algún filtro que no está cacheado, pum, golpe a la base de datos y consumo desmedido de recursos.

En particular el atacante con IPs argentinos e inyecciones de SQL lo viene haciendo en cantidad, hubo varios miles en una hora, ahora bajó mucho, pero llegó a dedicarle bastante presupuesto.

Con todas las variables de entrada sanitizadas mi única preocupación era que me llenaba el log de basura 😅 y yo lo quiero sólo para los ataques que no entiendo o necesito investigar, así que pasé a la fase 2 del contraataque: que ni siquiera llegue al blog.

La regla de Cloudflare

Los ataques tienen varias cosas que son comunes, una de ellas es que suelen ofuscar con texto variable los intentos, pero en general todos necesitan de las mismas cosas.

Luego de probar varias reglas llegué a una bastante complicada a primera vista, pero que es fácil de entender si aislamos un sólo caso, ejemplo:

remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "unionselect"

La idea aquí es sacar toda la basura y llegar a cualquier instancia donde el texto tenga un UNION SELECT, clásico ataque donde uno busca "extender" la consulta a la base de datos con algo extra y así validar que se puede inyectar lo que uno quiera.

La versión gratuita de Cloudflare es un poco más limitada y sólo permite ver las urls que entran por GET, pero como casi todo filtro y hasta el buscador del blog entran por GET es el caso ideal para filtrar http.request.uri nos trae la url que se usó, con todos sus parámetros, y ahí podemos trabajar.

Hay otras combinaciones muy usadas, UNION ALL SELECT, UNION DISTINCT SELECT, EXTRACTVALUE, etc. como el lenguaje SQL es bien corto es fácil crear una regla grande que contemple todos los intentos, esta es mi regla actual (va mejorando) para Cloudflare:

(
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "unionselect" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "unionallselect" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "uniondistinctselect" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "information_schema" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "group_concat" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "intooutfile" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "intodumpfile" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "@@version" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "@@datadir" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "@@hostname" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "procedureanalyse" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "orderby1--" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "xp_cmdshell" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "utl_inaddr" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "dbms_pipe" or
  remove_bytes(lower(url_decode(http.request.uri, "ur")), "\x09\x0a\x0b\x0c\x0d\x20\x2b\x2f\x2a\x28\x29\x60") contains "extractvalue"
)

Con esta regla he logrado mitigar el 99% de los ataques y ya no pasan al blog, se quedan a nivel red.

Ataques ejemplo:

index.php?pagenum=26&tema=%29%2F**%2Fand%2F**%2F%281909187795%3D1909187795%2F**%2FuNIOn%2F**%2FALL%2F**%2FSElECT%2F**%2FNUll%2C%27ukenjpfmyurncrrkrbqbskaeodwqvlxi%27--%2F**%2FP2LrJ5

nótese cómo está ofuscado todo para que no sea fácil de identificar, el remove_bytes ayuda a la limpieza y que no se escape.

¿Puede afectar a alguna búsqueda legítima en el sitio? Si, pero no me importa, la probabilidad es mínima, ya ningún programador usa el buscador de un sitio 😁 y quién cuernos pregunta por un SELECT? 

¿Por qué razón alguien buscaría tan esforzadamente reventar este blog? No tengo la respuesta para ello, el gasto que está haciendo me hace pensar que hasta es un lector del sitio que  está buscando provocar estos mismos posts para mejorar sus capacidades de ataque 🤪 si, vamos, ya se de uno de ustedes que no visitaba este sitio muy seguido que un día se puso a atacarlo por deporte, nunca le dije nada.

Otros, en cambio, más copados, me avisan y hasta me pasan avisos de vulnerabilidades que van encontrando, yo las corrijo, les aviso para que prueben de nuevo (el whitehat hacking se honra) y les paso info, porque así debe ser entre nosotros y por eso les escribo estas notas.

Nótese que, si bien ahora todos creen que una AI les solucionará todos los problemas, este tipo de detalles suelen pasárseles por alto, no te cubren en estos frentes, es el típico caso en el que ChatGPT te responderá "uh, mala mía, tenés razón, no saniticé la entrada, te culearon todos los datos en un GET" 😁 tratemos de evitarlo, jeje.

Si te gustó esta nota podés...
Invitame un café en cafecito.app


Otros posts que podrían llegar a gustarte...

Comentarios

  • 1
    MaC     16/09/2026 - 10:11:52

    Ponele que alguna vez haya instalado alguna de esas apps turbias...como hago para que mi ip no siga siendo usada de esa forma?

Deje su comentario:

Tranquilo, su email nunca será revelado.
La gente de bien tiene URL, no se olvide del http/https
Comentarios ofensivos o que no hagan al enriquecimiento del post serán borrados/editados por el administrador. Los comentarios son filtrados por Cloudflare Turnstile.