Skip to content

Droopescan - Escáner de Vulnerabilidades para Drupal

Droopescan - Escáner de Vulnerabilidades para Drupal

Section titled “Droopescan - Escáner de Vulnerabilidades para Drupal”

Droopescan es una herramienta especializada en la detección de vulnerabilidades y enumeración de componentes en sitios web que utilizan Drupal, así como otros CMS como WordPress y SilverStripe. Desarrollada en Python, esta herramienta automatiza el proceso de reconocimiento, identificación de versiones, módulos y temas vulnerables.

Drupal es un sistema de gestión de contenidos (CMS) de código abierto desarrollado en PHP, conocido por:

  • Flexibilidad: Altamente personalizable y escalable
  • Seguridad: Enfoque robusto en seguridad
  • Comunidad: Gran ecosistema de módulos y temas
  • Enterprise: Utilizado por gobiernos y grandes organizaciones

Droopescan es crucial para auditorías de Drupal porque:

  • Detección de versiones: Identifica versiones específicas para buscar CVEs
  • Enumeración de módulos: Encuentra módulos vulnerables
  • Análisis de temas: Detecta temas con problemas de seguridad
  • Configuraciones inseguras: Identifica archivos expuestos
Terminal window
# Instalar desde PyPI
pip install droopescan
# Verificar instalación
droopescan --version
Terminal window
# Clonar repositorio
git clone https://github.com/droope/droopescan.git
cd droopescan
# Instalar dependencias
pip install -r requirements.txt
# Instalar
python setup.py install
# O ejecutar directamente
python droopescan scan drupal -u http://ejemplo.com
Terminal window
# Usar imagen Docker
docker run --rm droope/droopescan scan drupal -u http://ejemplo.com
Terminal window
# Sintaxis general
droopescan scan [CMS] [opciones] -u <URL>
# Escaneo básico de Drupal
droopescan scan drupal -u http://ejemplo.com
# Escaneo con enumeración
droopescan scan drupal -u http://ejemplo.com --enumerate p,t,v
# Múltiples URLs
droopescan scan drupal -U urls.txt
CMSDescripciónEjemplo
drupalEscanear Drupalscan drupal -u URL
wordpressEscanear WordPressscan wordpress -u URL
silverstripeEscanear SilverStripescan silverstripe -u URL
ParámetroDescripciónEjemplo
-e, --enumerateComponentes a enumerar-e p,t,v
pPlugins/Módulos-e p
tTemas-e t
vVersiones-e v
iArchivos interesantes-e i
ParámetroDescripciónEjemplo
--outputFormato de salida--output json
--output-fileArchivo de salida--output-file reporte.json
-q, --quietModo silencioso-q
-v, --verboseModo verbose-v
Terminal window
# Escaneo básico de Drupal
droopescan scan drupal -u http://ejemplo.com
# Ejemplo de salida:
# [+] Possible version(s):
# [+] 8.9.13
# [+] 8.9.14
# [+] 8.9.15
Terminal window
# Enumerar plugins, temas y versiones
droopescan scan drupal -u http://ejemplo.com --enumerate p,t,v
# Salida en JSON
droopescan scan drupal -u http://ejemplo.com --enumerate p,t,v --output json
Terminal window
# Crear lista de URLs
echo "http://sitio1.com" > drupal_sites.txt
echo "http://sitio2.com" >> drupal_sites.txt
# Escanear múltiples sitios
droopescan scan drupal -U drupal_sites.txt --enumerate p,t
#!/bin/bash
# Script de auditoría completa para Drupal con Droopescan
# Uso: ./drupal_audit.sh <URL>
URL=$1
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
OUTPUT_DIR="drupal_audit_${TIMESTAMP}"
if [ -z "$URL" ]; then
echo "Uso: $0 <URL>"
exit 1
fi
echo "[+] Iniciando auditoría de Drupal para: $URL"
mkdir -p $OUTPUT_DIR
# 1. Escaneo básico
echo "[+] Fase 1: Escaneo básico"
droopescan scan drupal -u $URL --output json --output-file $OUTPUT_DIR/01_basic_scan.json
# 2. Enumeración completa
echo "[+] Fase 2: Enumeración completa"
droopescan scan drupal -u $URL --enumerate p,t,v,i --output json --output-file $OUTPUT_DIR/02_full_enum.json
# 3. Verificaciones manuales adicionales
echo "[+] Fase 3: Verificaciones adicionales"
check_drupal_files $URL > $OUTPUT_DIR/03_manual_checks.txt
# 4. Análisis de configuración
echo "[+] Fase 4: Análisis de configuración"
analyze_drupal_config $URL > $OUTPUT_DIR/04_config_analysis.txt
echo "[+] Auditoría completada. Resultados en: $OUTPUT_DIR"
# Generar resumen
generate_drupal_summary $OUTPUT_DIR
Terminal window
check_drupal_files() {
local url=$1
echo "=== VERIFICACIÓN DE ARCHIVOS DRUPAL ==="
# Archivos comunes de Drupal
drupal_files=(
"CHANGELOG.txt"
"COPYRIGHT.txt"
"INSTALL.txt"
"LICENSE.txt"
"MAINTAINERS.txt"
"README.txt"
"UPGRADE.txt"
"sites/default/settings.php"
"sites/default/files/"
"sites/all/modules/"
"sites/all/themes/"
"misc/"
"includes/"
"modules/"
"themes/"
"profiles/"
"scripts/"
"cron.php"
"install.php"
"update.php"
"xmlrpc.php"
"authorize.php"
)
for file in "${drupal_files[@]}"; do
status=$(curl -s -o /dev/null -w "%{http_code}" "$url/$file")
case $status in
200)
echo "[!] ACCESIBLE: $file (HTTP $status)"
;;
403)
echo "[?] PROHIBIDO: $file (HTTP $status) - Posiblemente existe"
;;
404)
echo "[+] NO ENCONTRADO: $file"
;;
esac
done
}
analyze_drupal_config() {
local url=$1
echo "=== ANÁLISIS DE CONFIGURACIÓN DRUPAL ==="
# Verificar CHANGELOG para versión
changelog_content=$(curl -s "$url/CHANGELOG.txt" | head -10)
if [ ! -z "$changelog_content" ]; then
echo "[!] CHANGELOG accesible - Posible filtración de versión"
echo "$changelog_content" | grep -i "drupal" | head -3
fi
# Verificar status report (si accesible)
status_report=$(curl -s "$url/admin/reports/status" | grep -i "drupal")
if [ ! -z "$status_report" ]; then
echo "[!] Status report accesible"
fi
# Verificar update.php
update_status=$(curl -s -o /dev/null -w "%{http_code}" "$url/update.php")
if [ "$update_status" = "200" ]; then
echo "[!] CRÍTICO: update.php accesible sin autenticación"
fi
# Verificar install.php
install_status=$(curl -s -o /dev/null -w "%{http_code}" "$url/install.php")
if [ "$install_status" = "200" ]; then
echo "[!] RIESGO: install.php accesible"
fi
}
generate_drupal_summary() {
local output_dir=$1
local summary_file="$output_dir/RESUMEN_EJECUTIVO.txt"
echo "=== RESUMEN EJECUTIVO - AUDITORÍA DRUPAL ===" > $summary_file
echo "Fecha: $(date)" >> $summary_file
echo "URL: $URL" >> $summary_file
echo "" >> $summary_file
# Extraer información de JSON si existe
if [ -f "$output_dir/01_basic_scan.json" ]; then
echo "=== INFORMACIÓN BÁSICA ===" >> $summary_file
python3 -c "
import json
try:
with open('$output_dir/01_basic_scan.json', 'r') as f:
data = json.load(f)
if 'version' in data:
print('Versiones detectadas:', ', '.join(data['version']))
if 'plugins' in data:
print('Plugins encontrados:', len(data['plugins']))
if 'themes' in data:
print('Temas encontrados:', len(data['themes']))
except:
print('No se pudo procesar el JSON')
" >> $summary_file
fi
echo "" >> $summary_file
echo "=== ARCHIVOS CRÍTICOS ACCESIBLES ===" >> $summary_file
grep "ACCESIBLE\|CRÍTICO" $output_dir/03_manual_checks.txt >> $summary_file
echo "[+] Resumen ejecutivo generado: $summary_file"
}
#!/bin/bash
check_drupal_vulnerabilities() {
local url=$1
local droopescan_output=$2
echo "[+] Analizando vulnerabilidades de módulos Drupal"
# Extraer módulos del output de Droopescan
if [ -f "$droopescan_output" ]; then
modules=$(python3 -c "
import json
try:
with open('$droopescan_output', 'r') as f:
data = json.load(f)
if 'plugins' in data:
for plugin in data['plugins']:
print(plugin)
except:
pass
")
echo "Módulos encontrados para verificar:"
echo "$modules"
# Verificar cada módulo contra base de datos de vulnerabilidades
for module in $modules; do
echo "[+] Verificando vulnerabilidades para: $module"
# Aquí se podría integrar con APIs de vulnerabilidades
check_module_advisories $module
done
fi
}
check_module_advisories() {
local module=$1
# Verificar advisories de Drupal.org
advisory_url="https://www.drupal.org/security"
echo "[+] Verificar manualmente: $advisory_url para $module"
# Verificar archivos README del módulo
readme_status=$(curl -s -o /dev/null -w "%{http_code}" "$URL/sites/all/modules/$module/README.txt")
if [ "$readme_status" = "200" ]; then
echo "[!] README accesible para $module"
fi
}
Terminal window
# Escaneo de puertos seguido de Droopescan
nmap -sV -p 80,443 ejemplo.com
droopescan scan drupal -u http://ejemplo.com --enumerate p,t,v
Terminal window
# Análisis complementario
nikto -h http://ejemplo.com
droopescan scan drupal -u http://ejemplo.com --enumerate p,t
Terminal window
# Templates específicos de Drupal
nuclei -u http://ejemplo.com -t ~/nuclei-templates/technologies/drupal/
#!/bin/bash
corporate_drupal_audit() {
local company_name=$1
local urls_file=$2
local output_base="drupal_corp_audit_$(date +%Y%m%d)"
mkdir -p $output_base
echo "[+] Auditoría corporativa de Drupal para: $company_name"
while IFS= read -r url; do
site_name=$(echo $url | sed 's/https\?:\/\///g' | sed 's/\/.*//g')
echo "[+] Auditando: $site_name"
mkdir -p "$output_base/$site_name"
# Droopescan completo
droopescan scan drupal -u $url --enumerate p,t,v,i --output json --output-file "$output_base/$site_name/droopescan.json"
# Verificaciones manuales
check_drupal_files $url > "$output_base/$site_name/manual_checks.txt"
# Resumen por sitio
echo "=== $site_name ===" >> "$output_base/resumen_corporativo.txt"
python3 -c "
import json
try:
with open('$output_base/$site_name/droopescan.json', 'r') as f:
data = json.load(f)
print('Versiones:', ', '.join(data.get('version', ['No detectada'])))
print('Plugins:', len(data.get('plugins', [])))
print('Temas:', len(data.get('themes', [])))
except:
print('Error procesando datos')
" >> "$output_base/resumen_corporativo.txt"
echo "" >> "$output_base/resumen_corporativo.txt"
done < $urls_file
echo "[+] Auditoría corporativa completada: $output_base"
}
#!/bin/bash
drupal_continuous_monitoring() {
local url=$1
local baseline_file="drupal_baseline_$(echo $url | sed 's/https\?:\/\///g' | sed 's/\//_/g').json"
local current_file="drupal_current_$(date +%Y%m%d_%H%M%S).json"
echo "[+] Monitoreo continuo de Drupal: $url"
# Escaneo actual
droopescan scan drupal -u $url --enumerate p,t,v --output json --output-file $current_file
if [ -f "$baseline_file" ]; then
echo "[+] Comparando con baseline..."
# Comparar usando Python
python3 -c "
import json
try:
with open('$baseline_file', 'r') as f:
baseline = json.load(f)
with open('$current_file', 'r') as f:
current = json.load(f)
# Comparar versiones
baseline_versions = set(baseline.get('version', []))
current_versions = set(current.get('version', []))
if baseline_versions != current_versions:
print('[!] CAMBIO DE VERSIÓN DETECTADO')
print('Baseline:', baseline_versions)
print('Actual:', current_versions)
# Comparar plugins
baseline_plugins = set(baseline.get('plugins', []))
current_plugins = set(current.get('plugins', []))
new_plugins = current_plugins - baseline_plugins
removed_plugins = baseline_plugins - current_plugins
if new_plugins:
print('[!] NUEVOS PLUGINS:', new_plugins)
if removed_plugins:
print('[!] PLUGINS REMOVIDOS:', removed_plugins)
except Exception as e:
print('Error comparando archivos:', e)
"
# Actualizar baseline
cp $current_file $baseline_file
else
echo "[+] Creando baseline inicial"
cp $current_file $baseline_file
fi
}
  1. Detección pasiva: Puede no detectar todos los módulos
  2. Falsos positivos: Especialmente en sitios personalizados
  3. Actualizaciones: Base de datos puede estar desactualizada
  4. Sitios protegidos: WAF puede interferir
  1. Combinar herramientas: Usar con Nmap, Nikto, etc.
  2. Verificación manual: Confirmar hallazgos importantes
  3. Actualizar regularmente: Mantener Droopescan actualizado
  4. Documentar resultados: Registrar todos los hallazgos
  • CMSmap: Scanner multi-CMS
  • Nuclei: Templates para Drupal
  • Drupwn: Enumerador específico de Drupal
  • DPScan: Otro scanner de Drupal

⚠️ IMPORTANTE: Esta documentación es únicamente para fines educativos y de investigación en ciberseguridad. El uso de Droopescan debe realizarse exclusivamente en:

  • Sitios web propios
  • Entornos de laboratorio
  • Sitios con autorización explícita y por escrito

El uso no autorizado puede constituir un delito. Los autores no se hacen responsables del mal uso de esta información.