CommandsStyle

jueves, 22 de junio de 2017

Punto de acceso... al AVERNO!

Hoy toca montar un punto del acceso wifi, y como lo vamos a controlar nosotros (que para eso es nuestro punto de acceso) también podremos visualizar el tráfico que viaja por el punto de acceso.

Punto de acceso... al AVERNO!
Punto de acceso... al AVERNO!

Para la realización de esta gran hazaña, vamos a utilizar:
  • 1 Raspberry PI (En mi caso una Raspberry pi)
    • Utilizaremos Raspbian como sistema operativo.
    • Por supuesto vas a necesitar cable de alimentación, tarjeta... ya sabes, el material bélico básico para que arranque la Raspberry pi.
  • 1 tarjeta de red (ALFA Network AWUS051NH V2) Esta tarjeta es opcional si utilizamos una Raspberry Pi 3, ya que esa versión, incorpora una tarjeta wifi.
    • He seleccionado esta tarjeta, ya que permite ponerla en modo monitor y en modo punto de acceso.

Raspberry Pi
Raspberry Pi

ALFA Network AWUS051NH
ALFA Network AWUS051NH


Lo primero que tenemos que hacer es conectar todos los aparejos a la Raspberry pi y enchufarla para que funcione (Si vale, ya sé que este paso me lo podía haber ahorrado...).

Lo siguiente que tenemos que hacer es instalar los paquetes hostapd e isc-dhcp-server.
El paquete hostapd nos permite poner la tarjeta en modo punto de acceso y configurar la red wifi que vamos a servir.

El paquete isc-dhcp-server es un pequeño servidor dhcp. Lo necesitamos porque queremos que los dispositivos que se conecten al punto de acceso obtengan una IP automáticamente.
Para instalarlos, utilizamos el siguiente comando:

sudo apt-get install hostapd isc-dhcp-server


Llegados a este punto, nos interesa ver cuáles son las interfaces de red que tenemos. Para ello lanzamos el siguiente comando:

ifconfig

Y en este caso, vamos a suponer que me entrega los siguientes datos:
La interfaz eth0 es la interfaz por la que la Raspberry pi se conecta a internet utilizando un cable RJ-45
La interfaz wlan0 es la tarjeta wifi USB (La ALFA Network AWUS051NH).

Lo siguiente que tenemos que hacer, es modificar el archivo "/etc/dhcp/dhcpd.conf".
Este fichero nos va a permitir configurar el servidor dhcp.
En este caso vamos a utilizar el editor de texto vi, pero podríamos utilizar el que queramos.

Para editar el documento, lanzamos el siguiente comando:

sudo vi /etc/dhcp/dhcpd.conf

En este fichero, localizamos las siguientes líneas:

option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;

y como esta configuración no nos interesa (no nos interesa, es porque no vamos a tener un servidor DNS ni un dominio), pues... lo comentamos y para ello añadimos una almohadilla (#) al inicio de cada línea.

Deberían quedarnos así:
#option domain-name "example.org";
#option domain-name-servers ns1.example.org, ns2.example.org;

Ahora buscamos la línea:

#authoritative;

y la des comentamos. Con esto habilitamos el servidor como DHCP "principal" que como no vamos a tener otro pues... que menos que darle ese privilegio...

Nos debería quedar la siguiente línea:
authoritative;

Ahora tenemos que añadir las siguientes líneas:

subnet 192.168.100.0 netmask 255.255.255.0 {
    range 192.168.100.10 192.168.100.50;
    option broadcast-address 192.168.100.255;
    option routers 192.168.100.1;
    default-lease-time 600;
    max-lease-time 7200;
    option domain-name "local";
    option domain-name-servers 8.8.8.8, 8.8.4.4;
}

Lo que le indicamos en las líneas anteriores, es que la red utilizada será la 192.168.100.0 con mascará 255.255.255.0.
Las IPs proporcionadas por el servidor dhcp serán de la 192.168.100.10 a la 192.168.100.50.
La puerta de enlace/gateway será la IP 192.168.100.1 y los servidores DNS que proporcionaremos serán los de Google (8.8.8.8 y 8.8.4.4). Aquí podemos poner estor servidores DNS, o poner los que nos proporcione nuestro ISP.

Ahora tenemos que modificar el fichero "/etc/default/isc-dhcp-server".
En este fichero vamos a indicar en que interfaz de red queremos que se utilice el servidor dhcp. En nuestro caso, queremos que sea la interfaz wlan0, que es la tarjeta en la que vamos a levantar el punto de acceso y a la que se conectaran los clientes de la red wifi.

Para ello, utilizaremos el siguiente comando:

sudo vi /etc/default/isc-dhcp-server

buscamos la siguiente línea:

INTERFACES=""

y la modificamos para que quede de la siguiente manera:

INTERFACES="wlan0"

Llegados a este punto, tenemos que dar una dirección IP fija a la tarjeta de red en la que vamos a levantar el punto de acceso ya que en la configuración del servidor dhcp hemos puesto que el Gateway seria la dirección 192.168.100.1.

Para ello, tenemos que modificar el fichero "/etc/network/interfaces". Utilizaremos el siguiente comando:

sudo vi /etc/network/interfaces

Buscamos la siguiente línea:
allow-hotplug wlan0

y modificamos el fichero, para que las líneas siguientes nos queden de la siguiente manera:

allow-hotplug wlan0
iface wlan0 inet static
  address 192.168.100.1
  netmask 255.255.255.0

Una vez modificado el fichero, vamos a asignar la IP a la tarjeta de red wlan0.
Utilizaremos los siguientes comandos:

sudo ifdown wlan0
sudo ifconfig wlan0 192.168.100.1

En este punto, ya tenemos configurado el servidor dhcp.
Ahora vamos a configurar el punto de acceso (La red wifi para que nos entendamos).

Para ello, vamos a crear el fichero "/etc/hostapd/hostapd.conf"

Utilizaremos el siguiente comando:

sudo vi /etc/hostapd/hostapd.conf

El contenido del fichero que vamos a insertar es el siguiente:

interface=wlan0
ssid=puntoAccesoDelAverno
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=contrasena
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

Con este contenido habilitamos la wifi protegida mediante WPA2.

Si queremos una wifi sin contraseña (Que si queremos un punto de acceso al averno/malicioso puede que nos interese para que se pueda conectar la gente libremente... guiño guiño...)

La configuración seria la siguiente:
interface=wlan0
ssid=puntoAccesoDelAverno
channel=6


Ahora tenemos que indicarle a hostapd donde está el fichero de configuración que acabamos de crear, para ello, modificamos el fichero "/etc/default/hostapd".

Utilizaremos el siguiente comando:

sudo vi /etc/default/hostapd

Localizamos la siguiente línea:
#DAEMON_CONF=""

y la modificamos para que quede de la siguiente manera:
DAEMON_CONF="/etc/hostapd/hostapd.conf"

Ahora vamos a habilitar el forwarding.
Utilizaremos el siguiente comando:

sudo su
echo 1 > /proc/sys/net/ipv4/ip_forward
exit

Pero como queremos que el forwarding se habilite automáticamente cada vez que reiniciemos la Raspberry pi, vamos a modificar el fichero "/etc/sysctl.conf".

Para ello utilizamos el comando:

sudo vi /etc/sysctl.conf

Localizamos la línea:

#net.ipv4.ip_forward=1

y la des comentamos para que quede:

net.ipv4.ip_forward=1


El siguiente paso es configurar iptables para que nos haga el enrutamiento entre la red wifi del punto del acceso y la red cableada (No es obligatorio que sea una red cableada, podemos hacer que nuestro punto de acceso se conecte a una red wifi, si tenéis dudas de cómo hacer esto, ponedlo en los comentarios :) )

Para configurar iptables, utilizaremos los siguientes comandos:

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT

Como queremos que esta configuración esté disponible cada vez que arrancamos la raspberry pi, ejecutamos el siguiente comando:

sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"

Con esto almacenamos la configuración actual de iptables en el fichero "/etc/iptables.ipv4.nat"

Para que se restaure la configuración cuando reiniciemos, vamos a modificar el fichero "/etc/network/interfaces".

Utilizamos el comando:

sudo vi /etc/network/interfaces

y al final, añadimos la siguiente línea:

up iptables-restore < /etc/iptables.ipv4.nat

Vamos a levantar manualmente los dos servicios que hemos configurado anteriormente.
Para ello, utilizaremos los siguientes comandos:

sudo service hostapd start
sudo service isc-dhcp-server start

Si queremos que se ejecuten al reiniciar la Raspberry pi, tenemos que ejecutar los siguientes comandos:

sudo update-rc.d hostapd enable
sudo update-rc.d isc-dhcp-server enable


Llegados a este punto, si buscamos con algún ordenador o móvil las redes disponibles, deberíamos ver que hay una red wifi llamada puntoAccesoDelAverno.

Ahora podemos analizar el tráfico que pasa por nuestro punto de acceso y podemos combinarlos con las técnicas que hemos visto en los post anteriores, así como otras que veremos en el futuro ;)

miércoles, 7 de junio de 2017

Almacenar las contraseñas para hacer un sistema de login

Hola de nuevo.
Hoy vamos a tratar una de las preguntas con que nos encontramos cuando vamos a hacer una aplicación y queremos hacer un sistema de login.



¿Como almaceno la contraseña?

Para responder a esta pregunta, primero vamos a imaginarnos que para almacenar la información de login del usuario vamos a utilizar una tabla como la que vemos a continuación:

Tabla users
id username password

En la columna id almacenaremos los identificadores de usuarios (Esta columna en realidad no la vamos a usar, pero me gusta ponerla ;)).
En la columna username almacenaremos el nombre de los usuarios.
En la columna password... bueno ahora veremos lo que tenemos que almacenar aquí.

Opción 1
La primera de las opciones que se nos puede ocurrir es almacenar la contraseña en texto plano.
De esta forma cuando un usuario intente hacer login en nuestra aplicación, nosotros vamos a buscar el registro por username y luego, compararemos que la contraseña que nos ha dado el usuario es igual a la contraseña que tenemos almacenada en nuestra tabla.

Por ejemplo:
Supongamos que tenemos la siguiente tabla users:

Tabla users
id username password
1 Juan ContraseñaDeJuan
2 Manuel ContraseñaDeManuel

Si el usuario con username Juan intenta hacer login con la contraseña MiContraseña.

  • Primero recuperamos el registro correspondiente al username Juan.
  • Segundo, compararemos que la contraseña Micontraseña es igual a ContraseñaDeJuan.

Como Micontraseña y ContraseñaDeJuan no son la misma cadena de caracteres (¿Es evidente no? :P) rechazamos el login del usuario.

Si el usuario por el contrario introduce el username Juan y la contraseña ContraseñaDeJuan daríamos el login por bueno y dejaríamos acceder al usuario a nuestra aplicación.

Bien, hemos visto cómo funciona este sistema, pero tiene un problema.
Si por alguna razón (Dios no lo quiera), nos roban los datos de la tabla users, el atacante podrá acceder a la aplicación como un usuario normal ya que conocerá los username y las contraseñas asociadas a esos usernames.

Esto claramente es un problema. (Bueno, son 2 problemas, uno que puede acceder como un usuario normal y otro que te han robado los datos de la base de datos ;) )
Visto este problema, vamos a darle una primera solución.

Opción 2
Vamos a hacer un hash de la contraseña y vamos a almacenarlo en la base de datos.

Una función hash es una función que, dada una entrada, nos ofrece una salida (normalmente de longitud fija) y lo interesante de las funciones hash, es que se puede calcular el hash de un valor, pero no se puede hacer la operación inversa, es decir, teniendo un hash, no puedes calcular qué valor a producido ese hash.

Hay varias funciones hash, como por ejemplo MD5, SHA-1, SHA-2...

Sabiendo esto, nuestro ejemplo de login quedaría de la siguiente manera:

Tabla users
id username password
1 Juan 63819e896e0eb74eea21027dd691f98edfa080e23677955038bcd57582881fcb
2 Manuel 86e11146f8f7a2e213dcf600976aa9e00b125d81be91c22fd193019f62cc36c4

Supongamos que Juan intenta hacer login en nuestra aplicación con la contraseña MiContraseña:

  • Primero, recuperamos el registro correspondiente al username Juan.
  • Segundo, hacemos el hash de la contraseña introducida por el usuario en este caso MiContraseña.
  • Tercero, comparamos el hash recuperado de la base de datos con el hash que hemos calculado en el paso anterior.


Si el usuario introduce el username Juan y la contraseña MiContraseña (El hash SHA-2 es 1ef1870f76d31f4b5e877996faf904fd5214135c9967100ff3eda9f568b4d751), compararemos el hash SHA-2 de MiContraseña, con el campo password del registro correspondiente al username Juan.

Como ambos hashes no son iguales, rechazamos el login del usuario.

Si por el contrario, introduce el valor ContraseñaDeJuan como contraseña, cuando calculemos el hash SHA-2 de la contraseña veremos que es igual al que tenemos almacenado en el registro para el username Juan y daremos el login por bueno.

Pero este sistema sigue teniendo un pequeño problema.
Imaginemos de nuevo que nos roban los datos de la tabla. Un atacante podría calcular los hashes SHA-2 de todas las cadenas (o de las contraseñas más comunes) almacenando el par palabra-hash(palabra).

Con lo que únicamente tendría que buscar en esa tabla de hashes pre-calculados el hash correspondiente al que tenemos almacenados en nuestra tabla, para ver que palabra genera ese hash.

Luego podría utilizar el username y esa palabra para hacer login como un usuario normal de nuestra aplicación.

A esas tablas de hashes, se las suele llamar Rainbow Tables.

Llegados a este punto, tenemos que darle una solución a este nuevo problema.

Opción 3
Esta solución pasa por la utilización de un salt.
En nuestro caso, el salt, va a ser una cadena aleatoria que utilizaremos junto con la contraseña para generar el hash que vamos a almacenar en la base de datos.

En este caso, por ejemplo, cuando vallamos a generar el hash de la contraseña, vamos a concatenar la contraseña con el salt (vamos a utilizar la concatenación, pero podríamos realizar cual otra operación que quisiéramos).

También tendremos que crear una nueva fila para almacenar el salt, con lo que la tabla users nos quedara como vemos a continuación.
Tabla users
id username salt password
1 Juan idav fe2951935dbd28541b561ba5be8d06c4378f46b8a05dabe0e95c5fb5a515ee72
2 Manuel iwns e2c5a2a35873aaa35a1a5b66d5ed8f82a483fa31f307772e06eae0aa4ff9d413


Supongamos ahora que Juan intenta hacer login en nuestra aplicación con la contraseña MiContraseña:


  • Primero, recuperamos el registro correspondiente al username Juan.
  • Segundo, concatenamos el salt correspondiente a Juan con la contraseña introducida. El resultado es MiContraseñaidav.
  • Tercero, calculamos el hash SHA-2 de MiContraseñaidav que es 37884538e6ea5efc921f602bb5793810b8106a6a290e91ee80a28d98c608476c
  • Cuarto, comprobamos que el hash que hemos calculado, es el mismo que tenemos almacenado en la base de datos.

  • Como podemos ver, el hash no coincide, por lo que rechazamos el login.
    Por el contrario, si la contraseña introducida hubiese sido ContraseñaDeJuan, al concatenarle el salt
    el resultado habría sido ContraseñaDeJuanidav.
    Como el hash SHA-2 de ContraseñaDeJuanidav es fe2951935dbd28541b561ba5be8d06c4378f46b8a05dabe0e95c5fb5a515ee72 el usuario habría echo login correctamente.

    Pero ¿Que ventaja me proporciona el uso del salt?
    Supongamos que nos roban de nuevo los datos de la tabla.

    Vamos a suponer que el atacante tiene una rainbow table en la que tiene unos hashes que hashes coinciden con algunos que tenemos guardados en la base de datos.

    Supongamos que una de las palabras de la rainbow table es  PATATA da como resultado el hash asociado a Juan, fe2951935dbd28541b561ba5be8d06c4378f46b8a05dabe0e95c5fb5a515ee72.

    El atacante introducirá PATATA como contraseña, pero nosotros a PATATA le vamos a concatenar idav, que es el salt correspondiente a Juan. con lo cual el hash SHA-2 correspondiente a PATATAidav no nos dará como resultado el mismo hash que PATATA y por lo tanto el atacante no podrá hacer login.

    En este punto, podríamos pensar, bueno, como el atacante ya tiene el salt, podría hacerse una rainbow table concatenando todas las palabras y calculando sus hashes.
    Esto es cierto, pero hacer esto, lleva una cantidad de tiempo elevada (podría utilizar fuerza bruta o un ataque de diccionario).
    Además, esto únicamente le valdría para calcular la contraseña de un usuario, ya que para cada usuario, el salt es diferente y por tanto, puede que en un hipotético caso se averigüe la contraseña de un usuario, pero no la del resto (a no ser que repita este proceso para cada uno de ellos).


    Espero que después de esta parrafada haya quedado claro cuál es el mejor de los 3 métodos para hacer un sistema de login. Si tenéis alguna duda, podéis plantearla en los comentarios para intentar resolverla.

    Hasta la siguiente!