Buscando como ganar algo de dinero acepté un trabajo que consistía en hacer un plugin para
scrappear los videos de una pagina web y ponerlos en un
WordPress. La verdad es que el uso de este plugin puede ser para hacer cosas buenas y también para hacer cosas malas, pero en mi caso consistía solo en hacer el trabajo, así que no me pareció mala idea y lo acepté. El caso es que durante el proceso de
scrappear las páginas del sitio me encontré con un problema. En un error mío empece a enviar peticiones a la pagina de forma masiva y sin control, lo que provocó lo que a ojos del sitio era un
Ataque de Denegación de Servicio de todo la vida, y en respuesta esa pagina puso su protección de
"I'm under attack" que tiene contratada con
Cloudflare. En ese momento pensé, vaya me quede sin el dinero y empece a indagar en el tema.
|
Figura 1: Cómo saltarse Cloudflare para scrappear una web |
El protector de
Cloudflare frente ataques de
Denegación de Servicio lo que parece que intenta es hacerte esperar durante cinco segundos antes de poder entrar en la pagina web. Así, cuando vas a una página protegida por
Cloudflare lo que ves en el navegador es simplemente una pantalla en blanco con la frase
"Espere 5 segundos". Sin embargo, lo que sucede por debajo es un poco más complejo, ya que en realidad hay una serie de peticiones y respuestas con un algoritmo que intenta detectar cuando es un
bot o cuando es un usuario navegando. Ésta es la pantalla que se puede observar al intentar entrar.
|
Figura 2: Pantalla de protección de Cloudflare para evitar los ataques DDoS |
Al ver esto lo primero que pensé fue en buscar por
Internet qué podía hacer y si había algún programa capaz de saltarse de forma automatizada esas peticiones, pero para mi sorpresa sólo había un código en
Python hecho por un tal
Anorov y yo ese código no podía usarlo en mi aplicación, ya que usaba librerías externas, así que lo que decidí fue crear mi propio código en
PHP para saltarme la protección.
Para ello decidí comenzar con el proceso desde cero y analizar qué estaba pasando durante esos cinco segundos. Quité todas las
cookies de mi navegador y empecé a analizar los paquetes que recibía por la red con
Wireshark y como podéis ver, el intercambio es algo más complejo .
|
Figura 3: Intercambio de paquetes entre cliente y servidor de Cloudflare |
Estos son los paquetes que recibía. Hasta aquí ningún problema, ahora los analizaremos con mas detalle para explicar qué es lo que hay que automatizar con el objeto de saltarse la protección y poder seguir
scrappeando.
|
Figura 4: Cookie __cfdui enviada por Cloudflare |
Como podeis ver en la respuesta que aparece en la
Figura 4, el servidor te envía una
cookie con
Set Cookie:__cfdui. Esto nos lo guardaremos para más adelante ya que deberemos gestionar esta cookie en el resto de peticiones que vayamos a automatizar al tener que pasarnos por un navegador. Nos hará falta ese valor.
Lo importante es que dentro de lo que envía el servidor de
Cloudflare hay un código Javascript que complica todo el proceso ya que obliga al navegador a hacer operaciones. Estas operaciones en el pasado ya han sido analizadas en el pasado, como explicaba
David Barroso en su artículo sobre
Cloudflare: Héroe o Villano, pero lo van cambiando y actualizando con el tiempo.
|
Figura 5: Código ofuscado enviado por Cloudflare para detectar al navegador |
Este código lo que hace es enviarnos números en formato ofuscado
JavaScript con la forma de
!![]+[]. Para transcribir este código dentro de un
PHP a números tenemos que ejecutarlo y para ello nos hacen falta librerías de ejecución de
JavaScript en
PHP. Es necesario hacer el cálculo de resultado de esta fichero porque luego debe ir en la respuesta que le enviaremos a
Cloudflare para autenticarnos como
“no bots”.
Yo lo que hice - como no tenia mucha idea inicialmente de esta codificación y lo único que sabía es que daba un número, fue empezar a ejecutar código
JavaScript en otro sitio y descubrir qué quería decir cada uno de estos símbolos. Al final después de un buen rato descubri la forma en la que funcionaba - sí, lo hice a pico y pala y seguro que hay formas mucho mas eficientes de hacerlo pero yo lo hice así. Para ello me hice este código.
|
Figura 6: Código para interpretar desde PHP las operaciones ofuscadas en JavaScript |
Lo que hace este código para calcular el resultado de la operación es, si tenemos:
var t,r,a,f, dUFLoHl={"StGGclxDbFtT":+((!+[]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]))};\n
Primero separa los paréntesis. Es decir, primero
(!+[]+!![]+!![]+!![]+[]) y después
(!+[]+!![]+!![]+!![]+!![]+!![]+!![]). Luego hay que interpretar los números, donde los
!+[] y
!![] valen
1 y los
[] valen
0, pero si el
[] esta después de un
!![] (1) y en el siguiente paréntesis hay un
!+[] delante valdrá
10, tienen que cumplirse estas dos condiciones si no, valdrá
0. Por lo tanto en este ejemplo el numero valdrá
((40)+(7)) = 47.
Al final, lo que hace el código
JavaScript que envía
Cloudflare es aprovechar la codificación no numérica, igual que la herramienta de
Hyeroglyphy lo usa para hacer ataques XSS ofuscados.
Como hemos visto en el código JavaScript este numero que se llama
dUFLoHl.
StGGclxDbFtT se va sumando, restando y multiplicando por otros números hasta dar un valor final tras ejecutar todas las operaciones. En este caso el valor es:
2380330. Después, más abajo en el código que envía
Cloudflare, tenemos otra parte del código que nos dará una credenciales dentro del código
HTML en un formulario con
type hidden.
|
Figura 8: Formulario con credenciales para enviar la petición |
Estos valores serán necesarios para enviarlos junto a la siguiente petición que hagamos, que será ésta. Ojo, antes de enviar la petición en el código hay que esperar 5 segundos, ya que si no te esperas el servidor te deniega la entrada directamente por
"sospechoso de rápido". Como podeis ver enviamos la
cookie junto a la petición, y la
URL a la que se lo enviamos es esta:
http://host.com/cdn-cgi/l/chk_jschl?jschl_vc=18fcb850b47d7c30a18420c5d5dbfbb5&pass=1443549964.854-Z%2F65V%2BZx%2Br&jschl_answer=2380330
|
Figura 9: Envío de petición con los valores calculados |
Con los valores que nos han pasado
jschl_vc,
pass,
jschl_answer, en
jschl_answer lo que pondremos como valor es el número que hemos calculado antes. Ésta era la parte mas difícil luego ya la cosa es mas sencilla. Veramos lo que nos devuelve ahora. Al ver que le hemos dado una
URL correcta con
password correcto y todo, sólo nos devuelve un
302 Found, y un
Set Cokie, cf_clearance, etcétera. Estos datos simplemente los tendremos que guardar y ya está.
|
Figura 10: Resultados de la petición |
Puntualizo que a veces no sé porque también, a parte de enviar el
cf_clearance en la segunda respuesta, también envían el valor
__cfduid. Es decir realizan un reemplazo de la primera cookie por otra, lo que me generó unas cuantas comeduras de cabeza. Esta es una protección para hacer que las cookies que utilizan mueran muy rápidamente, por lo que hay que estar atentos a ver si cambian el valor de
__cfduid en cada petición. Después de todo esto sólo nos falta enviar una petición con las cookies. Yo utilizaba este codigo.
|
Figura 11: Código final para saltarse la protección |
Cabe decir que mi código no funciona el
100% de las veces. Funciona alrededor del
70-80%, ya que alguna otra medida de seguridad metida en alguna petición hace que no se ejecute correctamente, pero el poder saltar la protección de
Cloudflare en el
70-80% de las veces permite que se pueda
scrappear cualquier web de forma automática correctamente.
No lo hice con el objetivo de saltarme la protección de nada, sino de conseguir resolver el problema y aunque para alguno no sea gran cosa o no sea elegante, es la primera vez que consigo hacer algo de este estilo y estoy muy contento de haberlo conseguido, así que si estás trabado intentando resolver algo y no te sale, sé constante que la satisfacción de conseguirlo merece la pena el sacrificio.
Y hasta aquí el post! Un saludo maligno!
Autor: Alejandro García
Gracias, como siempre. Chorrada de regalo: https://buffer-pictures.s3.amazonaws.com/ecf704408c7078fe1b822fee1c7b99f6.9801e31a3103c06fb006e4a8faf3263a.gif
ResponderEliminarEnhorabuena Alejandro!! Gran trabajo ;D
ResponderEliminarFelicidades por el trabajo.
ResponderEliminarEn mi caso me encontré con el mismo problema pero lo resolví de otro modo. Al final los servicios de Cloudflare o Akamai actúan como proxy y si se consigue averiguar la IP origen se puede hacer el scrapping directamente sobre ésta. La gente de Security Idiots publicaron un tutorial explicando algunos métodos para averiguar la IP origen. Aunque la mayoría de esos métodos ya están obsoletos existen otros "trucos" para dar con la IP origen.
Saludos.
Podías haber evaluado el código en NodeJS y te habrías ahorrado la investigación de la ofuscación y las expresiones regulares.
ResponderEliminarMuy interesante apreciación . ¿algún tuto para empezar?
EliminarEste comentario ha sido eliminado por el autor.
ResponderEliminarEste comentario ha sido eliminado por el autor.
ResponderEliminarEl artículo muy bueno!!!
ResponderEliminargrande como siempre , es mejor hacer el trabajo a mano asi se entiende lo que se hace y se aprende mejor ,exelente trabajo
ResponderEliminarInteresante
ResponderEliminarComo puedo contratarte para un servicio ?
ResponderEliminar