# Portswigger Business Logic Vulnerabilities 😎 <style>body {text-align: justify}</style> Hi, dưới đây là writeup của 11/11 bài lab về lỗ hổng [Business Logic Vulnerabilities](https://portswigger.net/web-security/logic-flaws) mình đã solve trong quá trình ôn tập thi chứng chỉ của Portswigger. ### 1. Excessive trust in client-side controls ##### Description > 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". > > You can log in to your own account using the following credentials: `wiener:peter` ##### Writeup Đây là ứng dụng web bán sản phẩm tồn tại lỗi logic cho phép người dùng chỉnh giá sản phẩm khi mua một cách tùy ý. Sau khi đăng nhập bằng tài khoản `wiener:peter`, account có `100$` để mua sắm. Tuy nhiên, để mua `Lightweight l33t leather jacket`, tài khoản cần có ít nhất `1337$`. ![](https://i.imgur.com/dTHdErg.png) Thử add sản phẩm trên vào giỏ hàng. ![](https://i.imgur.com/0PQIb1Z.png) Bắt gói tin POST đến đường dẫn `/cart`, ta thấy ngoài các thông tin về productId, ... thì có tham số price, chính là giá tiền sản phẩm. ![](https://i.imgur.com/CNDtcDR.png) Nếu như để `price=133700` tức là `1337$`, ta sẽ không đủ tiền để mua. ![](https://i.imgur.com/evs0BZX.png) Tuy nhiên, thử chỉnh `price=1`, tức là lúc này sản phẩm chỉ có giá `0.01$`. ![](https://i.imgur.com/rH4JsZy.png) Kiểm tra đơn hàng thấy giá của sản phẩm đã bị chỉnh còn `0.01$`. Lúc này ta có thể mua được sản phẩm. ![](https://i.imgur.com/pwnkISq.png) Thực hiện thanh toán và ta solve được challenge. ![](https://i.imgur.com/Nus0Uhk.png) ### 2. High-level logic vulnerability ##### Description > 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". > > You can log in to your own account using the following credentials: `wiener:peter` ##### Writeup Đây là ứng dụng web bán sản phẩm tồn tại lỗi logic cho phép người dùng chỉnh số lượng sản phẩm về số âm khi mua một cách tùy ý. Cụ thể, bài lab này sẽ tấn công trên tham số `quantity`. Khi nhập `quantity=-1` thì giá tiền cần thanh toán trở thành số âm. ![](https://i.imgur.com/ZO0Ctry.png) Tuy nhiên, khi thanh toán thì có thông báo tổng giá tiền không thể là số âm. ![](https://i.imgur.com/Hh9XIal.png) Do đó, để mua 1 chiếc `"Lightweight l33t leather jacket"` có giá `1337$`, ta cần mua 1 sản phẩm khác với số âm sản phẩm để khi đó, tổng giá tiền của nó sẽ cộng với `1337$` bằng tổng giá tiền đơn hàng nằm trong khoảng từ `0$-100$`. ![](https://i.imgur.com/P4bi0BS.png) Ở đây mình đã chọn mua sản phẩm thứ 2 với số lượng `-20` và 1 sản phẩm `"Lightweight l33t leather jacket"`. Tổng giá tiền lúc này là `50.8$`, hoàn toàn thanh toán được. ![](https://i.imgur.com/kHk4QHR.png) Thanh toán hóa đơn và ta solve được challenge. ![](https://i.imgur.com/hNPbUhN.png) ### 3. Inconsistent security controls ##### Description > This lab's flawed logic allows arbitrary users to access administrative functionality that should only be available to company employees. To solve the lab, access the admin panel and delete Carlos. ##### Writeup Bài lab cho phép chức năng của `administrator` chỉ cung cấp cho nhân viên công ty `DontWannaCry`. ![](https://i.imgur.com/udAU6p2.png) Những nhân viên đó sẽ có email với đuôi là `@dontwannacry.com`. Vì ta không có đuôi email này nên phải đăng kí với email được cấp như hình dưới. ![](https://i.imgur.com/WoKbqLR.png) Một link xác thực đăng kí được gửi về mail. Click vào link để vào trang thông tin cá nhân. ![](https://i.imgur.com/55ySj9u.png) Để ý trang thông tin cá nhân lại có chức năng cập nhật email. Lúc này mình có thể cập nhật email bất kì có đuôi `@dontwannacry.com`. Sau khi cập nhật, lúc này user này đã có chức năng admin tại `Admin panel`. ![](https://i.imgur.com/xJr2cZQ.png) Truy cập chức năng admin và xóa user `carlos`, ta đã solve được challenge. ![](https://i.imgur.com/V4J4YED.png) ### 4. Flawed enforcement of business rules ##### Description > 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` ##### Writeup Bài lab bị lỗi logic tại chức năng dùng coupon khi không check kĩ trường hợp submit coupon nhiều lần. Cụ thể, ta sẽ có 2 couponn như sau: - Một coupon `NEWCUST5` cho khách hàng mới, khi mua sẽ được giảm `5$` ![](https://i.imgur.com/QlllyMu.png) - Một coupon `SIGNUP30` khi sign up để nhận thông tin. Khi mua sản phẩm có coupon này, hóa đơn sẽ được giảm `30%`. ![](https://i.imgur.com/v8zN60Z.png) ![](https://i.imgur.com/Ou2rnID.png) Thực hiện mua sản phẩm `"Lightweight l33t leather jacket"`. Khi dùng coupon `NEWCUST5` thì sẽ được giảm `5$`. Nếu apply coupon này 2 lần liên tiếp sẽ bị báo `Coupon already applied`. ![](https://i.imgur.com/LmXWBhS.png) Tuy nhiên, nếu apply thêm coupon `SIGNUP30` rồi apply lại `NEWCUST5` thì lại thành công. Điều này chứng tỏ số lần apply coupon liên tiếp sẽ bị reset khi apply coupon khác thành công. ![](https://i.imgur.com/0p247xR.png) Dựa vào đó, ta sẽ apply 2 coupon trên một cách xen kẽ cho đến khi tổng hóa đơn có giá trị nằm trong khoảng `0$-100$`. ![](https://i.imgur.com/MPjeV6n.png) Thực hiện thanh toán và ta solve được challenge. ![](https://i.imgur.com/inhypWb.png) ### 5. Low-level logic flaw ##### Description > 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". > > You can log in to your own account using the following credentials: `wiener:peter` ##### Writeup Ứng dụng web này bị dính lỗi Integer Overflow tại tổng giá tiền hóa đơn. Tương tự các bài trên, ta chỉ control được tham số `quantity`. Nhập thử số âm thì thành công nhưng server reset nó về 0 trước khi render. ![](https://i.imgur.com/Kpqvl8B.png) Nếu như ta nhập `quantity > 99`, thì sẽ bị báo `Invalid paramter: quantity`. ![](https://i.imgur.com/KNVyrLL.png) Chứng tỏ tối đa ta sẽ mua được 99 sản phẩm trong 1 lần mua. Như đã nói ứng dụng bị dính Integer Overflow, cụ thể khi ta mua quá nhiều sản phẩm dẫn đến tổng hóa đơn sẽ tràn từ `2147483647` sang `-2147483648` và tiến về `0`. Ta gửi vô số request để tổng hóa đơn tràn sang số âm. ![](https://i.imgur.com/qxgI0du.png) Gửi request với null payload. ![](https://i.imgur.com/rGOoljs.png) Lúc này kiểm tra đã thấy tổng tiền hóa đơn đã là số âm. ![](https://i.imgur.com/5MZlbdH.png) Vì ta mua `"Lightweight l33t leather jacket"` có giá `1337$` 1 lần `99` cái nên ta cần tính toán sao cho tổng hóa đơn sẽ là số âm bé lớn nhất có thể. Cụ thể đó là `-64060` sau 325 request. ![](https://i.imgur.com/ISOOpch.png) Và vì `64060 / 1337 = 47` nên ta sẽ mua thêm 1 lần 47 sản phẩm nữa. Không thể là 48 sản phẩm vì khi đó tổng tiền nó sẽ là số dương > `100$` tài khoản có. ![](https://i.imgur.com/uXu1y8I.png) Lúc này ta sẽ mua sản phẩm khác có giá tiền bé hơn với số lượng lớn sao cho 0$ &le; tổng tiền &le; 100$. ![](https://i.imgur.com/YA9ar4s.png) Ở đây e mua thêm 50 sản phẩm thứ 2, khi đó tổng tiền là `18.54$`. Lúc này ta đã thanh toán được hóa đơn. ![](https://i.imgur.com/4iS98Ef.png) Thanh toán thành công và ta solve được challenge. ![](https://i.imgur.com/mq6xyxb.png) ### 6. Inconsistent handling of exceptional input ##### Description > 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. ##### Writeup Bài lab này tương tự với bài số 3. Điểm khác là không còn chức năng update email nữa. Thay vào đó, tận dụng các server xử lý email khi render để tấn công. Cụ thể, nếu ta đăng kí tài khoản với email dài như sau ![](https://i.imgur.com/NVmMCLN.png) thì ứng dụng đã cắt và chỉ lấy 255 kí tự đầu. ![](https://i.imgur.com/sApY7s5.png) Mặt khác vì email được cấp có thể nhận được tất cả các mail kể cả các subdomain nên ta sẽ nảy ra ý tưởng chèn `dontwannacry.com.` vào domain của email đăng kí và kết hợp với các kí tự khác sao cho khi server lấy 255 kí tự đầu thì kết quả sẽ là `<...>@dontwannacry.com`. ![](https://i.imgur.com/6mrNjnC.png) Cụ thể, email sẽ được đăng kí là: `'a'*238+'@dontwannacry.com.'+'exploit-<LABID>.exploit-server.net'`. ![](https://i.imgur.com/0rQt2b9.png) Lúc này, email đã được server xử lý và cắt thành `aaaa...aaa@dontwannacry.com`. Lúc này ta đã có thể dùng được chức năng của admin. ![](https://i.imgur.com/DkIS8d0.png) Sử dụng admin và xóa user `carlos`, ta solve được challenge. ![](https://i.imgur.com/4WdZQiO.png) ### 7. Weak isolation on dual-use endpoint ##### Description > 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. > > You can log in to your own account using the following credentials: `wiener:peter` ##### Writeup Sau khi đăng nhập, tại trang `/my-account` có chức năng đổi password cho user. ![](https://i.imgur.com/6XU4AG5.png) Thử cập nhật password mới thành công. Có 4 trường cần điền thông tin: - `username`: user cần đổi mật khẩu, mặc định sẽ là user hiện tại và không thay đổi được trên front-end. - `current-password`: mật khẩu hiện tại - `new-password-1`: mật khẩu mới - `new-password-2`: confirm mật khẩu mới ![](https://i.imgur.com/OStU2Se.png) Tuy nhiên, khi mình thử xóa luôn tham số `current-password` thì vẫn cập nhật thành công. ![](https://i.imgur.com/jW03MdS.png) Như vậy, bằng cách thay đổi `username`, ta có thể thay đổi password của bất kì user nào mà không cần biết password hiện tại của họ. Ta sẽ thay đổi password `administrator` thành `1112`. ![](https://i.imgur.com/ZlaRCQ9.png) Đăng nhập bằng tài khoản`administrator:1112`, ta sẽ vào được tài khoản admin. Thực hiện xóa user `carlos`, ta solve được challenge. ![](https://i.imgur.com/hpsj5sa.png) ### 8. Insufficient workflow validation ##### Description > 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". > > You can log in to your own account using the following credentials: `wiener:peter` ##### Writeup Khi ta mua một sản phẩm thành công, tồn tại 2 request như sau: - POST `/cart/checkout`: request thanh toán - GET `/cart/order-confirmation?order-confirmed=true`: request confirm các sản phẩm đã mua. ![](https://i.imgur.com/WjWa7hR.png) ![](https://i.imgur.com/hCInGU7.png) Tuy nhiên, ứng dụng bị dính lỗi logic khi có thể mua sản phẩm không mất tiền bằng cách gửi luôn request GET `/cart/order-confirmation?order-confirmed=true` và bỏ request `POST /cart/checkout`. ![](https://i.imgur.com/VpjlmMk.png) Lúc này ta mua được sản phẩm `"Lightweight l33t leather jacket"` và solve được challenge. ![](https://i.imgur.com/gSHXGSr.png) ### 9. Authentication bypass via flawed state machine ##### Description > 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. > > You can log in to your own account using the following credentials: `wiener:peter` ##### Writeup Sau khi đăng nhập, ứng dụng sẽ cho chọn role là `User` hoặc `Content author`. ![](https://i.imgur.com/jOUB7xd.png) ![](https://i.imgur.com/wWNEHl0.png) Tuy nhiên, nếu sau khi đăng nhập, mình bỏ bước chọn role này bằng cách drop luôn gói tin `GET /role-selector` ![](https://i.imgur.com/yuNZxGg.png) thì mặc định lúc này, user mình vừa đăng nhập sẽ trở thành `administrator`. ![](https://i.imgur.com/ZBtouvb.png) Sử dụng chức năng xóa user `carlos` của admin, ta solve được challenge. ![](https://i.imgur.com/290exen.png) ### 10. Infinite money logic flaw ##### Description > 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` ##### Writeup Bài lab tồn tại lỗi logic tại chức năng hoàn tiền bằng gift card code. ![](https://i.imgur.com/MNiWDhY.png) Cụ thể, khi mua sản phẩm `Gift Card` với giá `10$`, ta sẽ nhận được 1 gift code. Khi sử dụng code này, ta sẽ được hoàn lại `10$`. ![](https://i.imgur.com/XtoJ12K.png) Tuy nhiên, ứng dụng này còn có 1 coupon SIGNUP30 khi sign up email để nhận thông tin. ![](https://i.imgur.com/P6a0HQ3.png) ![](https://i.imgur.com/mVKrPZe.png) Khi sử dụng coupon trên thì đơn hàng sẽ được giảm 30%. Như vậy, với gift card `10$`, ta sẽ được giảm `3$` và chỉ cần trả `7$`. ![](https://i.imgur.com/C0QgUjq.png) Và khi sử dụng mã gift code mua được, thì ta lại được hoàn `10$`. Điều này chứng tỏ ta đã lời được `3$`. ![](https://i.imgur.com/MMIUgBx.png) Như vậy chỉ cần thực hiện mua gift card và apply mã code vô số lần, tài khoản của mình sẽ được cộng tiền một cách vô hạn. Ta sẽ sử dụng Intruder để gửi vô số request kèm theo 1 macro. Macro sẽ thực hiện các request lần lượt như sau: ``` POST /cart - Thêm gift card vào giỏ hàng POST /cart/coupon - Apply mã coupon SIGNUP30 POST /cart/checkout - Thanh toán GET /cart/order-confirmation?order-confirmed=true - Đây là bước confirm đơn hàng sau khi mua POST /gift-card - Thực hiện submit gift code để được hoàn tiền ``` ![](https://i.imgur.com/KhUvWwv.png) Cứ một macro được thực hiện xong thì ta sẽ được cộng thêm `3$`. Chú ý, tại request số 4, ta cần trích xuất mã `gift-card` vừa mua để truyền sang request số 5 để submit. ![](https://i.imgur.com/wxhvDOD.png) Tại request số 5, cấu hình lấy giá trị `gift-card` từ request số 4 để tiến hành submit. ![](https://i.imgur.com/QBvwkeW.png) Ta test thử và thấy macro đã hoạt động đúng theo ý tưởng. ![](https://i.imgur.com/yuSVR7z.png) Bây giờ mình cần mua `"Lightweight l33t leather jacket"` có giá `1337$`. Ta đã có sẵn `100$` và một lần macro thực thi thì được cộng `3$`. Do đó, ta cần gửi 413 request với macro trên do `(1337 - 100) / 3 = 412 (dư 1)`. Nên nhớ phải set chỉ có tối đa 1 request được gửi tại 1 thời điểm với Intruder. ![](https://i.imgur.com/XQDqFJ1.png) Đợi bruteforce xong, kiểm tra ta thấy lúc này mình đã có nhiều hơn `1337$`. ![](https://i.imgur.com/0vcmULk.png) Thanh toán sản phẩm và ta solve được challenge. ![](https://i.imgur.com/jq4Wl0z.png) ### 11. Authentication bypass via encryption oracle ##### Description > 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` ##### Writeup Tại chức năng login, ứng dụng web có sử dụng `stay logged in` để lưu cookie người dùng. ![](https://i.imgur.com/bgTkqBq.png) Một cookie `stay-logged-in` dạng base64 được thêm vào request. Tuy nhiên, khi decode thì dường như nó đã bị mã hóa trước. ![](https://i.imgur.com/a6vqjyT.png) Mặt khác, tại mỗi bài post có chức năng comment. Và khi ta để lại một email `a123` không hợp lệ như dưới: ![](https://i.imgur.com/fgZeGhc.png) Thì ứng dụng thông báo một dòng `Invalid email address: a123` và kèm theo một cookie `nofitication` dạng base64. Decode ra thì thấy nó cũng bị mã hóa. Ta có thể suy luận rằng: - Nội dung của notification chính là base64 của chuỗi `Invalid email address: a123` sau khi bị mã hóa - Và thuật toán mã hóa dùng cho `nofitication` giống với `stay-logged-in`. ![](https://i.imgur.com/TaN6V8j.png) Ta sẽ kiểm chứng bằng cách lấy giá trị của `stay-logged-in` để đưa vào `nofitication`. ![](https://i.imgur.com/9I2Rf8g.png) Kết quả cho thấy nội dung của `stay-logged-in` chính là `username:timestamp`. ![](https://i.imgur.com/1PbMpsk.png) Bây giờ, ta cần tạo một giá trị `stay-logged-in` cho `administrator` dựa vào cách mã hóa của trường `notification`. Và vì `notification` được tạo thông qua trường `email` nên ta sẽ truyền payload tại `email`. Ta sẽ truyền `administrator:<timestamp>` tại email. ![](https://i.imgur.com/RRnkBER.png) Có thể thấy thông báo `Invalid email address: administrator:1672593998338` với `notification` là dạng base64 mã hóa của nó. ![](https://i.imgur.com/us2wJTJ.png) Tuy nhiên mình cần xóa `Invalid email address: `(23 bytes) đi để `notification` chỉ chứa base64 giá trị mã hóa của `administrator:1672593998338`. Để làm được điều đó, lấy giá trị `notification` hiện tại, thực hiện decode URL+base64 và xóa 23 bytes đầu đi. ![](https://i.imgur.com/xgjoxXz.png) Sau khi xóa 23 bytes trên, thực hiện encode base64 + URL encode để truyền vào cookie `notification` xem đã cắt thành công chưa: `O3tEa1GHAnSumMNJYUyeNZmLguHpQlzLaC+N7hZEpoujFylp6tXe1Fc%3d`. Kết quả thông báo ciphertext trong `notification` phải là bội số 16. Mình có thể đoán thuật toán mã hóa mỗi block 16 bytes. ![](https://i.imgur.com/cZYdukB.png) Như vậy mình cần chèn thêm 9 bytes bất kì vào trước để kết hợp với 23 bytes trên thành 32 bytes cần xóa. ![](https://i.imgur.com/uJNLMTd.png) Làm tương tự ở trên, ta được mã base64 và chèn vào `notification` xem: `djB3rOXek/kH8c/b/tl4Ps595LA64fFl0wYvIfx%2bYHc%3d`. ![](https://i.imgur.com/cc2UT2m.png) Kết quả có thể thấy ta đã xóa `Invalid email address: ` thành công. Lúc này giá trị tại `notification` chính là `URLencode(base64encode('administrator:<timestamp>'))` - cái chúng ta cần để hèn vào cookie `stay-logged-in`. ![](https://i.imgur.com/vuNLoeW.png) Thực hiện request đến `/admin` với cookie `stay-logged-in` có giá trị mới trên. ![](https://i.imgur.com/mscNNhk.png) Ta đã vào được account của `administrator` thành công và xóa user `carlos` để solve challenge. ![](https://i.imgur.com/Edvus8t.png) ###### tags: `portswigger`, `logic-flaws`