admin管理员组文章数量:1404923
I recently discovered a serious security issue in Django e-commerce websites where users can modify product prices before adding items to the cart.
Many developers allow users to send price data from the frontend, which can be easily tampered with using Burp Suite or browser developer tools.
Example of the Issue:
Consider a simple Django view that adds items to the cart:
def add_item(request):
product_id = request.GET.get('product_id')
price = request.GET.get('price') # User-controlled value (security risk)
qty = int(request.GET.get('qty', 1))
cart_item = {
'product_id': product_id,
'qty': qty,
'price': price, # This price comes from the user, not the database!
}
request.session['cart'] = request.session.get('cart', {})
request.session['cart'][product_id] = cart_item
request.session.modified = True
return JsonResponse({'message': 'Added to cart'})
How an Attacker Can Exploit This:
- A product costs $500 in the database.
- The user clicks "Add to Cart".
- Instead of sending the original price, the attacker intercepts the request using Burp Suite.
- The
price
field is changed to $1, and the request is forwarded. - The cart now stores the manipulated price, and the user can proceed to checkout with the wrong amount.
Why Is This a Security Risk?
- The backend trusts data from the frontend, which can be easily manipulated.
- The session stores the wrong price, leading to financial loss.
- Attackers can buy expensive products at extremely low prices by modifying request data.
Discussion Points for the Community:
- What are the best practices to prevent this?
- Should e-commerce sites always fetch prices from the database instead of accepting them from the frontend?
- What other vulnerabilities should developers be aware of when handling cart data in Django?
Would love to hear your thoughts on this!
I recently discovered a serious security issue in Django e-commerce websites where users can modify product prices before adding items to the cart.
Many developers allow users to send price data from the frontend, which can be easily tampered with using Burp Suite or browser developer tools.
Example of the Issue:
Consider a simple Django view that adds items to the cart:
def add_item(request):
product_id = request.GET.get('product_id')
price = request.GET.get('price') # User-controlled value (security risk)
qty = int(request.GET.get('qty', 1))
cart_item = {
'product_id': product_id,
'qty': qty,
'price': price, # This price comes from the user, not the database!
}
request.session['cart'] = request.session.get('cart', {})
request.session['cart'][product_id] = cart_item
request.session.modified = True
return JsonResponse({'message': 'Added to cart'})
How an Attacker Can Exploit This:
- A product costs $500 in the database.
- The user clicks "Add to Cart".
- Instead of sending the original price, the attacker intercepts the request using Burp Suite.
- The
price
field is changed to $1, and the request is forwarded. - The cart now stores the manipulated price, and the user can proceed to checkout with the wrong amount.
Why Is This a Security Risk?
- The backend trusts data from the frontend, which can be easily manipulated.
- The session stores the wrong price, leading to financial loss.
- Attackers can buy expensive products at extremely low prices by modifying request data.
Discussion Points for the Community:
- What are the best practices to prevent this?
- Should e-commerce sites always fetch prices from the database instead of accepting them from the frontend?
- What other vulnerabilities should developers be aware of when handling cart data in Django?
Share Improve this question edited Mar 31 at 14:14 Google User asked Mar 9 at 6:19 Google UserGoogle User 1751 silver badge8 bronze badges 2Would love to hear your thoughts on this!
- 1 Yeah I've seen that "e-commerce project" frequently. I however did not know people really used this, since aside from the security vulnerability, the project had a lot performance issues, bad code design, and so on. – willeM_ Van Onsem Commented Mar 9 at 6:25
- 1 See for example here and here. Unfortunately there are a lot of youtube videos where you "learn" Django, but the host often themself is not very skilled in Django, or takes shortcuts not meant in a production setting. – willeM_ Van Onsem Commented Mar 9 at 6:30
2 Answers
Reset to default 2What are the best practices to prevent this?
You don't need the price, the view should add the product_id
to the cart, and perhaps a quantity
, but adding something to the cart has no price involved. It even makes it more complicated to later apply discounts, since the price is determined per product.
Should e-commerce sites always fetch prices from the database instead of accepting them from the frontend?
Not per se, there are some APIs that determine prices on-the-fly. Bots that thus drive up the price if there is more demand, or if a competitor drops their prices.
What other vulnerabilities should developers be aware of when handling cart data in Django?
This has nothing to do with a cart, you always ask the user the absolute minimum you need to know, and by design thus limit the parameters, since this limits what you can tamper with.
I've seen some questions on StackOverflow with a similar approach. Sometimes they define a class Cart
that then operates on the session data. But this was indeed bad design, and often not only in terms of this security vulnerability, but performance, referential integrity, etc.: you add an item to a cart with a GET request, which makes no sense; and you can even add a non-existing product as well.
The GET request thus means that if a person making the request hits refresh, it is made a second time. But more importantly, GET requests should be cacheable, which clearly is not the case, and it also puts the product_id
(and price
) in the URL, which means it is at least visible in the path as well, which is not good practice either.
I always got the impression some person gave a "Django eCommerce tutorial" on Youtube, and people copied some code. But apparently some indeed moved this to production.
To properly handle cart functionality and prevent users from tampering with prices, it's essential to store cart data securely in the database rather than relying on user input.
Cart Table
This table tracks user carts, whether they are associated with an authenticated user or an anonymous session.
id
(Primary Key)user
(ForeignKey toUser
, nullable for guest users)session
(ForeignKey toSession
, nullable for authenticated users)created_at
(Timestamp for when the cart was created)is_available
(Boolean to mark active/inactive carts)
Products Table
This stores product details, including price, which must always be retrieved from the database.
id
(Primary Key)name
(Product name)price
(Positive Integer for price storage)category
(ForeignKey to a separate Category table for better normalization)
CartItems Table
This table associates products with a cart and ensures price integrity.
id
(Primary Key)cart
(ForeignKey toCart
, linking items to a cart)product
(ForeignKey toProduct
, ensuring price consistency)quantity
(To track the number of items)
here is the sample code:
from django.db import models from django.contrib.sessions.models
import Session from django.contrib.auth.models
import User
class Cart(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
session = models.ForeignKey(Session, on_delete=models.CASCADE, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
is_available = models.BooleanField(default=True)
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.PositiveIntegerField()
category = models.CharField(max_length=255) # Ideally, this should be a separate table
class CartItem(models.Model):
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=1)
Notes:
In the Cart table, both session and user are nullable to support both guest and authenticated carts.
It's best to create a separate Category table and reference it with a foreign key for better database normalization.
After designing a robust database structure, the only step required is to send the product ID to the backend. The backend will then add the item to the user's or session's cart, creating a new cart if one doesn't already exist.
本文标签:
版权声明:本文标题:python - How can users modify cart prices using Burp Suite, and why is this a security risk in Django? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744876603a2629949.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论