
OpenCart 4.1.0.4 리워드 포인트와 Free Checkout 결제 우회에 대한 개념 증명 익스플로잇 및 실습 환경으로, 인증된 고객이 포인트를 유지하면서 주문 금액을 적게 지불할 수 있게 한다.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · opencart-reward-free-checkout
OpenCart 4.1.0.4 - OpenCart Ltd
CVE-2025-15116은 4.1.0.3까지 존재했던 쿠폰 레이스였다. 4.1.0.4에서는 coupon.save가 쿠폰이 변경될 때 payment_method를 unset한다. reward.save는 그렇지 않다. getTotals가 <= 0.00이 될 만큼 충분한 포인트를 적용하고, Free Checkout을 선택한 다음, 포인트를 지운다. Confirm은 대기 중인 행을 카탈로그 가격으로 다시 쓴다. free_checkout.confirm은 세션 결제 코드만 확인한다.
리워드 포인트를 가진 로그인 고객이 카탈로그 SKU를 Free Checkout으로 배송받고 포인트는 그대로 유지할 수 있다.
| ID | 아직 CVE 없음 |
| CWE | CWE-840, CWE-863 |
| CVSS | High: 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| 제품 | OpenCart |
| 영향 범위 | 4.1.0.4까지 reward + Free Checkout |
| 인증 | 인증된 고객 (게스트 장바구니는 이 버그가 아님) |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1 전용 |
로그인하고, 포인트로 커버되는 SKU를 장바구니에 담고, Free Checkout이 목록에 나타날 만큼 충분한 리워드를 적용하고, 해당 결제 수단을 저장한 다음, reward.save를 0으로 호출한다. 두 번째 confirm이 카탈로그 총액을 기록한다. free_checkout.confirm이 주문을 결제 완료로 승격시킨다. 포인트는 절대 차감되지 않는다.
셸을 얻는 것은 아니다. 게스트 체크아웃은 이 버그가 아니다: reward는 고객이 필요하다. Free Checkout은 total <= 0일 때만 목록에 나타난다. 버그는 포인트를 지워도 목록에서 사라지지 않으며, confirm이 총액을 다시 확인하지 않는다는 점이다.
reward.save, 그다음 coupon.save, 그다음 getMethods (total <= 0.00), 그다음 status가 0인 상태의 editOrder, 그다음 free_checkout.confirm을 읽었다. 4.1.0.4에서 reward=0은 session.reward를 제거한다. payment_method는 건드리지 않는다. 15116 하드닝 이후의 쿠폰은 건드린다.
이것을 처음 보는 클라이언트는 100 포인트를 적용하고, Free Checkout을 선택하고, 한 번 confirm하여 정직한 0원 주문을 받게 된다. 그것은 기능이지 버그가 아니다.
이미 기록된 잘못된 방향들: reward.save 대신 coupon.save (그 경로는 결제 수단을 unset함); 게스트 체크아웃; points=0인 상품 (Free Checkout이 절대 목록에 나타나지 않음); free_checkout.confirm까지 세션에 reward를 남겨두기 (정직한 무료 주문, 포인트는 차감되어야 함); order_status_id=0만 보기 (pending은 결제된 것이 아님). 오라클은 status 1, total 100.00, payment free_checkout, debit 0이다.
랩: 고객 로그인. 장바구니에 36 추가 (iPod Nano, points=100). reward.save 100. 결제 수단 목록에 Free Checkout. 저장. Confirm이 주문 3을 0으로 기록. reward.save 0. Confirm이 주문 4를 100.00으로 다시 씀. free_checkout.confirm. 시드는 세금과 배송비를 제거하여 reward가 getTotals를 정확히 0으로 만들 수 있게 한다. 그것은 버그가 아니다. 포인트가 해당 라인을 커버하는 카탈로그 SKU가 현실적인 사례다. 고객은 여전히 1000을 가지고 있다.
cd lab
./run.sh
오직 http://127.0.0.1:18108만 대상으로 한다. 먼저 OpenCart 4.1.0.4 upload/를 lab/www에 배치한다. 그 트리는 이 저장소에 없다.
SUCCESS OpenCart reward + Free Checkout underpay
IOC order-after-reward 3 total=0.0000 status=0 free_checkout.free_checkout
IOC order-after-clear 4 total=100.0000 status=0 free_checkout.free_checkout
IOC free_checkout.confirm redirect checkout/success
IOC order-final 4 total=100.0000 status=1 debit=0 balance=1000
coupon.save가 이미 하는 것처럼 reward.save에서 payment_method를 unset하고, free_checkout.confirm이 total > 0을 거부하도록 만든다.
reward.php · coupon.php · free_checkout.php 컨트롤러 · free_checkout.php 모델 · confirm.phpGNU Affero GPL v3.0. LICENSE 참조. 루프백 랩 전용. 보증 없음.