APP檢測GSM偽基站方案探索
GSM偽基站如果用于釣魚,危害就會很大。所以我就有一個想法,希望在APP層面檢測偽基站。因為偽基站隱蔽且容易流動,如果不在手機端檢測偽基站就不能及時發現異常。
雖然APP與偽基站對抗不在一個層級,但一定可以在APP層找到破綻——畢竟,偽基站要做到100%模擬正常基站難度也是很大的。比如通過OpenBTS、GNURadio和USRP實現的偽基站,默認都有好多獨有特性。


這就有點類似在應用層檢測系統的rootkit,雖然困難,但也并非完全不可能。我記得有一個簡易的檢測辦法,本地看系統開放了哪些端口,然后遠程掃描開放端口,兩個數據不一致,那就是有rootkit了。
可見,100%的虛擬現實是非常困難的。那么回到這個場景,偽基站的破綻在哪里?
嘗試
第一步很容易想到從OS層面能拿到的基站信息入手,看看獲得的信息能否有效甄別假基站。
Android SDK里面提供了類android.telephony.gsm.GsmCellLocation來獲取基站信息,可以得到Cid、Lac、Psc、hashCode,不過這些信息都很容易隨意偽造,看來得換個思路。
接下來我們又想到,在偽基站里電話和短信是不通的。雖然偽基站可以實現劫持,但是我目前見過的網上公開案例來看,偽基站都沒有做這個事。撥打電話這個操作太重,我們就在APP層發短信。如果網絡信息變化后,短信不能正常發出就說明可能存在偽基站。
發短信會涉及到費用,感覺不是很靠譜。不過我們想到給運營商號碼發是免費的,比如移動就給10086,聯通就給10001,電信的2G不是GSM,就先不管了。
于是,我們設想的方法是一旦發現基站信息發生變化,APP就發送一條短信給運營商,運營商收到后會答復,我們就看一定時間內是否有固定的回復內容,如無就認為當前接入的是偽基站。
不過后來考慮到收發短信權限太敏感,同時Android4.4及以后版本對APP的短信權限做了更嚴格地控制,所以這個方案我們也放棄了。
最后我們聚焦到網絡上。APP一旦發現基站信息發生變化,就調用GPRS獲取IP,如果得不到IP,就認為是偽基站——當然偽基站也可以搞個DHCP分配IP,如果發生對抗,我們還可以繼續從IP的范圍、網關IP等信息再來深入對抗。
demo演示
老規矩,在Android上實現了一個demo,以下是測試效果圖。后面這個demo會放到騰訊安全應急響應中心官網“實驗室”欄目,歡迎大家關注。

一些想法
這個方法還沒有考慮周全。比如漫游到境外的情況;還有,目前見到的偽基站都是發了短信后迅速將用戶踢出網絡,用戶則會重新回到正常網絡,整個過程只有短短幾分鐘,所以實際檢測效果還待測試。
如果有安裝量大的手機終端軟件,倒可以把手機附近的基站信息都上報到云端,如果偽基站出現,或許就可以及時發現。
后記
仍然感謝其他小伙伴popey、HuangJacky和riusksk的工作。
最后,一個有意思的想法是,如果這個“現實”世界是在一個“虛擬機”里運行的,你能從“應用層”找到破綻嗎?