En esta serie de artículos vamos a hablar sobre algunas técnicas de hacking que podemos facilitar, utilizando el lenguaje de programación Python.
Introducción
En Securetia, al momento de realizar Penetration Tests lo hacemos de forma "artesanal", es decir, que no nos limitamos a ejecutar herramientas automatizadas (como OpenVAS), si no que también realizamos un análisis manual, con herramientas particulares de acuerdo a cada situación.
Esto nos ha llevado a desarrollar algunas herramientas y scripts para cada caso particular.
Voy a aprovechar estos artículos para unificar estos pequeños programas en una herramienta un poco más organizada y documentada. Además de ser código abierto y hostearla en gitlab.
Como va a estar escrita con espíritu pedagógico, la herramienta va a ser desarrollada poco a poco, empezando por conceptos básicos e irá implementando funcionalidades más avanzadas a medida que pasen los artículos.
Software Necesario
Para trabajar en este proyecto, necesitamos lo siguiente:
- Python 3.x
- Git
Virtualenv
En Python se suelen utilizar entornos virtuales para aislar los paquetes instalados que son necesarios para cada proyecto en el que trabajamos o utilizamos. Esto nos va a beneficiar muchísimo al momento de evitar colisiones entre distintas versiones de los paquetes.
Para gestionar los entornos virtuales vamos a utilizar virtualenvwrapper, el cual podemos instalar a través de pip:
$ sudo pip install virtualenvwrapper
Una vez instalado, vamos a poder crear un nuevo entorno virtual:
$ mkvirtualenv habu Using base prefix '/usr' New python executable in /home/fabian/.python-envs/habu/bin/python3 Not overwriting existing python script /home/fabian/.python-envs/habu/bin/python (you must use /home/fabian/.python-envs/habu/bin/python3) Installing setuptools, pip, wheel...done. (habu)$
(No es necesario que el entorno virtual se llame de ninguna forma en particular, pero ponerle el mismo nombre del proyecto en el que estamos trabajando, ayuda a simplificar las cosas)
Como habremos notado, nuestro prompt ahora incluye el nombre del entorno virtual en el que estamos trabajando.
Esto ha cambiado (entre otras cosas) cuál es nuestro intérprete de python por defecto:
$ which python /home/fabian/.python-envs/habu/bin/python
Cada vez que instalemos un paquete estando dentro del entorno virtual, el mismo se va a instalar únicamente para ese entorno virtual.
Podemos utilizar 'deactivate' para desactivar el entorno virtual, y 'workon' para entrar en el entorno virtual:
(habu)$ which python /home/fabian/.python-envs/habu/bin/python (habu)$ deactivate $ which python /usr/bin/python $ workon habu (habu)$ which python /home/fabian/.python-envs/habu/bin/python
Estructura del Proyecto
Vamos a intentar mantener esto lo más sencillo posible, con el objetivo de hacerlo amigable a los que no estén tan familiarizados con Python. Así que la estructura no va a tener grandes cosas.
El repositorio de código está hosteado en https://github.com/portantier/habu.
Para traernos el proyecto:
$ git clone https://gitlab.com/securetia/habu Cloning into 'habu'... remote: Counting objects: 5, done. remote: Compressing objects: 100% (5/5), done. remote: Total 5 (delta 0), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (5/5), done.
Ahora tenemos el directorio habu, con una estructura similar a la siguiente:
├── dev-requirements.txt ├── docs ├── habu │ ├── cli │ │ ├── __init__.py │ │ └── cmd_ip.py │ ├── __init__.py │ └── lib │ └── ip.py ├── LICENSE ├── README.md ├── setup.py └── tests
Es una estructura relativamente sencilla, la cual detallaremos poco a poco. Por ahora, nos interesa saber lo siguiente:
- dev-requirements.txt: Lista de paquetes necesarios para trabajar en el desarrollo de habu
- docs: Documentación
- habu: Directorio donde va a ir el código del proyecto
- LICENSE: Licencia del proyecto
- README: Archivo 'leeme' en formato markdown (para gitlab)
- setup.py: Instrucciones para la instalación del paquete a través de pip
- tests: Directorio con los tests de calidad del proyecto
Uno de los archivos más importantes es 'setup.py', que contiene instrucciones para la instalación del paquete a través de pip, e información como las dependencias.
$ cat setup.py from setuptools import setup with open('README.md') as f: readme = f.read() with open('LICENSE') as f: license = f.read() setup( name='habu', version='0.0.1', description='Penetration Testing Utils', long_description=readme, author='Fabian Martinez Portantier', author_email='fportantier@securetia.com', url='https://gitlab.com/securetia/habu', license=license, install_requires=[ 'Click', 'Requests', ], packages=['habu'], include_package_data=True, entry_points=''' [console_scripts] habu.ip=habu.cli.cmd_ip:cmd_ip ''', )
Por ahora, las partes más importantes son:
- install_requires: Define las dependencias del paquete
- entry_points: Define los comandos que va a proveer el paquete
Librería y Ejecutables
El objetivo del proyecto es el de proveer comandos útiles para las tareas de un Penetration Test, así como también una librería que ponga a disposición las funciones utilizadas por los comandos, para que el proyecto pueda ser utilizado para la construcción rápida de otras herramientas.
Por eso, existen los directorios 'lib' y 'cli' en los cuales residen las funciones y los comandos, respectivamente.
Cuál es mi IP
Una de las funciones más básicas que podemos implementar, para demostrar la forma de trabajo del proyecto, es la de conocer cuál es nuestra dirección IP pública.
Para eso, tenemos la librería ip (lib/ip.py), que contiene la función 'get_ip':
import requests def get_ip(): return requests.get('https://api.ipify.org').text if __name__ == '__main__': print(get_ip())
Esta librería utiliza el paquete 'requests' para facilitar el trabajo con peticiones HTTP.
La función 'get_ip' simplemente realiza una petición al servicio https://api.ipify.org, que devuelve un string con únicamente nuestra dirección IP pública, y devuelve ese string como resultado.
En el caso de que el módulo sea ejecutado directamente (if name == 'main') se ejecuta la función get_ip()
Esto nos permite hacer lo siguiente:
$ python lib/ip.py
182.13.121.142
De todos modos, eso no sería muy práctico, por lo que definimos el archivo 'cli/cmd_ip.py', con lo siguiente:
import click from habu.lib.ip import get_ip @click.command() def cmd_ip(): """Example script.""" print(get_ip())
Aquí utilizamos el paquete 'click' para ayudarnos a construir nuestra interfaz CLI.
Decoramos la función cmd_ip con 'click.command()' para declarar que es un comando.
Nota: 'Decorar' una función nos permite llamar a otra función para modificar su comportamiento. En otros artículos vamos a usar más decoradores y a explicarlos mejor.
entry_points=''' [console_scripts] habu.ip=habu.cli.cmd_ip:cmd_ip ''',
Eso le indica a pip que tiene que poner a disposición el comando 'habu.ip' que, al ser ejecutado, va a llamar a la función cmd_ip, que reside dentro del archivo cmd_ip.py, que a su vez reside dentro del módulo cli, que a su vez reside dentro del paquete habu (por eso la sintáxis: habu.cli.cmd_ip:cmd_ip)
Para instalar el paquete habu en nuestro entorno virtual, podemos pararnos en la raíz del paquete y utilizar el siguiente comando:
$ pip install -e . Obtaining file:///home/fabian/habu Collecting Click (from habu==0.0.1) Collecting Requests (from habu==0.0.1) Using cached requests-2.11.1-py2.py3-none-any.whl Installing collected packages: Click, Requests, habu Running setup.py develop for habu Successfully installed Click-6.6 Requests-2.11.1 habu
Como podemos ver, no solamente se ha instalado el paquete habu, si no también sus dependencias (eso es gracias a que están detalladas en el archivo setup.py).
Ahora disponemos del ejecutable 'habu.ip':
$ habu.ip
186.19.120.102
Ejecutando Fuera del Entorno Virtual
Si salimos del entorno virtual, no vamos a tener acceso al comando habu.ip, pero eso es simplemente porque no va a estar en nuestro PATH.
No es una buena idea agregar el directorio en el cual reside el comando, debido a que hay otros comandos que colisionarían, como pip, python, etc.
Una forma bastante sencilla es incluir lo siguiente en nuestro .bashrc (en el caso de no usar bash, tendremos que verificar la documentación de nuestra shell)
for f in $(ls -1 ~/.python-envs/habu/bin) do alias $(basename $f)="~/.python-envs/habu/bin/$f" done
Esto genera un alias para cada comando que empieza con 'habu.', además, los scripts generados por setuptools permiten que los comandos funcionen fuera del entorno virtual (se encargan de que cada comando ingrese al entorno virtual antes de ejecutarse)
Conclusión
En este artículo hemos hecho una buena introducción a cómo empezar a trabajar en un proyecto Python para generar una interfaz de línea de comandos y una librería.
Ya contamos con los fundamentos para empezar a modificar el código y jugar con las diferentes funcionalidades.
En los próximos artículos
Vamos a implementar más funcionalidades asociadas a los Penetration Tests (la funcionalidad que vimos en este artículo fue un ejemplo muy básico).
hacking python