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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-18322 — CVE-2026-18322에 대한 근본 원인 분석, 수동 버전 검사기, 그리고 실습용 PoC로, Supsystic의 Smart Popup WordPress 플러그인에서 발생하는 인증되지 않은 권한 상승 취약점입니다. | Kitploit
도구/GitHubGitHub/i3it/cve-2026-18322
Privilege EscalationVulnerability ScannersVulnerability AnalysisExploitationWeb Application ExploitationSecurity VirtualizationWeb SecurityPenetration TestingPapers & ResearchLabs & Practice
GitHub
226일 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
i3it/cve-2026-18322

CVE-2026-18322

CVE-2026-18322에 대한 근본 원인 분석, 수동 버전 검사기, 그리고 실습용 PoC로, Supsystic의 Smart Popup WordPress 플러그인에서 발생하는 인증되지 않은 권한 상승 취약점입니다.

저장소 보기

CVE-2026-18322 — Smart Popup by Supsystic 권한 상승

CVE Severity Affected Fixed in CWE Python Tests License

WordPress 플러그인 Smart Popup by Supsystic(popup-by-supsystic)의 인증되지 않은 권한 상승 취약점인 CVE-2026-18322에 대한 보안 연구입니다. 이 저장소에는 업스트림 소스 diff에서 도출한 근본 원인 분석, 추출된 패치, 영향을 받는 설치를 식별하기 위한 탐지 도구(수동 버전 핑거프린터), 그리고 익스플로잇 PoC를 위한 랩이 포함되어 있습니다.

이 취약점은 공개되었으며 패치되었습니다. 이 작업은 방어 목적으로 게시됩니다: 운영자가 영향을 받는 호스트를 찾아 수정할 수 있도록 돕기 위함입니다.


영향을 받는 버전

버전 범위상태
< 1.13.0취약함
>= 1.13.0수정됨

1.13.0(2026년 7월 31일 릴리스)이 첫 번째 패치 릴리스이며, 아래에 설명된 체인의 세 고리를 모두 복구합니다. 분석 §1을 참조하세요.


취약점 요약

세 가지 독립적인 약점이 결합하여 인증되지 않은 관리자 생성으로 이어집니다:

1. 권한 맵 충돌 — havePermissions()가 두 개의 권한 맵을 array_merge()로 결합했습니다. 둘 다 문자열 키 PPS_USERLEVELS('userlevels')를 사용하며, array_merge()는 문자열 키를 덮어쓰기하므로, 기본 컨트롤러의 짧은 기본 목록이 팝업 모듈의 목록을 통째로 대체했습니다 — 이로 인해 save 및 기타 9개 메서드에서 관리자 제한이 조용히 제거되었습니다:

root@kitploit:~
$permissions     = $mod->getController()->getPermissions();      // [... 'save' ...]
$permissionsBase = $mod->getController()->getBasePermissions();  // ['getListForTbl','removeGroup','clear']
$permissions     = array_merge($permissions, $permissionsBase);  // base wins — 'save' is gone

이 검사는 열린 상태로 실패합니다: 맵에 없는 액션은 결코 거부되지 않습니다.

2. 낯선 사람에게 메일로 발송되는 재사용 가능한 nonce — save는 여전히 pps_nonce를 요구했지만, 구독 확인 이메일에 바로 그 nonce 액션이 포함되어 있었습니다. 로그아웃된 사용자의 경우 WordPress nonce는 uid=0을 기준으로 키가 생성되므로, 익명 구독자를 위해 발급된 토큰이 모든 익명 공격자에게 유효합니다.

3. 서버 측 역할 허용 목록 없음 — createWpSubscriber()는 구성된 역할을 그대로 WP_User::set_role()에 전달했습니다. 플러그인의 안전한 역할 목록(administrator 제외)은 관리자 드롭다운을 렌더링할 때만 적용되었습니다 — UI 전용 제어였습니다.

연결하면: 구독하여 nonce 획득 → popup::save에 재전송하여 sub_wp_create_user_role=administrator 설정 → 구독 흐름 트리거 → 영구 관리자 계정 생성.

파일/줄 참조가 포함된 전체 설명: docs/ANALYSIS.md.


탐지 — 수동 검사기

poc/cve_2026_18322_check.py는 사이트가 영향을 받는 버전을 실행 중인지 판별합니다. 익스플로잇을 시도하지 않습니다: 일반 HTTP GET을 보내고 설치가 스스로 공개하는 버전을 읽습니다.

설치

root@kitploit:~
git clone <this-repo> && cd CVE-2026-18322
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

requests는 권장되지만 선택 사항입니다 — 도구는 표준 라이브러리로 폴백합니다.

사용법

root@kitploit:~
# Single target
python3 poc/cve_2026_18322_check.py https://example.com

# With supporting evidence
python3 poc/cve_2026_18322_check.py https://example.com -v

# Many targets, concurrently, exporting results
python3 poc/cve_2026_18322_check.py -f targets.txt -t 20 --json results.json
python3 poc/cve_2026_18322_check.py -f targets.txt --csv results.csv --only-vulnerable

# Through a proxy, ignoring TLS errors (lab use)
python3 poc/cve_2026_18322_check.py https://staging.internal -k --proxy http://127.0.0.1:8080

대상은 인수로 주거나 -f로 줄 수 있습니다(-는 stdin을 읽음). 호스트 이름만 주어지면 https://로 간주합니다.

예시

root@kitploit:~
$ python3 poc/cve_2026_18322_check.py https://example.com -v
[VULNERABLE] https://example.com/  (Smart Popup by Supsystic 1.11.2)  < 1.13.0 affected by CVE-2026-18322; upgrade to 1.13.0+
      - asset-version: plugin asset enqueued with ?ver=1.11.2  (https://example.com/)
      - homepage-reference: references /plugins/popup-by-supsystic/  (https://example.com/)
      - readme: plugin readme.txt is publicly readable  (https://example.com/wp-content/plugins/popup-by-supsystic/readme.txt)
      - readme-stable-tag: Stable tag: 1.11.2  (.../readme.txt)

상태

종료 코드: 0 = 취약한 대상 없음, 1 = 최소 하나 취약함, 2 = 사용법 오류.

탐지 방법

두 가지 수동 신호, 둘 다 공개 리소스에 대한 일반 HTTP GET입니다:

  1. 에셋 캐시 버스터 — 플러그인은 CSS/JS를 ?ver=PPS_VERSION으로 enqueue하므로(classes/frame.php:410,473), 홈페이지가 종종 정확한 버전을 노출합니다.
  2. readme.txt — Stable tag:가 권위 있으며 잠재적으로 오래된 캐시된 에셋보다 우선합니다; 변경 로그는 폴백으로 사용됩니다.

홈페이지 스캔은 또한 이름이 변경된 wp-content 디렉터리(예: Bedrock의 /app/)를 발견하므로 readme 조회가 사이트의 실제 레이아웃을 따릅니다.


안전성

탐지 도구는 익스플로잇을 시도하지 않습니다. 이 CVE에 대한 무기화된 익스플로잇은 여기에 게시되지 않습니다: 전체 체인을 실행하는 유일한 코드는 로컬 랩에 하드 게이트되어 있습니다(아래 참조).

수동 검사기는 버전 핑거프린팅만 수행합니다. 그 HttpClient는 GET 외의 HTTP 메서드를 노출하지 않습니다 — 구조적으로 강제되며 테스트 스위트에서 검증됩니다. 따라서 실수로도 상태를 변경하는 요청을 보낼 수 없습니다. popup::save를 호출하거나, sub_wp_create_user_role 파라미터를 보내거나, 구독 양식을 제출하거나, 확인 이메일을 트리거하거나, 사용자, 팝업 또는 설정을 생성하거나 수정하지 않습니다. 두 개의 공개 리소스 — 홈페이지와 readme.txt — 만 읽고 그 외에는 아무것도 하지 않습니다.

그 안전성에는 대가가 따르며, 솔직히 말하면: 판정은 호스트가 게시하는 버전 메타데이터만큼만 좋습니다. 트레이드오프와 실패 모드: §9.

랩 익스플로잇은 랩에서만 실행됩니다

lab/exploit_full_chain.py는 여기서 실제 공격을 수행하는 유일한 코드 조각이며, WordPress 관리자를 생성합니다. 이는 분석을 신뢰로 받아들이는 대신 재현할 수 있도록 게시됩니다 — 입증할 수 없는 권한 부여 버그에 대한 주장은 발견이 아니라 단언입니다. 이는 lab/의 일회용 스택을 위해 작성되었으며 그 외에는 아무것도 아닙니다:

  • 비로컬 대상은 거부됩니다. 대상 호스트 이름이 확인되고 반환되는 모든 주소가 루프백 또는 RFC1918 사설이어야 합니다. 공용 DNS 이름은 현재 사설 주소로 확인되더라도 거부됩니다 — 이는 "랩" 도구를 프로덕션으로 겨냥하는 잘 알려진 방법입니다.
  • --lab-confirm은 필수입니다. 두 검사 모두 첫 HTTP 요청 전에 assert_lab_target()에서 실행되므로, 거부된 호출은 대상을 전혀 건드리지 않습니다.
  • 랩의 메일박스만 읽을 수 있습니다. 1단계는 랩의 Mailpit API(http://localhost:8025/api/v1/…)를 통해 구독 확인 이메일에서 재사용 가능한 pps_nonce를 수집합니다. 그 이메일을 다른 곳에서 검색하는 코드 경로는 없으므로, 체인은 랩 외부의 호스트에 대해 첫 단계가 없습니다.
  • 대상 랩은 외부에서 접근할 수 없습니다. lab/docker-compose.yml의 모든 서비스는 127.0.0.1에 바인딩됩니다.

따라서 배포된 그대로 실제 사이트를 겨냥할 수 없습니다 — 요청을 보내기 전에 REFUSING TO RUN에서 멈춥니다:

root@kitploit:~
$ python3 exploit_full_chain.py https://example.com --lab-confirm
REFUSING TO RUN: example.com resolves to non-local address(es) 104.20.23.154, ...
This script creates a WordPress administrator and is for the local lab only.
To test a real site, use the non-destructive checker in ../poc/.

이 가드들은 장식이 아니라 하중을 지탱합니다: 스크립트는 실제 체인이며, 이를 시연으로 유지하는 것은 일회용 로컬 스택 외부에서는 실행되지 않는다는 점입니다. 제거하지 마시고 SECURITY.md를 참조하세요 — 이를 약화시키는 변경이나 랩 외부에서 실행되도록 의도된 독립형 익스플로잇은 이 저장소의 범위를 벗어납니다. 실제 사이트가 영향을 받는지 확인하려면 poc/를 사용하세요 — 검사기는 아무것도 건드리지 않고 같은 질문에 답합니다.

통제하는 호스트에 대한 권위 있는 답변을 위해:

root@kitploit:~
grep -n "array_merge(\$permissions, \$permissionsBase)" \
     wp-content/plugins/popup-by-supsystic/classes/frame.php

출력이 있으면 호스트가 취약합니다 — 그 줄이 바로 1.13.0이 교체한 것입니다.

소유하거나 명시적으로 테스트 권한을 받은 시스템에만 사용하세요. SECURITY.md를 참조하세요.


재현 — 시연 랩

lab/에는 취약점을 엔드투엔드로 실행하는 일회용 Docker 스택이 있어 분석을 신뢰로 받아들이는 대신 검증할 수 있습니다:

root@kitploit:~
cd lab
./setup.sh                                                    # WordPress + plugin 1.12.0
../.venv/bin/python exploit_full_chain.py http://localhost:8080 --lab-confirm
./verify.sh                                                   # confirm from the database
./teardown.sh

가장 유용한 출력은 버전 비교입니다 — 세 릴리스에 대한 동일한 요청:

root@kitploit:~
./setup.sh --plugin-version 1.11.2    # exploit succeeds
./setup.sh --plugin-version 1.12.0    # exploit succeeds
./setup.sh --plugin-version 1.13.0    # exploit fails at phase 2

랩은 의도적으로 취약하며 그 익스플로잇 스크립트는 WordPress 관리자를 생성합니다. 모든 것이 127.0.0.1에 바인딩되며, 스크립트는 로컬 랩 외에는 실행되지 않습니다 — 랩 익스플로잇은 랩에서만 실행됩니다를 참조하세요. 스캐너가 아닙니다; 실제 사이트를 확인하려면 poc/를 사용하세요.


수정

  1. 1.13.0 이상으로 업데이트하세요.
  2. 업데이트할 수 없다면 플러그인을 비활성화하세요. 부분 완화는 약합니다 — 취약한 액션은 모든 익명 요청으로 도달할 수 있습니다.
  3. 구독 팝업이 활성화된 영향을 받는 버전을 실행했다면 침해 여부를 감사하세요: 예상치 못한 관리자 계정, sub_wp_create_user_role이 권한 있는 역할로 설정된 팝업, 그리고 pl=pps&mod=popup&action=save를 포함하여 admin-ajax.php로 가는 POST 요청.

쿼리 및 로그 grep: §10.


저장소 레이아웃

root@kitploit:~
.
├── README.md
├── SECURITY.md                  Scope, authorized-use policy, disclosure
├── LICENSE                      MIT
├── requirements.txt
├── docs/
│   └── ANALYSIS.md              Full root-cause analysis and fix rationale
├── patches/
│   ├── 01-frame-permission-merge.diff              array_merge() → _mergePermissions()
│   ├── 02-subscribe-role-allowlist-and-nonce.diff  Role allowlist + dedicated nonce
│   └── 03-v1.12.0-confirmation-page-hardening.diff Unrelated hardening added in 1.12.0
├── poc/
│   └── cve_2026_18322_check.py  Passive version fingerprint (GET only)
├── lab/                         Disposable Docker lab — INTENTIONALLY VULNERABLE
│   ├── docker-compose.yml       MariaDB + WordPress 1.12.0 + Mailpit (loopback only)
│   ├── setup.sh / teardown.sh   Bring the lab up / destroy it
│   ├── exploit_full_chain.py    Full attack chain — CREATES AN ADMIN; lab-gated
│   └── verify.sh                Independent confirmation from the database
├── scripts/
│   └── fetch_versions.sh        Export plugin versions from SVN and regenerate diffs
└── tests/
    └── test_check.py            Offline unit tests for the passive checker

개발

root@kitploit:~
pip install -r requirements.txt pytest
python3 -m pytest tests/ -v

스위트는 완전히 오프라인입니다 — 기록된 픽스처를 사용하며 라이브 대상을 사용하지 않습니다. 1.13.0 경계를 넘는 버전 분류, 대상 정규화, 그리고 각 상태를 결정하는 증거 규칙을 다룹니다.

안전 속성은 문서화될 뿐만 아니라 검증됩니다: 전체 스캔이 상태를 변경하는 요청을 발행하지 않으며, HttpClient가 GET 외의 HTTP 메서드를 노출하지 않는다는 것입니다.

개발 중 발견된 두 가지 회귀가 고정되어 있습니다: 줄 앵커 파싱을 무력화하는 CRLF readme.txt, 그리고 HTTP 오류 페이지가 플러그인 증거로 잘못 계산되는 문제.

업스트림 소스에서 분석을 재현하려면:

root@kitploit:~
./scripts/fetch_versions.sh          # exports 1.11.2 / 1.12.0 / 1.13.0 and regenerates patches/

라이선스

MIT — LICENSE를 참조하세요. 분석된 플러그인은 GPLv2-or-later이며 여기서 재배포되지 않습니다; scripts/fetch_versions.sh가 공식 WordPress SVN 저장소에서 가져옵니다.

도구 다운로드
상태의미
VULNERABLE플러그인이 < 1.13.0에서 탐지됨
NOT_VULNERABLE플러그인이 >= 1.13.0에서 탐지됨
PLUGIN_DETECTED_VERSION_UNKNOWN플러그인 존재, 버전 확인 불가 — 수동으로 확인
PLUGIN_NOT_DETECTED플러그인의 증거 없음(부재의 증명은 아님)
ERROR대상에 연결할 수 없거나 형식이 잘못됨