OSINT + Python = hacking a medida

El pasado 10 y 11 de mayo se celebró el curso de Perito Informático Forense en Reus (España) por la Asociación Nacional de Tasadores y Peritos Judiciales Informáticos (ANTPJI), de la que soy miembro y profesor en los cursos, donde tuve el placer de dar una charla sobre dos de mis pasiones como son Python y OSINT (Open Source Intelligence).

Python es un estupendo lenguaje para desarrollar rápidamente todo tipo de aplicaciones potentes y con multitud de librerías para realizar exploits, ingeniería inversa, herramientas web y más. Sin duda un conocimiento útil para cualquier experto en seguridad.

Internet es inmenso y abarca toda información inimaginable, por ello las técnicas OSINT son de vital importancia para recolectar, analizar y presentar esta información.

Para este curso decidí que sería interesante para los asistentes aprender a desarrollar simples herramientas (scripts) que les permitan realizar OSINT mediante Python con una serie de ejercicios prácticos con un objetivo concreto cada uno.

La presentación y el código están disponibles en la web de VULNEX.

Nota: he quitado la query de Google Hacking de los scripts para que el lector pueda meter su propia query.

Herramienta #1

Objetivo: buscar miembros ANTPJI en LinkedIn mediante Google Custom Search API

Estos scripts son muy sencillos y hacen lo mismo pero de forma diferente. El primero utiliza el Google API Client, mientras que el segundo utiliza la fantástica librería Requests.

En este script estamos utilizando un poco de Google Hacking para buscar miembros de la asociación en LinkedIn.


# File: ex1_a.py
# Date: 05/14/13
# Author: Simon Roses Femerling
# Desc: Basic Google Hacking 
#
# VULNEX (C) 2013
# www.vulnex.com

import const
from apiclient.discovery import build
import pprint

# your google hacking query
query=''
query_params=''

doquery=query+query_params

service = build("customsearch","v1",developerKey=const.cse_token)

res = service.cse().list(
    q=doquery,
    cx=const.cse_id,
    num=10).execute()

pprint.pprint(res)

# VULNEX EOF

# File: ex1_b.py        
# Date: 05/14/13
# Author: Simon Roses Femerling
# Desc: Simple Google Hacking                
#
# VULNEX (C) 2013
# www.vulnex.com

import requests
import json
import urllib
import const

site="https://www.googleapis.com/customsearch/v1?key="

# Your Google Hacking query
query='' 
query_params='' 

url=site+const.cse_token+"&cx="+const.cse_id+"&q=" + urllib.quote(query+query_params)
response = requests.get(url)
print json.dumps(response.json,indent=4)

# VULNEX EOF

Al ejecutar cualquiera de estos scripts obtenemos el siguiente resultado:

py_osint_img1

No demasiado interesante por el momento :)

Herramienta #2

Objetivo: obtener las fotos de los miembros ANTPJI en LinkedIn mediante Google Custom Search API.

El siguiente script obtiene las fotos de los miembros de la asociación en LinkedIn y de paso sacamos los metadatos ;) El script genera una página HTML con todas las fotos.

Librerías utilizadas: Google API Client, PIL, Requests y Markup.


# File: ex2.py         
# Date: 05/14/13
# Author: Simon Roses Femerling
# Desc: Download picture and extract metadata               
#
# VULNEX (C) 2013
# www.vulnex.com

import const
from apiclient.discovery import build
import pprint
import os
from PIL import Image
from StringIO import StringIO
from PIL.ExifTags import TAGS
import requests
import markup

def do_query(istart=0):
    if istart == 0:
        res = service.cse().list(
        q=doquery,
        cx=const.cse_id,
        num=10).execute()
    else:
        res = service.cse().list(
        q=doquery,
        cx=const.cse_id,
        num=10,
        start=istart).execute()
    return res

pic_id=1
do_stop=10
cnt=1

page=markup.page()

# Set page title
page.init(title="ANTPJI OSINT") 
page.h1("ANTPJI OSINT")

# Set output directory
out_dir = "pics_gepl"

# Your Google Hacking query 
query=''
query_params=''

doquery=query+query_params

service = build("customsearch","v1",developerKey=const.cse_token)

if not os.path.exists(out_dir):
    os.makedirs(out_dir)

res=[]
while True:
    if cnt==1:
        res = do_query()
    else:
        if not res['queries'].has_key("nextPage"): break
        res = do_query(res['queries']['nextPage'][0]['startIndex'])
    cnt+=1
    if cnt > do_stop: break
    if res.has_key("items"):
        for item in res['items']:
            name=""
            if not item.has_key('pagemap'): continue
            if not item['pagemap'].has_key('hcard'): continue
            hcard = item['pagemap']['hcard']
            for card in hcard:
                pic_url=""
                if 'title' in card:
                    if 'fn' in card: name = card['fn']
                    if 'photo' in card: pic_url = card['photo']
                if pic_url != "":   
                    image = requests.get(pic_url)
                    pic_n = os.path.join(out_dir,"%s.jpg") % pic_id
                    file = open(pic_n,"w")
                    pic_id+=1
                    try:
                        i = Image.open(StringIO(image.content))
                        if hasattr(i,"_getexif"):
                            ret = {}
                            info = i._getexif()
                            if info:
                                for k,v in info.items():
                                    decode = TAGS.get(k,v)
                                    ret[decode] = v
                                print ret
                        i.save(file,"JPEG")
                        page.p(name.encode('ascii','ignore')) 
                        page.img(src=pic_n)
                        page.br()
                        page.br()
                    except IOError, e:
                        print "error: %s" % e
                    file.close()            

# Set your output filename
with open('index_gepl.html','w') as fp:
    fp.write(str(page))

# VULNEX EOF

Y este es el resultado:

py_osint_img2

Con unas pocas líneas de código hemos conseguido una herramienta bastante interesante.

Herramienta #3

Objetivo: ¿cuál es la relación de los miembros de ANTPJI en LinkedIn?

Con este script buscamos la relación entre los miembros de la asociación en LinkedIn y creamos un gráfico que relaciona las palabras.

Librerías utilizadas: Google API Client, NetworkX y Matplotlib.


# File: ex3.py         
# Date: 05/14/13
# Author: Simon Roses Femerling
# Desc: Build graph from profiles                
#
# VULNEX (C) 2013
# www.vulnex.com

import const
from apiclient.discovery import build
import networkx as nx
import matplotlib.pyplot as plt

def do_query(istart=0):
    if istart == 0:
        res = service.cse().list(
        q=doquery,
        cx=const.cse_id,
        num=10).execute()
    else:
        res = service.cse().list(
        q=doquery,
        cx=const.cse_id,
        num=10,
        start=istart).execute()
    return res

do_stop=10
cnt=1

# Your Google Hacking query here
query=''
query_params=''

doquery=query+query_params

service = build("customsearch","v1",developerKey=const.cse_token)

G=nx.DiGraph()
res=[]
while True:
    if cnt==1:
        res = do_query()
    else:
        if not res['queries'].has_key("nextPage"): break
        res = do_query(res['queries']['nextPage'][0]['startIndex'])
    cnt+=1
    if cnt > do_stop: break
    if res.has_key("items"):
        for item in res['items']:
            name=""
            if not item.has_key('pagemap'): continue
            if not item['pagemap'].has_key('hcard'): continue
            hcard = item['pagemap']['hcard']
            for card in hcard:
                if 'title' in card:
                    if 'fn' in card: name = card['fn']
                G.add_edge(name,card["fn"])     

plt.figure(figsize=(30,30))
nx.draw(G)
# Set your output filename
plt.savefig('antpji_rela_map.png')

# VULNEX EOF

Y este es el gráfico que se genera:

py_osint_img3

Herramienta #4

Objetivo: ¿de qué se habla en el Twitter de la asociación?

Este script baja los últimos tweets de la cuenta de la asociación y genera una nube de palabras. Útil para ver rápidamente de qué se habla.

Librerías utilizadas: Requests, pytagcloud.


# File: ex4.py         
# Date: 05/14/13
# Author: Simon Roses Femerling
# Desc: Create word cloud               
#
# VULNEX (C) 2013
# www.vulnex.com

import requests
import json
import urllib
import const

from pytagcloud import create_tag_image, make_tags
from pytagcloud.lang.counter import get_tag_counts

site="http://search.twitter.com/search.json?q="

# Your query here
query=""

url=site+urllib.quote(query)

response = requests.get(url)

tag = []
for res in response.json["results"]:
    tag.append(res["text"].encode('ascii','ignore'))

text = "%s" % "".join(tag)  
tags = make_tags(get_tag_counts(text),maxsize=100)
# Set your output filename
create_tag_image(tags,"antpji_word_cloud.png", size=(600,500), fontname="Lobster")

# VULNEX EOF

Y esta es la nube de palabras:

py_osint_img4

Herramienta #5

Objetivo: ¿dónde tienen cuenta los alias que participan en el Twitter de ANTPJI?

El siguiente script extrae los alias que han publicado o mencionado en el Twitter de la asociación y se comprueba si existe ese alias en 160 redes sociales.

Librerías utilizadas: Requests.


# File: ex5.py         
# Date: 05/14/13
# Author: Simon Roses Femerling
# Desc: Check usernames on 160 social network sites               
#
# VULNEX (C) 2013
# www.vulnex.com

import requests
import json
import urllib
import const
import pprint

site="http://search.twitter.com/search.json?q="

# Your query here
query=""

url=site+urllib.quote(query)

print "Recolectando alias en Twitter: %s\n" % query
response = requests.get(url)

users = []

for res in response.json["results"]:
    if res.has_key('to_user'):
        if not res['to_user'] in users: users.append(str(res["to_user"]))
    if res.has_key('from_user'):
        if not res['from_user'] in users: users.append(str(res["from_user"]))

print "ALIAS-> %s" % users

print "\nComprobrando alias en 160 websites\n"
for username in users:  
    for service in const.services:  
            try:    
            res1 = requests.get('http://checkusernames.com/usercheckv2.php?target=' + service + '&username=' + username, headers={'X-Requested-With': 'XMLHttpRequest'}).text
            if 'notavailable' in res1: 
                print ""
                print username + " -> " + service 
                print "" 
            except Exception as e:  
                print e 

# VULNEX EOF

Y el resultado es el siguiente:

py_osint_img5

Herramienta #6

Objetivo: ¿se pueden obtener los metadatos en las fotos de ANTPJI?

Este script baja las fotos relacionadas con la asociación en Google y extrae los metadatos.

Librerías utilizadas: Requests, PIL y Markup.


# File: ex6.py         
# Date: 05/14/13
# Author: Simon Roses Femerling
# Desc: Download pictures from Google and extract metadata               
#
# VULNEX (C) 2013
# www.vulnex.com

import const
from apiclient.discovery import build
import pprint
import os
from PIL import Image
from StringIO import StringIO
from PIL.ExifTags import TAGS
import requests
import markup

def do_query(istart=0):
    if istart == 0:
        res = service.cse().list(
        q=doquery,
        cx=const.cse_id,
        num=10).execute()
    else:
        res = service.cse().list(
        q=doquery,
        cx=const.cse_id,
        num=10,
        start=istart).execute()
    return res

pic_id=1
do_stop=10
cnt=1

page=markup.page()
# Set your page title
page.init(title="ANTPJI OSINT") 
page.h1("ANTPJI OSINT")

# Set output directory
out_dir = "pics_gepl"

# Define your Google hacking query here
query=''
query_params=''

doquery=query+query_params

service = build("customsearch","v1",developerKey=const.cse_token)

if not os.path.exists(out_dir):
    os.makedirs(out_dir)

res=[]
while True:
    if cnt==1:
        res = do_query()
    else:
        if not res['queries'].has_key("nextPage"): break
        res = do_query(res['queries']['nextPage'][0]['startIndex'])
    cnt+=1
    if cnt > do_stop: break
    if res.has_key("items"):
        for item in res['items']:
            name=""
            if not item.has_key('pagemap'): continue
            if not item['pagemap'].has_key('hcard'): continue
            hcard = item['pagemap']['hcard']
            for card in hcard:
                pic_url=""
                if 'title' in card:
                    if 'fn' in card: name = card['fn']
                    if 'photo' in card: pic_url = card['photo']
                if pic_url != "":   
                    image = requests.get(pic_url)
                    pic_n = os.path.join(out_dir,"%s.jpg") % pic_id
                    file = open(pic_n,"w")
                    pic_id+=1
                    try:
                        i = Image.open(StringIO(image.content))
                        if hasattr(i,"_getexif"):
                            ret = {}
                            info = i._getexif()
                            if info:
                                for k,v in info.items():
                                    decode = TAGS.get(k,v)
                                    ret[decode] = v
                                print ret
                        i.save(file,"JPEG")
                        page.p(name.encode('ascii','ignore')) 
                        page.img(src=pic_n)
                        page.br()
                        page.br()
                    except IOError, e:
                        print "error: %s" % e
                    file.close()            

# Set your output filename
with open('index_gepl.html','w') as fp:
    fp.write(str(page))

# VULNEX EOF

Una imagen vale más que mil palabras!

py_osint_img6

Como hemos visto a lo largo de este artículo podemos escribir sofisticadas herramientas de OSINT de forma sencilla con un poco de Python que nos permiten recabar mucha información sobre individuos o colectivos.

Si te gustaría que profundizara sobre algún tema en Python y OSINT por favor házmelo saber :)

¿Y tú qué herramientas utilizas para OSINT?

— Simon Roses Femerling

Referencias

Publicado en Hacking, Hacking Etico, Privacidad, Seguridad, Tecnologia | Etiquetado , , , , , , , | Deja un comentario

Mi lista de 10 ciberarmas

Hace un par de semanas los medios publicaban que el US Air Force ha clasificado 6 herramientas como ciberarmas, sin duda un hot topic. Para este post yo haré lo mismo y pondré un listado de 10 herramientas que podrían ser ciberarmas.

Mi criterio de selección va en función de su utilidad, capacidades y que sea open source o gratis por lo menos.

Lógicamente existen más herramientas que me gustan o que utilizo, pero creo que esta lista es una estupenda recopilación para realizar ataques en red y sistemas, ingeniería inversa, análisis de tráfico, ingeniería social, búsqueda de vulnerabilidades y desarrollo de exploits, vamos, que debería estar en el toolkit de todo pentester :)

  1. Metasploit: la herramienta de hacking ético por excelencia.
  2. SET: amplias opciones para realizar ataques de ingeniería social.
  3. Dsploit: nada como llevar un toolkit de hacking ético en el móvil, para Android.
  4. Nmap: el popular escáner de puertos y más.
  5. WireShark: para analizar el tráfico de red de forma simple y potente.
  6. Ettercap: todo tipo de ataques en red.
  7. Immunity Debugger: un poco de ingeniería inversa combinada con scripting en Python.
  8. Mona: potente script para la herramienta anterior o Wingdb para desarrollar exploits.
  9. Peach: completo framework para buscar vulnerabilidades mediante fuzzing.
  10. Androguard: ingeniería inversa para Apps Android.

¿Cuál es tu lista de 10 ciberarmas?

— Simon Roses Femerling

Publicado en Hacking, Hacking Etico, Seguridad, Tecnologia | Etiquetado , , , , , , | Deja un comentario

AppSec: Mejora la seguridad de tu software con GCC Stack Protector Strong

El otro día ayudando a un cliente a desarrollar software seguro se me ocurrió que este tema podría ser de interés para mis lectores. Lógicamente esta temática es bastante amplia, pero en este artículo me centraré: es un patch para el compilador GCC que mejora la protección de stack protector (stack canary) mitigando las vulnerabilidades del tipo buffer overflow.

Stack Protector Strong es un patch desarrollado en Google y aplicado al Proyecto Chromium (Navegador Chromium y Chromium OS) que mejora sustancialmente esta defensa. Por defecto en GGC tenemos los parámetros –fstack-protector y –fstack-protector-all: el primero analiza cada función en el código y si detecta una posible vulnerabilidad aplica la defensa al compilar el programa (el programador no tiene que hacer nada, bueno sí, desarrollar de forma segura ;)), mientras que el segundo parámetro aplica esta defensa a TODAS las funciones del programa sin validar si son vulnerables.

Ambas opciones tienen sus respectivos problemas: la primera opción (-fstack-protector) está limitada por el código que considera vulnerable, mientras que la segunda (-fstack-protector-all) es demasiado agresiva y afecta al rendimiento de la aplicación.

Debido a estos problemas en Google optaron por desarrollar un tercer parámetro, -fstack-protector-strong, que abarca más casos de código vulnerable sin sacrificar rendimiento. En la figura 1 podemos ver una comparativa entre –fstack-protector y –fstack-protector-strong.

stack_protector_VS
Fig. 1 – -fstack-protector vs. –fstack-protector-strong

Claramente es una mejora sustancial que abarca más clases de posibles vulnerabilidades en código, pero basta de teoría y pasemos a un ejercicio práctico donde vamos a instalar el patch a la última versión de GCC 4.8.0 publicada recientemente en un Linux Debian 6.0.

El primer paso es bajarnos la versión GCC que nos interese parchear. El parche se escribió para la versión 4.6, aunque he probado con las versiones 4.7 y 4.8 y funciona correctamente. Para ello ejecutamos el comando wget con la URL de GCC y luego lo descomprimimos (ver figura 2).

gcc_cap1
Fig. 2 – Bajando GCC

Para compilar GCC debemos tener una serie de librerías instaladas por lo que utilizaremos el comando apt-get para su instalación (ver figura 3):

  • Build-essential
  • libgmp3-dev
  • libmpfr-dev
  • libmpc-dev
  • zip
  • autogen

gcc_cap2
Fig. 3 – Instalando paquetes necesarios para compilar GCC

Ahora bajamos el parche –fstack-protector-strong de aquí. El parche está compuesto por 5 ficheros diff.

gcc_cap4
Fig. 4 – Parches bajados

A continuación procedemos a parchear GCC y debemos seguir el orden que aparece en la figura 5. Prestad especial atención al orden de los directorios dentro de GCC.

gcc_cap5
Fig. 5 – Aplicando parches a GGC

Una vez que tengamos GCC parcheado podemos compilarlo, para su instalación en el sistema necesitamos tener privilegios de administrador (ver figura 6). Mientras el comando se ejecuta podemos leer otros artículos de este blog ya que el proceso tarda bastante :)

gcc_cap7
Fig. 6 – Compilando e instalando GCC

Ahora ya estamos listos para compilar programas con la última versión de GCC y con una mejor defensa ante vulnerabilidades buffer overflow.

En la figura 7 compilamos un programa vulnerable con el parámetro –fstack-protector-strong.

gcc_cap9
Fig. 7 – Probando –fstack-protector-strong

Al desensamblar (reversing) myapp podemos ver que se ha aplicado esta defensa en varias funciones y que con –fstack-protector no se hubiera aplicado (aunque este ejercicio lo dejo para otro artículo).

Actualmente este parche no está por defecto en GCC pero esperemos que lo esté en futuras versiones, así como nuevas y mejores defensas.

Es cierto que existen vectores de ataque para saltarse esta protección, aunque toda defensa es poca y hoy en día todos los compiladores modernos (GCC, Visual Studio y LLVM) incorporan diversas defensas que los programadores deberían utilizar siempre.

Sin duda el uso de estas defensas en los compiladores no quita la necesidad de desarrollar software de forma segura utilizando un marco de desarrollo seguro como son el MS SDL o el OpenSAMM.

¿Qué parámetros de seguridad utilizas al compilar software?

— Simon Roses Femerling

Publicado en Hacking Etico, Modelo de Amenazas, Privacidad, SDL, Seguridad, Tecnologia | Etiquetado , , , , , , , | Deja un comentario