NOW Briefing
-2026-jul 패치를 적용해야 합니다. 2.4.9도 영향 버전이므로 버전 상향만으로는 해결되지 않습니다.
Adobe Commerce 장바구니 API 미인증 파일 업로드 취약점 (CVE-2026-48356)
■ 개요
Adobe Commerce는 어도비가 제공하는 기업용 전자상거래 플랫폼이고, Magento Open Source는 같은 코드베이스의 오픈소스 배포판입니다. 두 제품의 REST API에는 미인증 사용자가 실행 가능한 파일을 서버에 저장할 수 있는 취약점이 있습니다. CISA는 2026년 10월 27일 이 취약점을 실제 악용이 확인된 취약점 목록(KEV)에 등재했고, 미국 연방기관의 조치 기한을 2026년 11월 10일로 지정했습니다.
영향을 받는 범위는 Magento Open Source 2.4.9와 2.4.8-p5·2.4.7-p10·2.4.6-p15 이하이며, Adobe Commerce는 여기에 2.4.5-p17 이하와 2.4.4-p18 이하까지 포함됩니다. 공격은 고객 계정이나 관리자 권한 없이 게스트 장바구니 API에 요청을 보내는 것으로 시작하고, 업로드된 파일은 웹에서 직접 접근할 수 있는 미디어 디렉터리에 그대로 저장됩니다. 공격자는 상점 서버에서 웹 서버 계정 권한으로 임의의 PHP 코드를 실행할 수 있습니다.
Sansec은 자사가 보호하는 상점을 기준으로 2026년 3월 17일 공개 경고를 낸 뒤 3월 19일 첫 공격을 관측했습니다. 이어 3월 23일 대량 스캔이 시작돼 4월 14일에는 상점의 82%에 악성 업로드가 이뤄졌다고 밝혔습니다. 2026년 10월 공개된 Sansec의 후속 분석에서는 2025년 7월부터 이어진 CMS 블록 로더 캠페인으로 953개 상점이 감염됐고, 그중 471개 상점은 3월 이 취약점으로 웹셸이 올라간 뒤 한 시간 만에 로더가 주입된 것으로 집계됐습니다. 로더가 받아오는 최종 페이로드는 확보되지 않아 공격의 최종 목적은 확인되지 않았습니다. 이 취약점을 대상으로 하는 공개 PoC 코드도 나와 있습니다.
■ 요약
| 항목 | 내용 |
|---|---|
| CVE ID | CVE-2026-48356 (게스트 장바구니 REST API의 업로드 파일 검증 누락) |
| CVSS 점수 | CVSS v3.1 9.6 (Adobe), 9.3 (NVD) |
| 취약점 유형 | CWE-434, 위험한 유형의 파일 업로드 제한 없음 → 미인증 원격 코드 실행 |
| 영향/위험 | • 인증 없이 실행 가능한 PHP 파일을 웹 접근 가능 경로에 저장 가능 • 저장된 파일 호출로 상점 서버에서 임의 코드 실행 가능 • 실제 공격 관측됨 (CISA KEV 등재, 2026-10-27) • 상점 콘텐츠 블록에 외부 페이로드 로더 주입 사례 보고됨 |
| 취약 버전 | • Adobe Commerce 2.4.9, 2.4.8-p5·2.4.7-p10·2.4.6-p15·2.4.5-p17·2.4.4-p18 이하 • Magento Open Source 2.4.9, 2.4.8-p5·2.4.7-p10·2.4.6-p15 이하 |
| 패치 버전 | • Adobe Commerce 2.4.9-2026-jul, 2.4.8-2026-jul, 2.4.7-2026-jul, 2.4.6-2026-jul, 2.4.5-2026-jul, 2.4.4-2026-jul • Magento Open Source 2.4.9-2026-jul, 2.4.8-2026-jul, 2.4.7-2026-jul, 2.4.6-2026-jul |
■ 기술 분석
게스트 장바구니에 상품을 담는 REST 요청(POST /rest/default/V1/guest-carts/{cartId}/items)에는 상품의 커스텀 옵션 값을 함께 넣을 수 있습니다. 그중 파일 업로드용 옵션에 쓰이는 file_info 필드에는 base64로 인코딩한 파일 내용과 파일 이름이 담깁니다. 연구자 분석 기준 이 값은 프레임워크의 이미지 처리 컴포넌트 ImageProcessor가 처리하며, 결과 파일은 pub/media/custom_options/quote/ 아래 파일 이름에서 파생된 두 단계 하위 경로에 생성됩니다. Sansec은 이 경로에서 세 가지 검사가 빠져 있다고 지적했습니다. 제출된 옵션 ID가 해당 상품의 실제 옵션인지 확인하지 않고, 상품에 파일 유형 옵션이 아예 없어도 업로드 로직이 실행되며, 저장 파일의 확장자를 제한하지 않습니다. 같은 분석에서 GraphQL 변경 요청은 다른 코드 경로를 쓰기 때문에 영향을 받지 않는다고 밝혔습니다.
업로드 값의 유효성 검사는 프레임워크 공통 클래스 Magento\Framework\Api\ImageContentValidator의 isValid() 메서드가 맡습니다. 아래는 공개 저장소 2.4.8 태그에 있는 해당 메서드입니다.
public function isValid(ImageContentInterface $imageContent)
{
$fileContent = @base64_decode($imageContent->getBase64EncodedData(), true);
if (empty($fileContent)) {
throw new InputException(new Phrase('The image content must be valid base64 encoded data.'));
}
$imageProperties = @getimagesizefromstring($fileContent);
if (empty($imageProperties)) {
throw new InputException(new Phrase('The image content must be valid base64 encoded data.'));
}
$sourceMimeType = $imageProperties['mime'];
if ($sourceMimeType != $imageContent->getType() || !$this->isMimeTypeValid($sourceMimeType)) {
throw new InputException(new Phrase('The image MIME type is not valid or not supported.'));
}
if (!$this->isNameValid($imageContent->getName())) {
throw new InputException(new Phrase('Provided image name contains forbidden characters.'));
}
return true;
}
검사 항목은 세 가지뿐입니다. 디코딩된 내용이 getimagesizefromstring()으로 이미지로 파싱되는지, 그렇게 판별된 MIME 타입이 요청에 선언된 타입과 같고 허용 목록에 있는지, 그리고 파일 이름이 isNameValid()를 통과하는지입니다. GIF89a 헤더로 시작하는 정상 이미지 뒤에 PHP 코드를 덧붙인 polyglot(하나의 파일이 두 포맷으로 동시에 해석되는 파일)은 앞의 두 검사를 모두 통과합니다. 남은 관문인 파일 이름 검사는 같은 파일의 isNameValid()가 처리합니다.
protected function isNameValid($name)
{
// Cannot contain \ / ? * : " ; < > ( ) | { }
if ($name === null || !preg_match('/^[^\\/?*:";<>()|{}\\\\]+$/', $name)) {
return false;
}
return true;
}
이 정규식은 경로 조작이나 구문 삽입에 쓰이는 문자만 거부하고 확장자는 보지 않습니다. 따라서 .php, .phtml, .phar로 끝나는 이름이 그대로 유지된 채 웹 루트 아래 미디어 경로에 저장됩니다. 웹 서버가 해당 파일을 PHP로 처리하도록 설정돼 있으면 해당 URL을 호출할 때 PHP로 실행됩니다.
이 파일의 내용은 공개 저장소의 2.4.8 태그와 2.4.9 태그에서 동일하며, Adobe 공지도 2.4.9를 영향 버전으로 명시하고 각 라인에 -2026-jul 격리 패치를 별도로 배포합니다. 다만 Sansec은 2026년 5월 12일 공개된 2.4.9에 수정이 포함됐다고 정리해 두 설명이 갈립니다. Adobe의 수정은 새 포인트 릴리스 번호 없이 제공돼, 확인한 공개 저장소 태그와 릴리스 범위에서는 공식 수정 diff를 식별하지 못했습니다.
■ PoC
공개된 익스플로잇 저장소에서 Magento Open Source 2.4.8-p5를 대상으로 하는 파이썬 코드와 Docker 기반 재현 환경을 확인했습니다. 저장소 최상위 스크립트는 랩 환경을 띄운 뒤 실제 공격 코드인 lab/poc.py를 실행합니다. 이 코드는 테스트 상품 식별자(SKU)가 존재하는지 GraphQL로 확인한 뒤 인증 없이 게스트 장바구니를 만들고, 커스텀 옵션의 파일 정보에 GIF 헤더와 PHP 코드를 함께 담은 파일을 .php 이름으로 올립니다. 응답 코드가 200이고 응답 본문에 업로드된 파일 이름이 그대로 나타나면 성공으로 판정하며, 저장된 파일을 호출해 코드를 실행하는 단계는 포함하지 않습니다. 저장소에 포함된 실행 환경은 로컬 루프백 주소와 포트 18096, 미리 만들어 둔 테스트 상품을 전제로 합니다.
PoC 코드는 본문에 싣지 않았습니다. 원문은 참고 자료의 링크에서 확인할 수 있습니다.
⚠️ WARN
재현 검증은 외부와 분리된 환경에서만 수행해야 합니다.
운영 중인 상점을 대상으로 업로드를 시도하면 그 자체로 실행 가능한 파일을 남깁니다.
■ 탐지 및 점검
• find pub/media/custom_options/ -type f ! -name '.htaccess'로 해당 경로의 파일을 모두 나열하고, .php·.phtml·.phar 등 이미지가 아닌 파일이 있는지 확인합니다.
• 웹 서버 접근 로그에서 /rest/default/V1/guest-carts/ 경로로 들어온 POST·PUT 요청의 출처와 빈도를 2026년 3월 이후 구간까지 소급해 조회합니다.
• Sansec이 보고한 백도어 파일 accesson.php를 find /var/www -name 'accesson.php' -type f로 웹 루트 전체에서 검색합니다. 이 백도어는 응답에 8194460을 출력하므로, 파일명과 이 응답 문자열을 함께 확인해 오탐을 줄입니다.
• 관리자 콘솔의 CMS 블록과 정적 블록, cms_block 테이블에서 최근 수정 이력을 확인하고 외부 스크립트를 불러오는 코드가 추가됐는지 점검합니다.
• 상점 페이지와 CMS 블록, 서버 통신 기록에서 lanhd6549tdhse[.]top, jslibrary[.]net, canevaslab[.]com, deepveindrilling[.]com 호출 흔적을 확인합니다. 주입된 로더는 방문자 브라우저에서 실행되므로 서버 로그만으로는 드러나지 않을 수 있습니다. 전체 지표 목록은 참고 자료의 Sansec 원문에서 확인합니다.
✅ CHECK
pub/media/custom_options/quote/의 파일이 정상적인 고객 업로드인지 확인해야 합니다.
이 경로에서 비이미지 파일이 발견되면 악성 업로드 여부를 확인하고 전수 점검해야 합니다.
■ 대응 방안
• 운영 중인 제품 라인에 맞는 -2026-jul 패치를 적용합니다. 2.4.9도 영향 버전 목록에 포함되므로 최신 라인으로 올리는 것만으로는 조치가 끝나지 않습니다.
• 패치 적용 전까지는 웹 애플리케이션 방화벽이나 리버스 프록시에서 외부의 게스트 장바구니 항목 추가·수정 요청을 차단하거나 속도 제한을 적용합니다.
• 미디어 디렉터리에서 PHP 파일이 실행되지 않도록 웹 서버 설정을 점검합니다. 업로드 자체를 막지는 못하지만 저장된 파일의 실행을 끊는 2차 방어선이 됩니다.
• KEV 등재로 실제 악용이 확인된 만큼, 외부 노출 이력이 있는 상점은 침해 가능성을 전제로 우선 조사합니다. 웹셸이나 콘텐츠 블록 주입이 발견되면 관리자 계정 비밀번호와 API 통합 토큰, 결제 연동 자격증명을 폐기하고 재발급합니다.
💡 TIP
패치를 적용해도 이미 올라간 웹셸은 그대로 남습니다.
패치 작업과 파일 점검·제거를 하나의 작업으로 묶어 처리해야 합니다.
[참고 자료]
• Adobe 보안 공지 APSB26-73 — Adobe Commerce 보안 업데이트
• CISA — 실제 악용 취약점 2건 추가 공지 (2026-10-27)
• CISA 실제 악용 취약점 목록 데이터 (등재일·조치 기한)
• Sansec 연구 — Magento PolyShell 분석 및 침해 지표
• Sansec 연구 — Magento CMS 블록 로더 캠페인 (953개 상점)
• Searchlight Cyber 연구 — Magento PolyShell 미인증 파일 업로드 분석
• Magento Open Source 2.4.8 소스 — ImageContentValidator.php
• Magento Open Source 2.4.9 소스 — ImageContentValidator.php
• 공개 PoC 저장소 — CVE-2026-48356 (고정 커밋)
• 공개 PoC 원문 — lab/poc.py (고정 커밋)