
Proof-of-Concept-Exploit und Lab für einen OpenCart 4.1.0.4 Reward-Points- plus Free-Checkout-Zahlungsumgehung, mit der ein authentifizierter Kunde Punkte behalten und Bestellungen unterbezahlen kann.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · opencart-reward-free-checkout
OpenCart 4.1.0.4 - OpenCart Ltd
CVE-2025-15116 war ein Coupon-Race bis 4.1.0.3. In 4.1.0.4 entfernt coupon.save payment_method, wenn sich der Coupon ändert. reward.save tut das nicht. Wende genügend Punkte an, sodass getTotals <= 0.00 ist, wähle Free Checkout und lösche dann die Punkte. Confirm schreibt die ausstehende Zeile auf den Katalogpreis um. free_checkout.confirm prüft nur den Zahlungscode der Session.
Ein angemeldeter Kunde mit Bonuspunkten kann eine Katalog-SKU als Free Checkout versenden und die Punkte behalten.
| ID | noch keine 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 |
| Produkt | OpenCart |
| Betroffen | bis 4.1.0.4 reward + Free Checkout |
| Auth | authentifizierter Kunde (Gast-Warenkorb ist nicht dieser Bug) |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1 |
Anmelden, eine durch Punkte abgedeckte SKU in den Warenkorb legen, genügend Reward anwenden, sodass Free Checkout gelistet wird, diese Methode speichern, dann reward.save mit 0. Das zweite Confirm schreibt den Katalog-Gesamtbetrag. free_checkout.confirm stuft die Bestellung auf bezahlt hoch. Punkte werden nie abgebucht.
Sie bekommen keine Shell. Gast-Checkout ist nicht dieser Bug: Reward benötigt einen Kunden. Free Checkout wird nur bei total <= 0 gelistet. Der Bug ist, dass das Löschen der Punkte es nicht entlistet und Confirm den Gesamtbetrag nicht erneut prüft.
Ich habe reward.save gelesen, dann coupon.save, dann getMethods (total <= 0.00), dann editOrder während der Status 0 ist, dann free_checkout.confirm. In 4.1.0.4 entfernt reward=0 session.reward. Es berührt payment_method nicht. Coupon nach der 15116-Härtung tut das.
Der erste Client, der sich das ansieht, wird 100 Punkte anwenden, Free Checkout wählen, einmal bestätigen und eine ehrliche Bestellung mit Null-Gesamtbetrag erhalten. Das ist das Feature, nicht der Bug.
Bereits festgehaltene Irrwege: coupon.save statt reward.save (dieser Pfad entfernt die Methode); Gast-Checkout; Produkt mit points=0 (Free Checkout wird nie gelistet); reward in der Session durch free_checkout.confirm belassen (ehrliche kostenlose Bestellung, Punkte sollten abgebucht werden); nur auf order_status_id=0 schauen (ausstehend ist nicht bezahlt). Das Orakel ist Status 1, total 100.00, payment free_checkout, debit 0.
Lab: Kunden-Login. Warenkorb 36 hinzufügen (iPod Nano, points=100). reward.save 100. Zahlungsmethoden listen Free Checkout. Speichern. Confirm schreibt Bestellung 3 bei 0. reward.save 0. Confirm schreibt Bestellung 4 bei 100.00 um. free_checkout.confirm. Seed entfernt Steuer und Versand, damit Reward getTotals exakt auf null bringen kann. Das ist nicht der Bug. Eine Katalog-SKU, deren Punkte die Position abdecken, ist der realistische Fall. Der Kunde hat immer noch die 1000.
cd lab
./run.sh
Ziel nur http://127.0.0.1:18108. Platziere OpenCart 4.1.0.4 upload/ zuerst unter lab/www. Dieser Baum ist nicht in diesem Repo.
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
unset payment_method in reward.save so, wie coupon.save es bereits tut, und free_checkout.confirm dazu bringen, total > 0 abzulehnen.
reward.php · coupon.php · free_checkout.php controller · free_checkout.php model · confirm.phpGNU Affero GPL v3.0. Siehe LICENSE. Nur Loopback-Lab. Keine Gewährleistung.