一個人東京

看我如何得到iTaiwan帳號密碼

先說結論就是"不要使用公共Wifi"
以下實驗均為學術研究用途 如自行使用 後過自負

緣起

有一晚我窩在北門臥客的房內
電腦雖然收得到Wi-Fi卻無法上網
而且這個現象在大廳不會發生
打開WiFi掃描儀 看到四個相同SSID的訊號
而這個最強的訊號就是讓我沒辦法上網的原因
立馬回報這個問題給他們
最後協助他們修復了那台有問題的AP
還得到了一張免費住宿卷(結果被我放到過期

去年的AIS3 Mentor計畫要想題目
我就在我腦海把這個東西挖了出來
"相同SSID蓋台DoS攻擊的防禦"
這是一個連網裝置連線設計的feature
在出現相同SSID的情況下
裝置會選擇訊號最強的進行連線
不管裝置是否已經連線
想到的解決方法是記憶MAC
但攻擊者也可以偽造MAC
這個題目就被我擱置了

看到TDOH conf的徵稿
這個題目又被我挖出來了
把題目的重點改成釣魚
但Wifi釣魚其實行之有年
究竟能玩出什麼新花樣呢

要釣就要釣最大條的
"iTaiwan免費無線上網服務熱點數量在全台已逾8700處,註冊人數超過460萬人"
要使用iTaiwan要先註冊帳號密碼
帳號是使用者手機
密碼是使用者自訂
連上iTaiwan 會跳出登入視窗
這樣的機制稱之為Captive Portal

Captive Portal運作的原理大致如下
手機連上Wifi會測試網路的可用性
而不同OS有不同的測試路徑

Android: http://connectivitycheck.android.com/generate_204
Apple: http://captive.apple.com/hotspot-detect.html
Windows: http://www.msftconnecttest.com/connecttest.txt

根據這些測試連線的response status
手機就可以知道Captive Portal的存在
並且重新導向到登入的頁面
這東西太有意思了!
我開始研究了"Captive Portal 釣魚"(以下簡稱CP釣魚)

正文

CP釣魚有許多的優點
1. 信任的Wifi名稱,裝置會自動連線
2. 自動跳出登入視窗,降低使用者的懷疑
3. 獲取登入帳號密碼,手機也是很重要的個資,許多人帳號密碼在不同網站是重複的
4. 不用提供網路服務,劣質、低成本

要實作CP釣魚有幾個重點
1. 一個同名的Wifi熱點
2. 自動跳出登入畫面
3. 一個與原登入頁面相似的釣魚頁面
4. 將輸入的資料傳入到我的資料庫

而我使用的硬體設備有
1. RPi2
2. TL-WN722N(v2)

1. 一個同名的Wifi熱點

這個太簡單了 應該大家都做得到
打開手機熱點編輯一下熱點名稱就好了

我在RPi2使用hostapd這個套件來管理我的Wifi名稱
當然這個Wifi的SSID就是"iTaiwan"

2. 自動跳出登入畫面

在了解每個OS的Captive Portal機制
且大部分的裝置預設會採用分享器提供的DNS設定
我決定採用dnsmasq來做DNS hijacking
將所有的DNS請求都解析到我的裝置上
並且將每一個OS的測試連線對應到一個跳轉頁面
將這些請求都導向到我的釣魚登入頁面

3. 一個與原登入頁面相似的釣魚頁面

我使用HTTracker來將iTaiwan的登入頁面砍回來
再將登入的表單修改成傳入我的處理頁面

4. 將輸入的資料傳入到我的資料庫

最後我的處理頁面會將使用者的輸入儲存到資料庫中

5. 讓他看起來更像

利用剛剛的DNS hijacking
我讓他的網址與原本的iTaiwan一模一樣
並且每次都只會導引到失敗頁面
因為跳轉的太快 在fail.php sleep(3)
最後就變成了這樣
受害者以為登入失敗 還會嘗試其他組密碼呢XD

進階利用

以上的釣魚都是利用人心的弱點
接下來利用裝置才是重點!
在更改iTaiwan頁面的時候我注意到了一個功能
沒錯就是"記住我"
關鍵的程式碼如下
function cookie_check(login_form, key) {
    var frm=login_form;
    var remember=login_form.remember;
    var autologin=login_form.autologin;
    var autologin_set = getCookie("Autologin");
    var type;

    if( (type = getCookie("TYPE"))!== null) {
        if( type == "TPE") {
            login_form.type[1].checked = true;
        } else if( type == "NTPC") {
            login_form.type[0].checked = true;
            return;
        } else if( type == "TANet") {
            login_form.type[2].checked = true;
        } else if( type == "iTainan") {
            login_form.type[3].checked = true;
        } else {
            login_form.type[0].checked = true;
        }
    }

    if(getCookie("ID")!== null) {
        login_form.clt_user.value=Aes.Ctr.decrypt(getCookie("ID"),key,256);
        if(autologin_set == '1') {
            autologin.checked=true;
        } else {
            remember.checked=true;
        }
    }

    if(getCookie("Serial")!== null) {
        login_form.clt_pass.value=Aes.Ctr.decrypt(getCookie("Serial"),key,256);
    }

    if(getCookie("Autologin") == '1') {
        if(login_form.onsubmit()) {
            login_form.submit();
        }
    }
}

"記住我"使用了cookie來加密儲存使用者的帳號密碼
在我仔細研究後發現key的產生方式與裝置的MAC address有關
攻擊者可以利用真實網站送出不同的MAC address得到不同的key
一個Wifi熱點能輕鬆得到裝置的MAC address
而DNS hijacking後的網址的吻合性
也能輕鬆拿到瀏覽器內同網域下的Cookie
有了Cookie,有了MAC address,不用使用者互動拿到帳號密碼
簡單來說 只要手機曾經使用過"記住我"
連上釣魚Wifi跳出登入視窗 帳號密碼就送出了
而且不少裝置在關閉螢幕下也能跳出登入視窗
使用者根本無法察覺 因為這一切都是預設動作
DEMO影片(以下實驗均為學術研究用途)

後記

最後我把這個漏洞回報給HITCON ZeroDay
https://zeroday.hitcon.org/vulnerability/ZD-2017-00906
2017/10/19 提交漏洞
2017/10/21 審核通過
2017/12/07 修復完畢
2018/02/01 公開漏洞

修復的方式就是在cookie加上secure flag
讓沒有憑證的釣魚頁面無法存取cookie
但這樣的攻擊只是冰山一角
防禦CP釣魚最好的方法就是"不要使用公共Wifi"

留言