Escenario Vulnerable
Introducción
En este proyecto, se ha diseñado un entorno de red que simula la estructura de una organización real, con vulnerabilidades específicas en cada host desplegado para simular posibles ataques. La topología se ha implementado en GNS3 utilizando un script automatizado para asegurar la eficiencia y consistencia del proceso. Las configuraciones vulnerables se aplicarán automáticamente a través de Ansible.
El entorno consta de tres máquinas que representan distintos puntos de vulnerabilidad en una red típica de una organización. Estas máquinas están diseñadas para ser objetivos de diversas técnicas de pentesting, permitiendo a los estudiantes explorar y explotar vulnerabilidades en un entorno controlado y seguro.
Requisitos previos
Antes de iniciar el despliegue, asegúrate de cumplir con los siguientes requisitos:
Sistema operativo
El entorno puede desplegarse en cualquier sistema operativo compatible con los requisitos de software especificados a continuación.
Software necesario
- Python: Versión 3.12.1
- Pydantic: Versión 1.9.2
- GNS3: Versión 2.2.43
- GNS3Fy: Versión 0.8.0
Instalación de requisitos
En Linux (Ubuntu como ejemplo)
sudo apt update
sudo apt install -y python3.12 python3-pip
pip3 install pydantic==1.9.2 gns3fy==0.8.0
En Windows
- Instalar Python 3.12.1: Descarga el instalador desde Python.org y sigue las instrucciones.
-
Instalar Pydantic y GNS3Fy: Abre PowerShell como administrador y ejecuta:
pip install pydantic==1.9.2 gns3fy==0.8.0 -
Instalar GNS3: Descarga e instala GNS3 desde GNS3.
En otros sistemas operativos
Asegúrate de instalar las versiones especificadas de Python, Pydantic, GNS3 y GNS3Fy utilizando los métodos correspondientes para tu sistema operativo.
ISOs para GNS3
Necesitarás descargar las siguientes ISOs para desplegarlas en GNS3:
- Ubuntu Desktop 22.04: Descargar ISO
- Windows 10 Enterprise Evaluation: Descargar ISO
Topología de red
La red incluye los siguientes componentes:

- Nube Cloud: Representa la conexión externa a Internet.
- Router/Firewall PFSense v2.7.0: Actúa como el dispositivo de seguridad principal, controlando el tráfico entre la nube y la red interna.
- Ethernet Switch: Proporciona conectividad entre los diferentes hosts internos.
- PC1 - Ubuntu Desktop Guest 22.04 (Servidor Ansible): Máquina que gestiona las configuraciones a través de Ansible.
- PC2 - Ubuntu Desktop Guest 22.04 (Cliente): Máquina cliente con configuraciones vulnerables.
- PC3 - Windows 10 Enterprise Evaluation (Cliente): Máquina cliente con configuraciones vulnerables.
Despliegue de la topología
Para desplegar la topología en GNS3, sigue estos pasos:
1. Descarga el script de despliegue
Para desplegar la topología en GNS3, utilizaremos un script en Python con la ayuda de la librería GNS3Fy.
2. Personalización del script
-
Asegúrate de que el servidor GNS3 esté configurado correctamente y disponible en la dirección especificada en el script (
server_url). -
Utiliza las credenciales proporcionadas en el script (
usernameypassword) para conectarte al servidor GNS3. -
Asigna un nombre al proyecto en
project_name.
3. Ejecutar el script de Python
- Ejecuta el script con Python, por ejemplo, utilizando
python nombre_archivo.py.
El script realizará las siguientes acciones:
-
Crea una conexión con el servidor GNS3.
-
Verifica si ya existe un proyecto con el nombre especificado (
project_name) y lo elimina si es así. -
Crea un nuevo proyecto con el nombre especificado (
project_name). -
Despliega los nodos especificados en la lista (
nodes_to_deploy) y los almacena en el diccionariodeployed_nodes. -
Conecta los nodos entre sí para formar la topología de red.
Explicación del script
El siguiente código muestra el script de despliegue con explicaciones detalladas sobre cada bloque de código:
1. Importar las clases necesarias y establecer variables básicas:
from gns3fy import Gns3Connector, Project, Node, Link
server_url = "http://192.168.1.74:80"
username = 'username'
password = 'password'
project_name = "project_name"
2. Crear una instancia de Gns3Connector:
# Creando el conector con autenticación
server = Gns3Connector(server_url, user=username, cred=password)
3. Eliminar proyectos existentes con el mismo nombre:
# Verificar si el proyecto ya existe y eliminarlo si es así
existing_projects = server.get_projects()
for proj in existing_projects:
if proj['name'] == project_name:
project = Project(project_id=proj['project_id'], connector=server)
project.delete()
print(f"Proyecto existente '{project_name}' eliminado.")
4. Crear un nuevo proyecto:
# Crear un nuevo proyecto
project = Project(name=project_name, connector=server)
project.create()
print(f"Nuevo proyecto '{project_name}' creado.")
5. Lista de plantillas a desplegar:
# Lista de plantillas a desplegar y sus nombres
nodes_to_deploy = [
{"template_id": "39e257dc-8412-3174-b6b3-0ee3ed6a43e9", "name": "Nube_Cloud"},
{"template_id": "abd8c506-2f57-4b1a-b0cf-447cbbec79ee", "name": "R1_PFSense"},
{"template_id": "1966b864-93e7-32d5-965f-001384eec461", "name": "Switch"},
{"template_id": "3f8652a2-2260-432a-8702-759db0c13c51", "name": "PC1"},
{"template_id": "3f8652a2-2260-432a-8702-759db0c13c51", "name": "PC2"},
{"template_id": "b84f5c78-5611-488f-8173-16dfefe83349", "name": "PC3"}
]
Nota: Para conocer la ID de todas las plantillas del servidor de GNS3, utilizamos otro script que adjuntaremos a este proyecto.
6. Función para desplegar los nodos:
# Desplegando nodos y almacenando sus node_id
deployed_nodes = {}
def deploy_nodes():
for node_info in nodes_to_deploy:
node = Node(project_id=project.project_id, connector=server, name=node_info["name"], template_id=node_info["template_id"])
node.create()
deployed_nodes[node.name] = node.node_id
print(f"Nodo '{node.name}' creado con éxito en el proyecto '{project.name}' usando la plantilla ID {node_info['template_id']}")
try:
deploy_nodes()
except Exception as e:
print(f"Error al desplegar nodos: {e}")
7. Crear enlaces entre los nodos:
# Conectar Nube_Cloud con R1_PFSense
try:
link1 = Link(project_id=project.project_id, connector=server, nodes=[
{"node_id": deployed_nodes["Nube_Cloud"], "adapter_number": 0, "port_number": 0},
{"node_id": deployed_nodes["R1_PFSense"], "adapter_number": 0, "port_number": 0}
])
link1.create()
print("Enlace creado entre Nube_Cloud y R1_PFSense.")
except Exception as e:
print(f"Error al crear el enlace entre Nube_Cloud y R1_PFSense: {e}")
# Conectar R1_PFSense con Switch
try:
link2 = Link(project_id=project.project_id, connector=server, nodes=[
{"node_id": deployed_nodes["R1_PFSense"], "adapter_number": 1, "port_number": 0},
{"node_id": deployed_nodes["Switch"], "adapter_number": 0, "port_number": 0}
])
link2.create()
print("Enlace creado entre R1_PFSense y Switch.")
except Exception as e:
print(f"Error al crear el enlace entre R1_PFSense y Switch: {e}")
try:
# Conectar Switch (Ethernet1) con PC1
link_pc1 = Link(project_id=project.project_id, connector=server, nodes=[
{"node_id": deployed_nodes["Switch"], "adapter_number": 0, "port_number": 1},
{"node_id": deployed_nodes["PC1"], "adapter_number": 0, "port_number": 0}
])
link_pc1.create()
print("Enlace creado entre Switch (Ethernet1) y PC1.")
# Conectar Switch (Ethernet2) con PC2
link_pc2 = Link(project_id=project.project_id, connector=server, nodes=[
{"node_id": deployed_nodes["Switch"], "adapter_number": 0, "port_number": 2},
{"node_id": deployed_nodes["PC2"], "adapter_number": 0, "port_number": 0}
])
link_pc2.create()
print("Enlace creado entre Switch (Ethernet2) y PC2.")
# Conectar Switch (Ethernet3) con PC3
link_pc3 = Link(project_id=project.project_id, connector=server, nodes=[
{"node_id": deployed_nodes["Switch"], "adapter_number": 0, "port_number": 3},
{"node_id": deployed_nodes["PC3"], "adapter_number": 0, "port_number": 0}
])
link_pc3.create()
print("Enlace creado entre Switch (Ethernet3) y PC3.")
except Exception as e:
print(f"Error al crear los enlaces entre el Switch y los PCs: {e}")
Despliegue de las máquinas mediante Ansible
Después de desplegar la topología en GNS3, configuraremos las máquinas utilizando playbooks de Ansible.
Ansible es una herramienta de automatización que nos permite gestionar configuraciones y despliegues de manera eficiente. Utilizando playbooks de Ansible, podemos aplicar configuraciones y desplegar aplicaciones en múltiples nodos de forma automática y repetible.
Configuración del PC1 (Servidor Ansible)
En primer lugar vamos a configurar nuestro servidor Ansible (PC1), para ello seguiremos los siguientes pasos:
1. Conexión al PC1 (Servidor Ansible)
Nos conectamos a la máquina que se utilizará como servidor Ansible (PC1) y abrimos un terminal.
2. Instalación de Ansible
Instalamos Ansible utilizando el gestor de paquetes correspondiente.
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
Ejecutamos el comando ansible --version en la terminal para verficar que ansible se ha instalado correctamente. Debe mostrar la versión de Ansible instalada.
ansible --version
2. Creación del archivo de configuración de Ansible
Una vez que Ansible está instalado, generalmente se crea automáticamente un archivo de configuración en la ruta /etc/ansible/ansible.cfg. Comprobamos si el archivo existe:
ls /etc/ansible/ansible.cfg
Si no encuentras el archivo predeterminado, puedes generar un nuevo archivo de configuración con todas las opciones comentadas para facilitar su configuración. Para hacerlo, ejecuta el siguiente comando:
ansible-config init --disabled > ansible.cfg
Estructura del archivo
El archivo de configuración contiene varias variables de configuración importantes, como:
inventory: Ruta del archivo de inventario.forks: Número máximo de conexiones simultáneas.sudo_user: Usuario con el que se hace sudo.module_lang: Idioma definido.timeout: Timeout del ssh.remote_user: Usuario por defecto.log_path: Ruta de los logs.ask_sudo_pass: Si se debe solicitar una contraseña de sudo.remote_port: Puerto para usar en conexiones remotas.
Aquí podemos ver un ejemplo de archivo de configuración de Ansible básico:
[defaults]
inventory = /etc/ansible/hosts
forks = 10
sudo_user = root
module_lang = C
timeout = 60
remote_user = ansible
log_path = /var/log/ansible.log
ask_sudo_pass = yes
remote_port = 22
3. Configuración del inventario
El archivo de inventario es un archivo que contiene la lista de nodos o hosts que Ansible gestionará. Debemos configurarlo para que Ansible pueda conectarse y gestionar los nodos de manera efectiva.
En la mayoría de las instalaciones de Ansible, el archivo de configuración predeterminado (/etc/ansible/ansible.cfg) no contiene la ruta del archivo de inventario (/etc/ansible/hosts) por defecto. Para verificar si la ruta está configurada, ejecuta el siguiente comando:
cat /etc/ansible/ansible.cfg
Si la ruta no está configurada, debemos añadirla. Edita el archivo de configuración de Ansible:
sudo nano /etc/ansible/ansible.cfg
Añade o modifica la línea para que incluya la ruta del archivo de inventario:
[defaults]
inventory = /etc/ansible/hosts
Guarda y cierra el archivo.
Configuración del archivo de inventario
Ahora vamos a configurar el archivo de inventario con los detalles de los nodos del proyecto (PC2 y PC3).
1. Abre el archivo de inventario:
sudo nano /etc/ansible/hosts
2. Añade las siguientes líneas para definir los nodos del proyecto:
[ubuntuclient]
192.168.1.10
[windowsclient]
192.168.1.20
Donde, 192.168.1.10, y 192.168.1.20 son las direcciones IP de los respectivos nodos en la topología de red.
Para mayor claridad, aquí podemos ver un ejemplo completo de cómo debería verse el archivo de inventario (hosts):
[ubuntuclient]
192.168.1.10
[windowsclient]
192.168.1.20
Con estas configuraciones, Ansible podrá gestionar los nodos definidos en el archivo de inventario, permitiendo ejecutar los playbooks en los hosts especificados.
Despliegue del PC2 (Máquina cliente con Moodle vulnerable)
Una vez que tenemos nuestro servidor Ansible listo y comprobado, vamos a desplegar el servidor Moodle en el PC2. Sigue estos pasos:
1. Conéctate al PC1 (servidor Ansible)
Abre una terminal en el servidor Ansible o asegúrate de tener acceso SSH.
2. Descarga el playbook de Moodle y el archivo de configuración
Descarga el playbook desde el siguiente enlace: Descargar playbook
Descarga el archivo moodle-config.php desde el siguiente enlace y asegúrate de colocarlo en el mismo directorio donde tienes el playbook. Durante la ejecución del playbook, este archivo será copiado automáticamente al directorio adecuado.
<?php // Moodle configuration file
unset($CFG);
global $CFG;
$CFG = new stdClass();
$CFG->dbtype = 'mysqli';
$CFG->dblibrary = 'native';
$CFG->dbhost = 'localhost';
$CFG->dbname = 'moodle';
$CFG->dbuser = 'moodle_g4'; // Cambia 'moodle_g4' por el nombre de usuario deseado
$CFG->dbpass = 'grupo4rules'; // Cambia 'grupo4rules' por la contraseña deseada
$CFG->prefix = 'mdl_';
$CFG->dboptions = array (
'dbpersist' => false,
'dbport' => '',
'dbsocket' => '',
'dbcollation' => 'utf8mb4_unicode_ci',
);
$CFG->wwwroot = 'http://localhost/moodle';
$CFG->dataroot = '/var/moodledata';
$CFG->admin = 'admin';
$CFG->directorypermissions = 0777;
Nota: Antes de ejecutar el playbook, asegúrate de revisar y configurar las siguientes variables en el archivo playbook_moodle.yml y moodle-config.php:
-
En el playbook
playbook_moodle.yml:db_user,db_password,db_root_password, y cualquier otra variable que necesite ser personalizada. -
En el archivo
moodle-config.php:dbuser,dbpass, y cualquier otra configuración específica de tu entorno.
3. Ejecuta el playbook de Ansible
Navega hasta el directorio donde se encuentra el playbook y ejecuta el siguiente comando:
ansible-playbook -i /etc/ansible/hosts playbook_moodle.yml
Explicación del script
Este playbook desplegará un servidor Moodle con varias configuraciones y servicios vulnerables. A continuación, se explican los pasos que realiza cada uno de los bloques del script de Ansible:
1. Definición del objetivo del playbook y ejecución de tareas con permisos elevados
- hosts: moodleserver
become: yes
2. Definición de variables
vars:
ansible_python_interpreter: /usr/bin/python3
moodle_version: "3.4.1"
db_name: "moodle"
db_user: "moodle_g4"
db_password: "grupo4rules"
db_root_password: "grupo4rules"
moodle_www_root: "/var/www/html"
moodle_data_root: "/var/moodledata"
3. Tasks
3.1. Añadir el repositorio de PHP 7.1
- name: Añadir el repositorio de PHP 7.1
apt_repository:
repo: ppa:ondrej/php
state: present
Se añade un repositorio de terceros que contiene varias versiones de PHP.
3.2. Actualizar e instalar paquetes necesarios
- name: Actualizar e instalar paquetes necesarios
apt:
update_cache: yes
name:
- apache2
- mysql-server
- php7.1
- libapache2-mod-php7.1
- php7.1-mysql
- php7.1-xml
- php7.1-curl
- php7.1-zip
- php7.1-gd
- php7.1-intl
- php7.1-xmlrpc
- php7.1-soap
- php7.1-mbstring
- php7.1-ldap
- php7.1-bcmath
- php7.1-opcache
- unzip
- python3-pip
state: present
Actualiza la caché del paquete y luego instala Apache, MySQL y varias extensiones de PHP necesarias para Moodle.
3.3. Instalar pip para Python 3
- name: Instalar pip para Python 3
apt:
name: python3-pip
state: present
Asegura que pip para Python 3 está instalado.
3.4. Instalar módulo PyMySQL
- name: Instalar módulo PyMySQL
pip:
name: PyMySQL
state: present
executable: pip3
Instala el módulo PyMySQL usando pip3, necesario para que Ansible pueda gestionar MySQL.
3.5. Iniciar y habilitar Apache
- name: Iniciar y habilitar Apache
systemd:
name: apache2
state: started
enabled: yes
Inicia el servicio Apache y asegura que se habilite para arrancar al iniciar el sistema.
3.6. Configurar contraseña root de MySQL
- name: Configurar contraseña root de MySQL
mysql_user:
name: root
host: localhost
password: "{{ db_root_password }}"
login_user: root
login_password: "{{ db_root_password }}"
login_unix_socket: /var/run/mysqld/mysqld.sock
state: present
Configura la contraseña para el usuario root de MySQL, sirviéndose de las variables mencionadas al principio del playbook.
3.7. Crear base de datos para Moodle
- name: Crear base de datos para Moodle
mysql_db:
name: "{{ db_name }}"
state: present
login_user: root
login_password: "{{ db_root_password }}"
login_unix_socket: /var/run/mysqld/mysqld.sock
Crea una base de datos llamada moodle, sirviéndose de las variables mencionadas al principio del playbook.
3.8. Crear usuario de base de datos para Moodle
- name: Crear usuario de base de datos para Moodle
mysql_user:
name: "{{ db_user }}"
password: "{{ db_password }}"
priv: "{{ db_name }}.*:ALL"
state: present
login_user: root
login_password: "{{ db_root_password }}"
login_unix_socket: /var/run/mysqld/mysqld.sock
Crea un usuario de MySQL (moodle_g4) con privilegios sobre la base de datos moodle.
3.9. Descargar Moodle
- name: Descargar Moodle
get_url:
url: "https://github.com/moodle/moodle/archive/refs/tags/v3.4.1.zip"
dest: "/tmp/moodle-{{ moodle_version }}.zip"
Descarga el archivo zip de Moodle de la versión especificada desde GitHub.
3.10. Extraer Moodle
- name: Extraer Moodle
unarchive:
src: "/tmp/moodle-{{ moodle_version }}.zip"
dest: "{{ moodle_www_root }}"
remote_src: yes
Extrae el contenido del archivo zip en el directorio web de Apache (/var/www/html).
3.11. Establecer permisos en el directorio de Moodle
- name: Establecer permisos en el directorio de Moodle
file:
path: "{{ moodle_www_root }}"
owner: www-data
group: www-data
recurse: yes
Establece los permisos del directorio de Moodle para que el usuario y grupo www-data (usado por Apache) tengan control sobre él.
3.12. Crear directorio de datos de Moodle
- name: Crear directorio de datos de Moodle
file:
path: "{{ moodle_data_root }}"
state: directory
owner: www-data
group: www-data
mode: '0770'
Crea el directorio para los datos de Moodle (/var/moodledata) con los permisos adecuados.
3.13. Configurar Apache para Moodle
- name: Configurar Apache para Moodle
copy:
content: |
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot {{ moodle_www_root }}
<Directory {{ moodle_www_root }}>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
dest: /etc/apache2/sites-available/moodle.conf
Copia una configuración de Apache para Moodle en el directorio de sitios disponibles.
3.14. Deshabilitar el sitio por defecto de Apache
- name: Deshabilitar el sitio por defecto de Apache
command: a2dissite 000-default.conf
Deshabilita el sitio por defecto de Apache para evitar conflictos.
3.15. Habilitar sitio Moodle en Apache
- name: Habilitar sitio Moodle en Apache
command: a2ensite moodle.conf
Habilita la nueva configuración de sitio de Moodle en Apache.
3.16. Habilitar módulo rewrite de Apache
- name: Habilitar módulo rewrite de Apache
command: a2enmod rewrite
Habilita el módulo rewrite de Apache, necesario para las URLs amigables en Moodle.
3.17. Reiniciar Apache para aplicar cambios
- name: Reiniciar Apache para aplicar cambios
systemd:
name: apache2
state: restarted
Reinicia Apache para que los cambios en la configuración surtan efecto.
3.18. Ajustar configuración de PHP para Moodle
- name: Ajustar configuración de PHP para Moodle
lineinfile:
path: /etc/php/7.1/apache2/php.ini
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
with_items:
- { regexp: '^post_max_size', line: 'post_max_size = 50M' }
- { regexp: '^upload_max_filesize', line: 'upload_max_filesize = 50M' }
- { regexp: '^max_execution_time', line: 'max_execution_time = 300' }
- { regexp: '^max_input_time', line: 'max_input_time = 300' }
3.19. Reiniciar Apache para aplicar cambios de PHP
- name: Reiniciar Apache para aplicar cambios de PHP
systemd:
name: apache2
state: restarted
Reinicia Apache para aplicar cambios de configuración de PHP.
3.20. Configurar Moodle
- name: Configurar Moodle
template:
src: moodle-config.php
dest: "{{ moodle_www_root }}/config.php"
owner: www-data
group: www-data
mode: '0644'
Copia el archivo de configuración de Moodle al directorio adecuado.
4. Handlers
handlers:
- name: reiniciar apache
systemd:
name: apache2
state: restarted
Define un handler que reinicia Apache cuando es necesario.
Despliegue del PC3 (Máquina cliente con Wordpress vulnerable)
Por último, vamos a desplegar el servidor Wordpress en el PC3. Sigue estos pasos:
1. Conéctate al PC1 (servidor Ansible)
Abre una terminal en el servidor Ansible o asegúrate de tener acceso SSH.
2. Descarga el playbook de Moodle
Descarga el playbook desde el siguiente enlace: Descargar playbook
3. Ejecuta el playbook de Ansible
Navega hasta el directorio donde se encuentra el playbook y ejecuta el siguiente comando:
ansible-playbook -i /etc/ansible/hosts playbook_wordpress.yml
Explicación del script
Conclusión
En este apartado se ha detallado cómo desplegar un entorno vulnerable utilizando GNS3 y Ansible. Se ha proporcionado un script para la configuración de la topología en GNS3 y un playbook de Ansible para configurar un servidor Moodle vulnerable. Los playbooks adicionales para los clientes Ubuntu y Windows estarán disponibles en futuras actualizaciones del proyecto.
Este entorno permite a los estudiantes practicar habilidades de pentesting en un entorno controlado, explorando y explotando diversas vulnerabilidades para aprender a proteger sistemas reales.