Một lỗ hổng, một câu chuyện riêng: #3

Một lỗ hổng, một câu chuyện riêng: #3

·

4 min read

Table of contents

No heading

No headings in the article.

Banner chỉ mang tính chất tấu hài, không cổ suý, ủng hộ hay cổ vũ các hành động phạm pháp dưới bất kỳ hình thức nào.


Sau một thời gian dài không múa phím, hôm nay mình quay lại với 1 bài Race condition từ rất lâu rồi, cụ thể là 2 năm cmnr. Race condition là gì thì mời anh em đọc Race conditions | Web Security Academy (portswigger.net) chứ mình lười giải thích lắm :(


Nói qua 1 chút về target lần này, đó là 1 ứng dụng của Việt Nam, kiểu sàn thương mại điện tử hay ứng dụng thông mink gì đó, idk ¯\_(ツ)_/¯. Mình làm vì đơn giản là vì mình thích mấy target kiểu vậy, dễ clear nghiệp vụ, gần gũi, thân thiện, bla bla ...

Trong lúc dạo chơi ứng dụng, mình có để ý đến 1 chức năng như này:

Đại loại là trong app có mục Voucher, được app phát miễn phí cho người dùng nhưng mỗi người chỉ được 1 số lượng voucher nhất định. Là một thằng trái khoáy, thích phá hơn làm, cấu kết gian thương, đẩy *** xuống biển, *** con ***, mình ngay lập tức muốn "break" cái gọi là "Nhận tối đa 30 voucher/khách hàng 🗣️🔥🔥" ¯\_(ツ)_/¯.

Mình nghĩ ngay đến lỗi Race condition, dù không chắc chắn lắm, tại thường thì cái lỗi này cũng chả tồn tại 1 cách lộ liễu như vậy, còn tại sao mình nghĩ đến Race condition á? Tại trước đó đọc và tìm hiểu chút éc thì mình biết được Race condition thường hay xảy ra ở các tính năng kiểu kiểu này thôi, không có gì to tát cả :^.

Ok, qua đoạn nghĩ rồi, giờ là lúc kiểm chứng giả thiết đặt ra. Khi người dùng click nút Nhận ngay, ứng dụng sẽ gửi 1 request có dạng

POST /evoucher/voucher/v1/voucher/10801/claim HTTP/2
Host: abc.xyz
X-Device-Request-Id: e6e9ffe6-5d33-41d0-8ff9-a52cc4b764ff
X-Device-Id: f987737b0058f518
X-Device-Session-Id: 43488cad-a03c-4e02-9c67-c8b5cb7685c7
User-Agent: vinid/134.0 Dalvik/2.1.0 (Linux; U; Android 7.1.2; SM-G965N Build/QP1A.190711.020)
X-Device-Version: 134.0
X-Device-Dv-Token: 
X-Device-Os-Token: A+lh1jeIq3Usk3ot7cJeEzrp7g/vJZLACHNxcbXxxbZM3e8I89gbz5pR9O980dH6NaHni01c7cLsO7Wlp1N/6Vts6v4XqkLNcGm99Z5Mgu+bCRKJEGVtk1RLXaThhEGfHanZpdMZs10RSx+BLEvXhuMy1hEM8Tdz3zyMLAOnCLkVNg9VwIPVUg67e4/aJqREUnqAmSlXzg2N0KZ4nX69bPyr5pf7WuCRYT/LgnlsLEspknLO5KrjgjNUOHzlBzW559FSgM+XNkFYHSt3JA0UrXdqFFa1UUAsEviR0j5tvxMer+b7NQfz1vwXfthZND8wLe8aXQltzOiYh5u0iWDfAw==
Authorization: Bearer <Token>
Content-Type: application/json; charset=UTF-8
Content-Length: 36
Accept-Encoding: gzip, deflate

{"quantity":1,"c":10801,"source":""}

Với trường quantity là số lượng, trường c là số thứ tự của voucher đấy.

Tại đây mình đã thử thay đổi quatity trước đó, và tất nhiên là không thành công :^), cơ bản quá mà.

Và đó là lúc mình quay sang test Race condition, phương pháp cũng không có gì hoa mĩ, mình chỉ đơn giản gửi 1 lượng lớn request với trường c có giá trị tăng dần (thực ra mình định múa múa tý, nhưng lúc đấy cũng muộn rồi nên đây là cách dễ nhất để kiểm chứng)

Sau khi chạy Intruder xong, mình cũng hơi bất ngờ tý vì đoán xem ai lấy được 31 cái voucher thay vì giới hạn 30 voucher/user nào

Sau khi bú được nhiều voucher hơn hạn mức, việc còn lại của mình chỉ là viết report thôi. Quá trình triage report diễn ra khá nhanh nhưng (Đúng vậy, luôn có nhưng) người anh em triager đã ý kiến lại với mình như này

Đại khái là ừ, mày lấy được nhiều voucher hơn mức quy định rồi đấy, nhưng còn sử dụng được nhiều hơn thì sao? Hay là lấy về để trưng thôi.

Và okokok, mình đã reproduce lại lỗ hổng, kèm thêm sử dụng nhiều hơn hạn mức quy định (ở đây là 30)

Đầu tiên là voucher mình sẽ sử dụng để reproduce, nó đây

Voucher này cho phép lấy max 10 cái/user

Sử dụng Race condition, mình lấy được 12 cái :^

Sau đấy là màn spam sử dụng cả 12 cái và mình không gặp cản trở nào trong quá trình đấy cả. API trong ảnh dưới cho phép search voucher đã sử dụng, ở đây tìm kiếm ra cả 12 cái voucher (đồng nghĩa với việc sử dụng thành công vượt hạn mức 10 cái/user)

Sau đấy thì không có sau đấy nữa, chỉ như này thôi :(


Đoạn này hết rượu, chưa biết viết như nào... Khi nào say mình viết tiếp, stay t u n e b r u h