
취약점 개요
| 항목 | 내용 |
| CVE | CVE-2026-89274 |
| 대상 | WordPress 플러그인 WP Recipe Maker |
| 영향 버전 | 10.8.1 이하 |
| 패치 버전 | 10.8.2 |
| 유형 | CWE-94 (Code Injection) — 임의 shortcode 실행 |
| CVSS 3.1 | 9.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N) |
| 인증 | 불필요 (단, 댓글이 승인되어야 함) |
한 줄 요약입니다. 방문자가 남긴 평점 댓글 내용이 do_shortcode()에 그대로 들어가서, 댓글에 적은 [shortcode]가 서버에서 실행됩니다.
주의할 점이 하나 있습니다. 이 취약점은 임의 PHP 실행(RCE)이 아닙니다. 사이트에 이미 등록된 shortcode만 실행할 수 있고, 피해 범위는 그 shortcode가 무엇을 하느냐에 따라 달라집니다.
배경지식: shortcode와 JSON-LD
shortcode란?
WordPress에서 [tag 옵션] 형태로 적는 문법입니다. 글에 이렇게 쓰면
[gallery ids="1,2,3"]
WordPress가 do_shortcode()를 호출하는 순간 gallery에 등록된 PHP 함수가 실행되고, 그 반환값(HTML)으로 치환됩니다.

핵심은 do_shortcode()가 호출되면 문자열 속 shortcode는 무조건 실행된다는 점입니다. 그래서 do_shortcode()에는 신뢰할 수 있는 문자열만 넣어야 합니다. 글 작성자(author/editor)가 쓴 본문은 신뢰할 수 있지만, 방문자가 쓴 댓글은 신뢰할 수 없습니다.
JSON-LD란?
검색엔진에 "이 페이지는 레시피이고, 별점은 이렇고, 리뷰는 이렇다"고 알려주는 구조화 데이터입니다. 페이지 HTML 안에 이렇게 들어갑니다.

WP Recipe Maker는 평점이 달린 댓글을 이 review 배열의 reviewBody에 넣습니다. 이 JSON-LD는 모든 방문자와 검색 크롤러에게 공개되는 영역입니다.
취약한 코드 분석
데이터 흐름


그림 2 설명. 위에서 아래로 읽는 5단계 체인입니다. 맨 위 황토색 카드(①)가 신뢰할 수 없는 입력(Source)이고, 맨 아래 빨간 카드(⑤)가 실행 지점(Sink)입니다. 카드 오른쪽 아래의 작은 글씨는 해당 코드의 줄 번호입니다. 오른쪽의 빨간 점선 괄호는 ①에서 ⑤까지 검증이나 필터링 단계가 하나도 없다는 뜻입니다. 입력이 곧바로 실행으로 이어진다는 점을 이 그림 한 장으로 확인할 수 있습니다.
① 어떤 댓글을 가져오는가 (:973, :1016)

- 대상은 레시피가 들어 있는 글의 승인된 평점 댓글입니다.
- reviewBody에는 comment_content가 검증 없이 그대로 들어갑니다. 여기까지는 문제가 아닙니다. 문제는 다음 단계입니다.
② 취약점의 핵심: sanitize_metadata() (:553)
메타데이터를 출력하기 전에 "정리(sanitize)"하는 함수입니다. 배열이면 안으로 들어가고, 문자열이면 정리합니다.

이 한 줄이 취약점의 전부입니다. 안쪽부터 실행되는 순서대로 읽어 보겠습니다.
| 순서 | 함수 | 하는 일 |
| 1 | do_shortcode( $metadata ) | shortcode를 실행하고 결과 문자열로 치환 |
| 2 | wp_strip_all_tags( ... ) | 결과에서 HTML 태그 제거 |
| 3 | strip_shortcodes( ... ) | 남아 있는 shortcode 문법 제거 |
개발자의 의도는 "shortcode와 태그를 다 지워서 깨끗한 텍스트만 JSON-LD에 넣자"였을 것입니다. 그런데 지우기(2, 3번) 전에 실행(1번)이 먼저 일어납니다. 2, 3번은 이미 실행된 결과물을 청소할 뿐이라, 서버 쪽 실행을 막지 못합니다.
비유하면 이렇습니다. 택배 상자를 "폭발물 검사 후 배달"해야 하는데, 상자를 먼저 열어 내용물을 작동시키고 나서 포장지를 검사하는 셈입니다.
왜 하필 reviewBody인가?
sanitize_metadata()는 배열의 모든 문자열 필드에 do_shortcode()를 적용합니다. 레시피 이름이나 재료 같은 필드는 관리자가 입력한 신뢰 데이터이니 평소엔 문제가 없습니다. 그런데 방문자가 쓴 댓글이 같은 배열에 섞여 들어오는 통로가 reviewBody 하나였습니다. 신뢰 데이터용으로 만든 처리 로직에 비신뢰 데이터가 합류한 것입니다.
공격 흐름
- 공격자가 레시피가 들어 있는 글에 평점과 함께 댓글을 작성합니다. 본문에 shortcode 문법을 넣습니다. (wprm-comment-rating 값이 있어야 리뷰로 취급됩니다.)
- 댓글이 사이트의 승인 기준을 통과합니다. 자동 승인이거나 관리자가 승인한 경우입니다.
- 누군가 그 레시피 페이지를 열면 플러그인이 메타데이터를 만듭니다. 승인된 평점 댓글이 review에 포함됩니다.
- sanitize_metadata()가 댓글 본문에 do_shortcode()를 실행하고, shortcode가 서버에서 실행됩니다.
- 실행 결과가 reviewBody에 들어가 JSON-LD로 출력되고, 모든 방문자와 크롤러에게 노출됩니다.

그림 1 설명. 가로 세 개의 레인(공격자 / 사이트 / 방문자·크롤러)을 번호 ①~⑥ 순서대로 따라가며 읽습니다. 공격자는 ① 한 번만 등장하고, 이후는 모두 사이트와 방문자 레인에서 일어납니다. 곡선 화살표가 레인 사이를 오가는 부분은 "댓글 승인 → 누군가의 페이지 요청 → 메타데이터 생성"의 흐름입니다. ⑤번 카드만 빨간 강조선이 있는데, 서버에서 shortcode가 실행되는 지점이라는 뜻입니다. ⑤에서 ⑥으로 내려가는 빨간 화살표는 실행 결과가 방문자에게 그대로 전달된다는 표시입니다. 공격자가 아닌 방문자 레인에 결과가 도착한다는 점이 이 그림의 핵심입니다.
참고로 WordPress 기본 설정에는 "이전에 승인된 댓글이 있는 작성자만 자동 승인"이 켜져 있습니다. 그래서 첫 댓글은 대기 상태로 걸리는 경우가 많고, 이 점이 공격 난이도를 어느 정도 낮춥니다. 반대로 승인 정책이 느슨한 사이트는 바로 노출됩니다.
영향
- 실행 결과가 페이지에 박히기 때문에, 출력을 내놓는 shortcode가 정보 유출 통로가 됩니다. 어드바이저리가 예로 든 것은 첨부파일 캡션, 비공개 글의 필드, 설치된 플러그인이 노출하는 데이터입니다.
- 부작용이 있는 shortcode가 설치되어 있다면, 페이지가 렌더링될 때마다 반복 실행될 수 있습니다.
- 페이지에 서버 측 코드 실행 능력이 직접 생기는 것은 아니므로 RCE로 볼 수는 없습니다.
패치 분석 (10.8.2)

바뀐 곳은 do_shortcode() → WPRM_Instacart::do_shortcode_safe() 하나입니다.
- do_shortcode_safe()는 shortcode를 실행하지 않습니다. shortcode 태그는 걷어내고 안쪽 내용만 남깁니다. (class-wprm-instacart.php:501)
- 같은 입력이라도 이제 shortcode 출력이 reviewBody에 찍히지 않고, 문법만 제거되거나 아무것도 실행되지 않습니다.
- 공식 변경 로그에도 "recipe metadata 안의 댓글 텍스트에서 shortcode가 실행되지 않도록 수정"이라는 항목이 있습니다.

그림 3 설명. 위 줄이 10.8.1, 아래 줄이 10.8.2의 처리 순서입니다. 세 칸 중 첫 칸만 색이 있고 나머지는 회색입니다. 패치에서 바뀐 곳이 첫 단계 한 줄뿐이라는 점을 색으로 보여주려는 것입니다. 위 줄 아래의 빨간 괄호는 2, 3번 방어 코드가 실행(1번)보다 뒤에 있어서 이미 늦었다는 뜻이고, 아래 줄의 청록 괄호는 첫 단계에서 실행 자체를 차단한다는 뜻입니다.

그림 4 설명. 위의 같은 댓글 한 개가 좌우 두 갈래로 나뉘어 각각 10.8.1과 10.8.2에서 처리됩니다. 왼쪽(10.8.1)은 reviewBody 값에 shortcode의 실행 결과가 들어가 모든 방문자에게 공개되고, 오른쪽(10.8.2)은 shortcode가 제거되어 실행되지 않습니다. 강조된 줄만 보면 두 버전의 차이를 바로 알 수 있습니다. 오른쪽의 빈 값은 shortcode만 있는 댓글을 기준으로 한 예이며, 안쪽에 글이 있는 shortcode라면 그 글은 남을 수 있습니다.
대응 방법
- WP Recipe Maker를 10.8.2 이상, 가능하면 최신 버전으로 업데이트합니다.
- 업데이트 전 임시 조치로 평점 댓글 승인 정책을 수동 승인으로 바꾸고, 대기 중이거나 승인된 댓글 중 [ ] 문법이 들어간 것을 점검합니다.
- 사이트에 등록된 shortcode 중 민감한 데이터를 출력하는 것이 없는지 함께 점검합니다.
'CVE 취약점' 카테고리의 다른 글
| CVE-2026-93485 분석: WordPress 댓글 하나로 관리자 서버를 장악하는 Comment2XSS (0) | 2026.10.10 |
|---|---|
| CVE-2026-38526 취약점 분석: Krayin CRM TinyMCE 파일 업로드 RCE (0) | 2026.10.08 |
| CVE-2026-6951: simple-git --config 플래그 우회를 통한 원격 코드 실행(RCE) 분석 (0) | 2026.10.07 |
| CVE-2026-94504 분석: Ninja Forms 저장형 XSS, </textarea> 한 줄로 관리자 화면을 뚫다 (0) | 2026.10.06 |
| CVE-2026-29057: Next.js Rewrites HTTP Request Smuggling 분석 (0) | 2026.10.05 |