
Laboratorio basado en Docker para reproducir CVE-2026-42647, una inyección SQL ciega basada en tiempo no autenticada en el plugin JoomSport de WordPress a través del parámetro sortf. Incluye objetivos vulnerables y parcheados para comparación.
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.