
# Docker-лаборатория для воспроизведения CVE-2026-42647 Docker-лаборатория для воспроизведения CVE-2026-42647 — неаутентифицированной time-based blind SQL-инъекции в плагине JoomSport для WordPress через параметр `sortf`. Включает уязвимую и пропатченную цели для сравнения.
sortfЭтот репозиторий содержит локальную Docker-лабораторию для воспроизведения и проверки CVE-2026-42647 — уязвимости неаутентифицированной SQL-инъекции, затрагивающей плагин WordPress JoomSport - for Sports: Team & League, Football, Hockey & more.
Уязвимое поведение возникает в функции сортировки списка игроков. Публичный посетитель может контролировать параметр запроса sortf, который используется для построения SQL-выражения ORDER BY. В уязвимых версиях значение очищается как текст и заключается в обратные кавычки, но не проверяется по строгому белому списку перед добавлением в SQL-запрос.
Эта лаборатория сравнивает две версии JoomSport:
| Сервис | Версия JoomSport | Назначение | URL |
|---|---|---|---|
vuln | 5.7.6 | Уязвимая цель сравнения | http://localhost:8081 |
patched | 5.7.8 | Исправленная цель сравнения | http://localhost:8082 |
Официальные уведомления определяют версии до 5.7.8 как затронутые, а 5.7.8 — как исправленную версию. Эта лаборатория использует 5.7.6 в качестве уязвимой цели, поскольку тег исходного кода 5.7.7 отсутствовал в списке тегов SVN плагина WordPress.org на момент подготовки этой лаборатории.
Демонстрируемая цепочка уязвимости:```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
Этот лабораторный стенд подтверждает уязвимость как слепую SQL-инъекцию на основе времени. Он не выполняет дамп базы данных, извлечение учётных данных, изменение данных или деструктивные SQL-операции.
Данный стенд предназначен только для контролируемого локального исследования, понимания на уровне исходного кода и демонстрации в портфолио.
## Проверенные факты
| Утверждение | Доказательство | Как проверить в этом стенде |
| ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Сообщается, что JoomSport до версии 5.7.8 уязвим к неаутентифицированной SQL-инъекции. | Публичные уведомления об уязвимостях относят JoomSport `< 5.7.8` / `<= 5.7.7` к затронутым версиям. | Изучите раздел References и сравните уязвимую и исправленную версии сервисов. |
| JoomSport 5.7.8 — это исправленная версия. | Публичные уведомления и сравнение исходного кода показывают, что в 5.7.8 значение `sortf` проверяется перед формированием выражения сортировки. | Изучите `class-jsport-playerlist.php` в обеих версиях. |
| Затронутый параметр — `sortf`. | Уязвимый код списка игроков считывает `classJsportRequest::get('sortf')`. | Запустите PoC и наблюдайте инъецированный запрос с параметром `sortf`. |
| Уязвимый код формирует динамическое значение сортировки SQL из пользовательского ввода. | В уязвимой версии `sortf` используется для построения `$options['ordering']`. | Изучите `sportleague/classes/objects/class-jsport-playerlist.php`. |
| SQL-sink — это выражение `ORDER BY`. | Сформированное значение `$ordering` позже добавляется в SQL-запрос с `ORDER BY`. | Изучите `sportleague/base/wordpress/classes/class-jsport-getplayers.php`. |
| Патч использует исправление в стиле белого списка (allowlist). | Исправленная версия вводит разрешённые статические столбцы и ожидаемые шаблоны динамических полей перед использованием поля сортировки. | Сравните исходный код JoomSport 5.7.6 и 5.7.8. |
| Стенд демонстрирует слепую SQL-инъекцию на основе времени. | Уязвимая цель отвечает с задержкой при использовании инъецированного выражения `SLEEP()`; исправленная цель — нет. | Выполните `python3 poc/poc.py http://localhost:8081 http://localhost:8082`. |
## Допущения и неизвестные
В данном стенде JoomSport 5.7.6 используется в качестве уязвимой цели для сравнения, поскольку публичная исправленная версия — 5.7.8, а тега исходного кода 5.7.7 не было в списке SVN-тегов плагина на WordPress.org на момент подготовки стенда.
Стенд не утверждает, что 5.7.6 — единственная уязвимая версия. Она используется как воспроизводимая уязвимая базовая версия для сравнения уязвимого поведения с поведением исправленной версии 5.7.8.
Стенд сосредоточен на параметре `sortf` в процессе сортировки списка игроков.
Демонстрируемое воздействие — слепая SQL-инъекция на основе времени. Стенд не демонстрирует:
* прямой дамп базы данных,
* извлечение учётных данных,
* обход аутентификации,
* повышение привилегий,
* произвольное изменение данных,
* удалённое выполнение кода,
* закрепление в системе (persistence),
* внешние обратные вызовы,
* или атаки на системы, не входящие в состав стенда.
Возможно проявление error-based или boolean-based поведения в зависимости от поведения базы данных, конфигурации приложения и различий в ответах, но данный стенд не опирается на эти методы. Основное доказательство основано на временных задержках (timing-based).
## Сводка о корневой причине
Корневая причина — небезопасное формирование динамического SQL-выражения `ORDER BY` из параметра запроса `sortf`.
Уязвимый путь выполнения кода начинается в:```text
sportleague/classes/objects/class-jsport-playerlist.php
В логике загрузки списка игроков JoomSport читает параметр запроса:```text sortf
и использует его для создания:```text
$options['ordering']
Соответствующий шаблон уязвимого исходного кода:```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;
}
Проблема в первую очередь не в параметре `sortd`. Значение `sortd` ограничено:```text
ASC
DESC
Проблема в параметре sortf, поскольку он управляет позицией SQL-идентификатора/выражения, используемой для сортировки.
Опасное выражение:```php
"".classJsportRequest::get('sortf').""
Код помещает управляемые атакующим входные данные в контекст идентификатора MySQL и затем передаёт их как фрагмент SQL-сортировки.
Код применяет:```php
sanitize_text_field()
но sanitize_text_field() — это не проверка SQL-идентификаторов. Она предназначена для очистки текста, а не для безопасного построения SQL-синтаксиса.
Уязвимый код также оборачивает управляемое пользователем поле сортировки в обратные кавычки. Однако обратные кавычки не являются границей безопасности, когда атакующий может влиять на содержимое идентификатора. Если атакующий может внедрить обратную кавычку в значение, он сможет выйти за пределы предполагаемого контекста идентификатора.
Сгенерированное значение сортировки позже передаётся в запрос получения игрока и добавляется в SQL-предложение ORDER BY в:```text
sportleague/base/wordpress/classes/class-jsport-getplayers.php
Паттерн sink:```php
$query .= ' ORDER BY '.($ordering);
Это создаёт уязвимый поток данных:```text sortf request parameter → classJsportRequest::get('sortf') → $options['ordering'] → $ordering → ORDER BY
Проблема безопасности заключается в том, что приложение обрабатывает управляемый пользователем параметр запроса как идентификатор/выражение SQL без предварительной проверки его по строгому списку разрешённых значений.
## Краткое описание патча