
Preuve de concept d'exploit et labo pour un contournement de paiement via les points de fidélité et Free Checkout dans OpenCart 4.1.0.4, permettant à un client authentifié de conserver ses points et de sous-payer ses commandes.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · opencart-reward-free-checkout
OpenCart 4.1.0.4 - OpenCart Ltd
CVE-2025-15116 était une course de coupons jusqu'à la version 4.1.0.3. Sur la 4.1.0.4, coupon.save supprime payment_method lorsque le coupon change. reward.save ne le fait pas. Appliquez suffisamment de points pour que getTotals soit <= 0.00, choisissez Free Checkout, puis effacez les points. La confirmation réécrit la ligne en attente au prix catalogue. free_checkout.confirm ne vérifie que le code de paiement de la session.
Un client connecté disposant de points de fidélité peut expédier un SKU du catalogue en Free Checkout et conserver les points.
| ID | pas encore de CVE |
| CWE | CWE-840, CWE-863 |
| CVSS | Élevé : 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| Produit | OpenCart |
| Affecté | jusqu'à 4.1.0.4 reward + Free Checkout |
| Auth | client authentifié (le panier invité n'est pas ce bug) |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Se connecter, mettre dans le panier un SKU couvert par des points, appliquer suffisamment de récompenses pour que Free Checkout apparaisse, enregistrer cette méthode, puis reward.save avec 0. La seconde confirmation écrit le total catalogue. free_checkout.confirm promeut la commande en payée. Les points ne sont jamais débités.
Ils n'obtiennent pas de shell. Le paiement invité n'est pas ce bug : reward nécessite un client. Free Checkout ne s'affiche que lorsque total <= 0. Le bug est que l'effacement des points ne le retire pas de la liste, et que la confirmation ne regarde plus le total.
J'ai lu reward.save, puis coupon.save, puis getMethods (total <= 0.00), puis editOrder tant que le statut est 0, puis free_checkout.confirm. Sur la 4.1.0.4, reward=0 supprime session.reward. Cela ne touche pas payment_method. Le coupon, après le durcissement de la 15116, le fait.
Le premier client qui regarde cela appliquera 100 points, choisira Free Checkout, confirmera une fois, et obtiendra une commande honnête à total zéro. C'est la fonctionnalité, pas le bug.
Fausses pistes déjà consignées : coupon.save au lieu de reward.save (ce chemin supprime la méthode) ; le paiement invité ; un produit avec points=0 (Free Checkout ne s'affiche jamais) ; laisser reward dans la session pendant free_checkout.confirm (commande gratuite honnête, les points devraient être débités) ; ne regarder que order_status_id=0 (en attente n'est pas payé). L'oracle est statut 1, total 100.00, paiement free_checkout, débit 0.
Lab : connexion client. Ajout au panier 36 (iPod Nano, points=100). reward.save 100. La liste des méthodes de paiement affiche Free Checkout. L'enregistrer. La confirmation écrit la commande 3 à 0. reward.save 0. La confirmation réécrit la commande 4 à 100.00. free_checkout.confirm. Le seed supprime la taxe et la livraison pour que reward puisse mettre getTotals à zéro exactement. Ce n'est pas le bug. Un SKU du catalogue dont les points couvrent la ligne est le cas réaliste. Le client a toujours les 1000.
cd lab
./run.sh
Cible uniquement http://127.0.0.1:18108. Placez d'abord OpenCart 4.1.0.4 upload/ dans lab/www. Cette arborescence n'est pas dans ce dépôt.
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 dans reward.save comme le fait déjà coupon.save, et faire en sorte que free_checkout.confirm refuse total > 0.
reward.php · coupon.php · free_checkout.php controller · free_checkout.php model · confirm.phpGNU Affero GPL v3.0. Voir LICENSE. Lab en boucle locale uniquement. Aucune garantie.