iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 19
1
Software Development

Go Phishing!30 天用 Go 實作 Reverse Proxy 之釣魚大作戰系列 第 19

Day19-發 issue II(實作篇)

今日目標

昨天發現不能發 issue 是因為有一個 cookie 是 __Host- 開頭的,那個 cookie 一定要 secure 屬性才會被瀏覽器存起來,今天就是要解決這個問題

解決方案

針對這個問題,筆者我想到三種解決方法:

  • 不管他,反正之後架在線上也會支援 HTTPS

    這大概是最簡單的解決方法 XD,其實這個釣魚網站已經幾乎做好了,只要之後部署到線上有 HTTPS 就沒問題了,但是在 localhost 的開發版就會沒辦法測試

  • 在 localhost 使用 HTTPS

    目前在 local 開發的網站沒有 HTTPS 導致沒辦法設定 secure cookie,那弄個 HTTPS 就好了嘛,但因為在 localhost 架設 HTTPS 有點麻煩,雖然有 mkcert 之類的工具可以用,但還是要設定一堆有的沒的

  • 幫 cookie 改名

    這是我最後選的方法,既然是因為名字是 __Host- 開頭才有這問題,其他名字的 cookie 都沒問題,那就幫 cookie 改個名吧!

幫 cookie 改名

幫 cookie 改名分成兩個步驟:

1. Github Set-Cookie 給瀏覽器

首先是 Github 要 Set-Cookie 給瀏覽器時(下圖 3、4 步),把 __Host-user-session 改成 XXHost-user-session 再給瀏覽器,這樣就不會因為是 __Host- 開頭而 set 不進去

2. 瀏覽器發出 cookie

瀏覽器傳出去的 cookie 也要改一下(1、2 步),因為存在瀏覽器內的 cookie 叫做 XXHost-user-session,不可能原封不動傳給 Github,所以幫他改回原本的名字 __Host-user-session 再給 Github

對瀏覽器來說他只需要收發叫做 XXHost-user-session 的 cookie,而對 Github 來說他也要收發 __Host-user-session,中間的 reverse proxy 會自動進行轉換,這樣一來 cookie 就可以成功 set 到瀏覽器內,Github 也不會發現 cookie 有被改過名~

實作

1. Github Set-Cookie 給瀏覽器(上圖 3、4 步)

除了先前在 Day13 中把 cookie 的 domainsecure 拿掉之外,現在多了兩行把 __Host 改成 XXHost__Secure 改成 XXSecure,改完再把 Set-Cookie 傳給瀏覽器

func handler(w http.ResponseWriter, r *http.Request) {
    // ...

    for _, v := range header["Set-Cookie"] {
        newValue := strings.Replace(v, "domain=.github.com;", "", -1)
        newValue = strings.Replace(newValue, "secure;", "", 1)

        // 幫 cookie 改名
        // __Host-user-session -> XXHost-user-session
        // __Secure-cookie-name -> XXSecure-cookie-name
        newValue = strings.Replace(newValue, "__Host", "XXHost", -1)
        newValue = strings.Replace(newValue, "__Secure", "XXSecure", -1)

        w.Header().Add("Set-Cookie", newValue)
    }

    // ...
}

2. 瀏覽器發出 cookie(上圖 1、2 步)

cloneReqest 內複製請求時就反過來,把 XXHost 改回 __HostXXSecure 改回 __Secure,這樣 Github 就還是會收到 __Host-user-session,也不知道我們有改過

func cloneRequest(r *http.Request) *http.Request {
    // ...

    req := http.NewRequest(method, url, body)
    req.Header = r.Header

    for i, value := range req.Header["Cookie"] {
        // 取代 cookie 名字
        newValue := strings.Replace(value, "XXHost", "__Host", -1)
        newValue = strings.Replace(newValue, "XXSecure", "__Secure", -1)
        req.Header["Cookie"][i] = newValue
    }

    return req
}

實測

之後登入瀏覽器果然拿到了一個叫做 XXHost-user-session 的 cookie,而且因為不是 __Host- 開頭了所以有成功存到瀏覽器內,也可以成功發 issue 了,一切都很完美


小結

這是今天的 commit,到目前為止已經成功 完美模仿 Github

如果在 localhost 跑起來應該全部的功能都可以用,包刮登入、新增 repo 等等,就跟 Demo 一模一樣,不看網址用起來根本就是真正的 Github,如果有什麼不能用的麻煩留言跟我說,我會馬上開始研究然後把那個功能做完 XD

大家還記得這一系列的標題「Go Phishing!30 天用 Go 實作 Reverse Proxy 之釣魚大作戰」嗎,現在模仿 Github 已經告一段落了,接下來的內容會講怎麼把釣到的魚收集起來,有問題的話歡迎在底下留言,沒問題的話就敬請期待後面的內容囉


上一篇
Day18-發 issue I(觀察篇)
下一篇
Day20-Go modules
系列文
Go Phishing!30 天用 Go 實作 Reverse Proxy 之釣魚大作戰30

尚未有邦友留言

立即登入留言