Pricing Exploits
Pricing Exploits at a glance
Overview
Pricing exploits manipulate the pricing logic of e-commerce and subscription applications to obtain goods or services for less than their intended cost, or even for free. These attacks target business rules around pricing, discounts, currency conversion, and payment validation.
Common vulnerabilities include trusting client-provided prices, accepting negative quantities or prices, missing validation of discount code eligibility, inadequate validation of currency or unit conversions, and failing to recalculate totals server-side. Attackers exploit these by manipulating HTTP parameters, replaying discount codes, or exploiting rounding errors.
Where it occurs
Pricing exploits occur in payment or checkout logic that trusts client input, lacks server-side validation, mishandles discounts or currency conversions, or allows invalid price calculations.
Impact
Pricing exploits cause direct revenue loss through underpriced sales, inventory depletion from free items, discount code fraud, chargebacks from customers discovering underpriced competitors, and business disruption from exploits at scale.
Prevention
Prevent this by recalculating all prices server-side from trusted data, rejecting client-supplied totals, validating numeric ranges and discounts, using atomic counters and decimal math, auditing all calculations, and monitoring for pricing anomalies.
Examples
Switch tabs to view language/framework variants.
Checkout accepts negative quantities for store credit
E-commerce cart allows negative item quantities, enabling attackers to receive payments instead of making them.
# Vulnerable: No validation on quantity
from django.http import JsonResponse
from decimal import Decimal
import stripe
def checkout(request):
cart_items = request.POST.get('items', [])
total = Decimal('0')
for item in cart_items:
product = Product.objects.get(id=item['product_id'])
quantity = int(item['quantity']) # No validation!
# Vulnerable: Negative quantity allowed
item_total = product.price * quantity
total += item_total
# Create Stripe charge
charge = stripe.Charge.create(
amount=int(total * 100), # Can be negative!
currency='usd',
source=request.POST['stripe_token']
)
return JsonResponse({'success': True, 'total': float(total)})- Line 10:
- Line 13:
Negative quantities allowed, enabling reverse charges.
# Secure: Validate all business logic inputs
from django.http import JsonResponse
from decimal import Decimal
import stripe
def checkout(request):
cart_items = request.POST.get('items', [])
# Validate cart before processing
if len(cart_items) > 100:
return JsonResponse({'error': 'Too many items'}, status=400)
total = Decimal('0')
for item in cart_items:
product = Product.objects.get(id=item['product_id'])
quantity = int(item['quantity'])
# Validate quantity is positive and reasonable
if quantity <= 0:
return JsonResponse(
{'error': f'Invalid quantity for {product.name}'},
status=400
)
if quantity > 1000:
return JsonResponse(
{'error': 'Quantity exceeds maximum'},
status=400
)
item_total = product.price * quantity
total += item_total
# Ensure total is positive
if total <= 0:
return JsonResponse({'error': 'Invalid total'}, status=400)
# Additional sanity checks
if total > Decimal('100000'):
return JsonResponse(
{'error': 'Order exceeds maximum'},
status=400
)
# Create Stripe charge with validated amount
charge = stripe.Charge.create(
amount=int(total * 100),
currency='usd',
source=request.POST['stripe_token'],
metadata={'order_id': order.id}
)
return JsonResponse({'success': True, 'total': float(total)})- Line 16:
- Line 33:
Validates all inputs: quantity > 0, total > 0, reasonable maximums.
Engineer Checklist
-
Recalculate all prices server-side from product catalog
-
Never trust client-provided prices, quantities, or totals
-
Validate all numeric inputs are within valid ranges
-
Reject negative quantities or prices
-
Validate discount codes server-side (eligibility, expiration, limits)
-
Use atomic operations for limited-use discount tracking
-
Validate currency conversions server-side
-
Use decimal arithmetic for monetary calculations
-
Implement comprehensive audit logging
-
Monitor for unusual pricing patterns
-
Test with negative values, zero, and edge cases
-
Add CSRF protection to checkout forms
-
Implement idempotency for order submissions
End-to-End Example
An e-commerce site trusts client-provided prices during checkout, allowing attackers to purchase items at arbitrary prices.
# Vulnerable: Trusts client price
@app.route('/checkout', methods=['POST'])
def checkout():
items = request.json['items']
# Vulnerable: Uses client-provided price!
total = sum(item['price'] * item['quantity'] for item in items)
order = create_order(items, total)
process_payment(total)
return jsonify({'order_id': order.id})# Secure: Server-side price validation
from decimal import Decimal
@app.route('/checkout', methods=['POST'])
def checkout():
items = request.json['items']
# Recalculate from authoritative source
validated_items = []
total = Decimal('0')
for item in items:
# Get actual price from database
product = Product.query.get(item['product_id'])
if not product:
return "Invalid product", 400
quantity = Decimal(str(item['quantity']))
# Validate quantity
if quantity <= 0 or quantity > 1000:
return "Invalid quantity", 400
# Use server-side price
item_total = product.price * quantity
total += item_total
validated_items.append({
'product_id': product.id,
'price': product.price,
'quantity': quantity,
'subtotal': item_total
})
# Validate discount if provided
discount = Decimal('0')
if 'discount_code' in request.json:
discount_obj = validate_discount_code(
request.json['discount_code'],
user_id=current_user.id,
total=total
)
if discount_obj:
discount = discount_obj.calculate_discount(total)
discount_obj.mark_used()
final_total = total - discount
# Create order with validated data
order = create_order(
user_id=current_user.id,
items=validated_items,
subtotal=total,
discount=discount,
total=final_total
)
# Log for audit
log_order_created(order, validated_items, discount)
process_payment(final_total)
return jsonify({'order_id': order.id, 'total': str(final_total)})Discovery
Intercept checkout requests and modify price, quantity, or discount parameters. Test with negative values and extreme numbers.
-
1. Test price parameter manipulation
httpAction
Intercept checkout request and modify price values
Request
POST https://app.example.com/checkoutBody:"{'items': [{'id': 123, 'price': 0.01, 'quantity': 1}]}"Response
Status: 200Body:{ "note": "Order processes at manipulated price instead of catalog price" }Artifacts
manipulated_price price_acceptance -
2. Test negative quantity exploit
httpAction
Submit negative quantities to test for credit/refund
Request
POST https://app.example.com/cart/addBody:"{'product_id': 123, 'quantity': -10}"Response
Status: 200Body:{ "note": "Negative quantity accepted, creating credit in account" }Artifacts
negative_quantity account_credit -
3. Test discount code abuse
httpAction
Attempt to reuse expired or single-use discount codes
Request
POST https://app.example.com/apply-couponBody:"{'code': 'EXPIRED50', 'order_id': 456}"Response
Status: 200Body:{ "note": "Expired or exhausted discount code still applies" }Artifacts
discount_reuse code_bypass
Exploit steps
Attacker manipulates client-side price parameters, applies expired or invalid discount codes, or uses negative quantities to credit their account.
-
1. Purchase items at manipulated prices
Zero-dollar checkout
httpAction
Modify price to $0.01 and purchase high-value items
Request
POST https://app.example.com/checkoutBody:"{'items': [{'product_id': 999, 'price': 0.01, 'quantity': 100}]}"Response
Status: 200Body:{ "note": "$10,000 worth of items purchased for $1" }Artifacts
fraudulent_order revenue_loss inventory_depletion -
2. Exploit negative quantities for credits
Generate account credits
httpAction
Use negative quantities to add credits to account balance
Request
POST https://app.example.com/order/createBody:"{'items': [{'id': 123, 'quantity': -100, 'price': 50}]}"Response
Status: 200Body:{ "note": "$5,000 credit added to attacker's account" }Artifacts
account_credit_fraud financial_manipulation -
3. Stack and reuse discount codes
Unlimited discount abuse
httpAction
Apply multiple or expired discount codes to same order
Request
POST https://app.example.com/checkoutBody:"{'coupons': ['SAVE50', 'SAVE50', 'EXPIRED20'], 'items': [...]}"Response
Status: 200Body:{ "note": "120% discount applied, resulting in negative total or free items" }Artifacts
discount_stacking free_merchandise
Specific Impact
Direct financial loss from items sold below cost, fraud at scale causing significant revenue impact, and inventory depletion.
Fix
Always fetch prices from the authoritative product catalog server-side. Validate all quantities and numeric inputs. Use Decimal arithmetic for money. Validate discount codes with eligibility and usage checks. Implement comprehensive audit logging.
Detect This Vulnerability in Your Code
Sourcery automatically identifies pricing exploits vulnerabilities and many other security issues in your codebase.
Scan Your Code for Free