本文轉載於:猿2048網站⇛【XSS】對抗蠕蟲 —— 如何讓按鈕不被 JS 自動點擊php
XSS 自動點按鈕有什麼危害?前端
在社交網絡裏,不少操做都是經過點擊按鈕發起的,例如發表留言。假如留言系統有 XSS,用戶中招後除了基本攻擊外,還能進行傳播 —— XSS 自動填入留言內容,並模擬點擊發表按鈕,因而就能發佈帶有惡意代碼的留言。好友看了中招後,又傳播給他們的好友。。。從而造成蠕蟲擴散。後端
那麼有沒有一種機制,讓「發表留言」必須經過用戶的「真實點擊」按鈕才能完成,而沒法經過腳本自動實現?這樣就能減緩蠕蟲傳播速度了。安全
這個想法聽起來好像不可行:若是發表留言須要帶上用戶行爲信息,那麼 XSS 徹底能夠僞造一份行爲數據,後端根本沒法識別。服務器
除非,用戶在點擊按鈕時會產生一個「特殊數據」,讓後端校驗它。網絡
可是,XSS 也能夠直接調用按鈕元素的 click 方法,這樣效果和用戶點擊仍然同樣。後端仍沒法識別是「腳本點的」仍是「用戶點的」。xss
這麼看來,咱們只能保護好這個「按鈕元素」,讓它無法被 XSS 訪問到。例如,把按鈕放到一個 不一樣源的 iframe 裏,這樣就和 XSS 所在的環境隔離了!post
不過,這樣還不夠。假如 XSS 破解了這個「特殊數據」的生成規則,那麼便可本身僞造一個,而後直接調用 HTTP 接口發表留言。因此,咱們得找一個不可僞造的硬標識。網站
事實上,有個很簡單的辦法:咱們乾脆讓 HTTP 請求也經過 iframe 發送。這樣,後端經過 referer 便可檢測請求是否爲 iframe 發起的。畢竟,XSS 是沒法僞造 referer 的!spa
Demo: https://www.etherdream.com/FunnyScript/anti-xssworm/
注意:這個案例不是看能不能注入 XSS,而是看能不能經過當前頁面的 JS 自動發留言!
另外,經過第三方服務器發表是不算的。這裏爲簡單,省略了登陸態;真實場合下,會話 Cookie 是 HttpOnly 的,沒法被 JS 獲取到,也就沒法讓第三方服務器代替發表。
細節:
使用者加載 safebutton.js
,引入 SafeButton
類
使用者實例化 SafeButton
對象 A,建立出一個不一樣源的 iframe 做爲按鈕界面
用戶點擊 iframe 按鈕後,內部變量 S 置爲 true,同時將點擊消息告知主頁面(postMessage)
主頁面收到消息後,讓 A 產生 onclick
事件
使用者將 HTTP 請求數據,經過 A 的 send
方法扔給 iframe
iframe 校驗內部變量 S:若爲 true,則將數據經過 AJAX 發送;不然放棄
服務器校驗 referer:若爲 iframe 的地址,則繼續業務邏輯;不然放棄
iframe 收到 AJAX 返回後,將結果扔給主頁面
A 產生 onreceive
事件,其中包含 HTTP 返回結果
其中 No.6 的步驟最爲關鍵。正是這一步,使得未經用戶點擊,XSS 強制扔給 iframe 的消息變得無效!
固然,這個方案阻擋不了點擊劫持 —— XSS 能夠把 iframe 元素放大至整個頁面,並設置全透明。
這樣用戶只要在頁面的任何位置點一下,iframe 的 S 狀態就變成 true 了,因而就能繞過 No.6。
固然,安全防護有勝於無。而且該方案的改形成本也不是很大,後端只是增長一個 referer 判斷而已;前端也只需改造個別按鈕,例如發帖按鈕,像點贊這種按鈕就不必保護了。