
CVE-2026-63030
인증되지 않은 SQL 인젝션을 WordPress 코어에서 원격 코드 실행으로 연결하는 개념 증명(PoC)입니다. REST 배치 라우트 혼동(CVE-2026-63030)을 통해 작동합니다.
이 익스플로잇은 접근 가능한 대상 외에는 자격 증명이나 구성이 필요하지 않습니다. 단일 엔드포인트 POST /wp-json/batch/v1을 통해 인젝션에 도달합니다.
발견 자체는 인증되지 않은 SQL 인젝션입니다. check 명령어가 이를 확인하고, read 명령어가 임의 데이터베이스 읽기를 시연합니다. shell 명령어는 선택적 사후 익스플로잇(복구된 관리자 자격 증명 → 플러그인 업로드 → 명령 실행)으로, 전체 영향을 보여주기 위해 포함되었으며, 취약점 자체가 아닙니다.
| 브랜치 | 영향받는 버전 | 수정된 버전 |
|---|---|---|
| 6.9.x | 6.9.0 – 6.9.4 | 6.9.5 |
| 7.0.x | 7.0.0 – 7.0.1 | 7.0.2 |
6.9.0 이전 버전은 이 체인에 영향을 받지 않습니다.
REST 배치 엔드포인트(/batch/v1)는 인증되지 않으며, 각 하위 요청이 자체적으로 검증되고 권한 검사된다는 점에 의존하여 하나의 호출에서 여러 하위 요청을 실행합니다.
serve_batch_request_v1()은 두 개의 병렬 배열을 만듭니다 — $matches (하위 요청별로 일치하는 핸들러)와 $validation (하위 요청별로 검증 결과) — 그런 다음 디스패치 시 두 배열을 동일한 오프셋으로 인덱싱합니다. wp_parse_url()에 실패한 경로를 가진 하위 요청은 $validation에는 추가되지만 $matches에는 추가되지 않아 배열의 순서가 어긋나고, 하위 요청이 다른 하위 요청의 핸들러 아래에서 디스패치됩니다. 이것이 라우트 혼동입니다.
PoC는 이 프리미티브를 두 번 중첩합니다:
requests 본문을 전달하는 POST /wp/v2/posts 요청이 배치 핸들러 자체 아래에서 디스패치됩니다. 게시물 요청으로 검증되었으므로 requests 목록이 배치 스키마에 대해 검사되지 않아 하위 요청이 GET을 사용할 수 있습니다 — 메서드 허용 목록이 우회됩니다.author_exclude 문자열을 전달하는 GET /wp/v2/users 요청(사용자 스키마에는 해당 매개변수가 없으므로 값이 검증을 그대로 통과)이 게시물 get_items() 아래에서 디스패치됩니다. 여기서 author_exclude는 WP_Query의 author__not_in 쿼리 변수에 매핑되며, 취약한 빌드는 이를 SQL에 문자열로 보간합니다.결과는 인증 전에 도달 가능한 boolean 기반 및 시간 기반 블라인드 SQL 인젝션입니다. 데이터베이스 읽기 액세스 권한으로 관리자 비밀번호 해시를 복구할 수 있습니다. 해시가 크래킹되면 관리자 액세스로 플러그인 업로드를 통한 코드 실행이 가능합니다.
Python 3.8+ 및 표준 라이브러리. 타사 종속성이 없습니다.
저장소 디렉토리에서 실행하십시오:
./wp2shell.py <command> <url> [options]
또는 pip install .을 실행하여 PATH에 wp2shell 명령을 추가하십시오.
차등 시간 지연으로 익스플로잇 가능성을 확인합니다. 데이터를 읽거나 변경하지 않습니다.
./wp2shell.py check http://target
./wp2shell.py read http://target # 서버 지문
./wp2shell.py read http://target --preset users # 사용자 로그인 및 비밀번호 해시
./wp2shell.py read http://target --query "SELECT @@version"
선택적 사후 익스플로잇. 유효한 관리자 자격 증명이 필요합니다. 인젝션이 비밀번호 해시를 복구하므로, 여기서 복구된 평문을 제공하십시오.
./wp2shell.py shell http://target --user admin --password '<recovered>' --cmd id
./wp2shell.py shell http://target --user admin --password '<recovered>' -i # 대화형 셸
shell은 플러그인 웹셸(무작위 경로 및 실행별 토큰으로 잠김)을 업로드하고 해당 경로를 출력합니다. 사용 후 제거하십시오.
WordPress 6.9.5 또는 7.0.2로 업데이트하십시오. 그때까지는 /wp-json/batch/v1과 rest_route=/batch/v1 쿼리 매개변수를 모두 에지에서 차단하거나, rest_pre_dispatch 필터를 통해 배치 엔드포인트에 인증을 요구하십시오.
승인된 보안 테스트 전용입니다. 소유하고 있거나 명시적인 서면 허가를 받은 시스템에 대해서만 사용하십시오. 작성자는 오용에 대한 책임을 지지 않습니다.
| 옵션 | 적용 대상 | 설명 |
|---|
--rest-route | 모두 | /?rest_route=/batch/v1 사용 (예쁜 퍼머링크가 없는 사이트용). |
--proxy URL | 모두 | HTTP 프록시를 통해 트래픽 라우팅 (예: Burp). |
--timeout N | 모두 | 요청 타임아웃(초). |
--sleep N | check | 인젝션 확인에 사용되는 지연 시간. |
--preset | read | fingerprint 또는 users. |
--query | read | 읽을 스칼라 SQL 표현식. |
--prefix | read | 데이터베이스 테이블 접두사 (기본값 wp_). |
--max-length N | read | 값당 최대 읽기 문자 수 (기본값 128). |
--user / --password | shell | 관리자 자격 증명 (해시에서 복구된 평문). |
--cmd | shell | 실행할 명령 (-i 사용 시 생략). |
-i / --interactive | shell | 배포 후 대화형 셸 열기. |