
إثبات مفهوم للاستغلال ومختبر لثغرة تجاوز الدفع في 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 عند تغيير الكوبون. 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 |
| Product | OpenCart |
| Affected | حتى 4.1.0.4 reward + Free Checkout |
| Auth | عميل مصادَق عليه (سلة الضيف ليست هذا الخطأ) |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 فقط |
سجّل الدخول، ضع SKU مغطّى بالنقاط في السلة، طبّق مكافأة كافية بحيث يُدرج Free Checkout، احفظ تلك الطريقة، ثم reward.save بقيمة 0. Confirm الثاني يكتب إجمالي الكتالوج. free_checkout.confirm يرقّي الطلب إلى مدفوع. النقاط لا تُخصم أبدًا.
لا يحصلون على shell. دفع الضيف ليس هذا الخطأ: المكافأة تحتاج عميلًا. Free Checkout يُدرج فقط عند total <= 0. الخطأ هو أن مسح النقاط لا يزيله من القائمة، و confirm لا ينظر إلى الإجمالي مرة أخرى.
قرأت reward.save، ثم coupon.save، ثم getMethods (total <= 0.00)، ثم editOrder بينما الحالة 0، ثم free_checkout.confirm. في 4.1.0.4، reward=0 يُسقط session.reward. لا يلمس payment_method. الكوبون بعد تحصين 15116 يفعل ذلك.
أول عميل ينظر إلى هذا سيطبّق 100 نقطة، يختار Free Checkout، يؤكد مرة واحدة، ويحصل على طلب صادق بإجمالي صفري. هذه هي الميزة، وليست الخطأ.
المنعطفات الخاطئة المسجّلة بالفعل: coupon.save بدلًا من reward.save (هذا المسار يلغي تعيين الطريقة)؛ دفع الضيف؛ منتج بـ points=0 (Free Checkout لا يُدرج أبدًا)؛ ترك reward في الجلسة عبر free_checkout.confirm (طلب مجاني صادق، يجب خصم النقاط)؛ النظر إلى order_status_id=0 فقط (المعلّق ليس مدفوعًا). المعيار هو 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. البذرة تُسقط الضريبة والشحن حتى تتمكن المكافأة من تصفير getTotals بدقة. هذا ليس الخطأ. 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
unset لـ payment_method في reward.save بالطريقة التي يفعلها coupon.save بالفعل، واجعل free_checkout.confirm يرفض total > 0.
reward.php · coupon.php · free_checkout.php controller · free_checkout.php model · confirm.phpGNU Affero GPL v3.0. انظر LICENSE. مختبر loopback فقط. لا ضمان.