CSRF漏洞詳解,一文看懂CSRF

更多關於代碼審計、WEB×××、網絡安全的運維的知識,請關注微信公衆號:發哥微課堂。

0x00:CSRF 簡述
CSRF(Cross Site Request Forgery,跨站請求僞造),字面理解意思就是在別的站點僞造了一個請求。專業術語來說就是在受害者訪問一個網站時,其 Cookie 還沒有過期的情況下,×××者僞造一個鏈接地址發送受害者並欺騙讓其點擊,從而形成 CSRF ×××。

0x01:CSRF 案例
受害者 (A) 登錄了某個銀行給朋友 (B) 轉賬,其轉賬操作發送的請求 URL 如下:

https://www.xxxx.com?account=A&money=10000&touser=B
account 代表受害者,money 是要轉賬的金額,touser 是被轉入的賬戶。發送這個鏈接請求後,A 給 B 轉賬的操作完成。這時×××者(C)僞造了一個鏈接,如下:

https://www.xxxx.com?account=A&money=10000&touser=C
這個鏈接的請求是 A 用戶給 C 用戶轉賬一萬元。當 A 沒有登錄不存在 Cookie 信息時,此鏈接是無法執行的。這時×××者通過一系列手段讓 A 執行此鏈接,當 A 登錄銀行沒有退出的時候,點擊此鏈接便會執行成功。

0x02:代碼示例
當程序對於類似此敏感信息操作提交時,沒有進行相應的防護,便會產生 CSRF ×××,例如一下代碼:

<form method="GET" action="/transferFunds">

轉賬金額:<input type="text" name="money">
轉入賬戶:<input type="text" name="touser">
<input type="submit" name="action" value="提交">

</form>
0x03:如何測試
在×××測試中,可以先看下網頁源代碼對於敏感信息提交有無防護措施,初步判斷是否存在 CSRF,隨後通過抓包確定提交的完整 URL 鏈接,並僞造另一個鏈接進行測試。
在代碼審計中,可以先查看網頁源代碼,是否有防護措施。隨後可查看 WEB 應用程序的配置文件中是否有相應的驗證措施,最後查看後臺的處理邏輯,對於發送過來的請求是否有過濾等措施。

0x04:防護方法
1,二次驗證,進行重要敏感操作時,要求用戶進行二次驗證。

2,驗證碼,進行重要敏感操作時,加入驗證碼。

3,驗證 HTTP 的 Referer 字段。

4,請求地址中添加 Token 並驗證。

5,HTTP 頭中自定義屬性並驗證。

0x05:防護代碼
1,對於二次驗證,可添加 JS,提交請求後詢問客戶是否提交,而不是直接發送請求給後臺。

<script>
function moneySub(){

    if(confirm('確認進行轉賬操作?')){
        renturn ture;
    }else{
        return false;
    }

}

</script>

<form method="GET" action="/transferFunds">

轉賬金額:<input type="text" name="money">
轉入賬戶:<input type="text" name="touser">
<input type="submit" name="action" value="提交">

</form>
2,對於驗證碼,進行轉賬時,可輸入圖形驗證碼,也可以添加手機接收驗證碼等功能。

<script>

var code;

window.onload=function createCode(){

code = "";  
var codeLength = 4;
var checkCode = document.getElementById("code");  
var random = new Array(0,1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R', 'S','T','U','V','W','X','Y','Z'); 

for(var i = 0; i < codeLength; i++) {

    var index = Math.floor(Math.random()*36);
    code += random[index];

}  

checkCode.value = code;

}

function validate(){

var inputCode = document.getElementById("yzm").value.toUpperCase();

if(inputCode.length <= 0) { 

    alert("請輸入驗證碼!");
    return false;

}else if(inputCode != code ) {

    alert("驗證碼輸入錯誤!");
    return false; 

}else {

    return true;

}

}

以上代碼,當驗證碼爲空時或錯誤時則無法提交請求。

3,對於驗證 HTTP Referer 字段,請求到後臺時,判斷下請求是否來自自己的站點,如果不是 Referer 的值不是以自己域名開頭,則會請求失敗。

String referer = request.getHeader("Referer");

if((referer!=null) && (referer.trim().startsWith("xxxx.com"))){

chain.doFilter(request,response);

}else{

request.getRequestDispatcher("error.jsp").forward(request,response);

}
以上代碼,使用 Java 的過濾器 Filter 來攔截請求,當獲取請求的 Referer 的值不爲空時並且是以自己站點的域名開頭時,則放行。否則跳轉到 error 頁面。

4,對於請求地址中添加 Token 驗證,也是用的最多的一個方法,在表單中添加一個 hidden 隱藏字段,發送請求時一起發送,並在服務器驗證 Token 的值。Token 的值越複雜,則安全性越高。

HttpServletRequest req = (HttpServletRequest)request;
HttpSession s = req.getSession();

String sToken = (String)s.getAttribute("token");

if(sToken == null){

//如果token爲空,則認爲首次訪問,生成新的token

sToken = generateToken();
s.setAttribute("token",sToken);
chain.doFilter(request,response);

}else{

String token = req.getParameter("token");

//不是第一次訪問,如果token和服務器的相同,則放行
if(sToken != null && sToken.equals(token)){

    chain.doFilter(request,response);

}else{

    request.getRequestDispatcher("error.jsp").forward(request,response);

}

}
對於代碼中的 generateToken 生成 token 的方法,可以使用 Java 的 UUID,代碼如下:

for(int i=0;i<10;i++){
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
}
5,對於 HTTP 頭部自定義屬性驗證,和 token 機制類似。只不過是把 token 從表單放到了請求的頭重,如下代碼:

var plainXhr = dojo.xhr;

dojo.xhr = function(method,args,hasBody) { // 重寫 dojo.xhr 方法

args.headers = args.header || {};     // 確保 header 對象存在

tokenValue = '<%=request.getSession(false).getAttribute("token")%>'; 
var token = dojo.getObject("tokenValue"); 

args.headers["token"] = (token) ? token : "  ";     //把token 屬性放到頭中
return plainXhr(method,args,hasBody); 

}
dojo.xhr 是用 JS 寫的一個工具包,重寫其中的方法,把從 session 中獲取的 token 值放到新添加的頭部字段中,然後發送給後臺。

0x06:CSRF 總結
對於 CSRF 其危害性比較大,不易防護,建議在開發過程中結合以上的多條防護措施進行防護,不建議只用某一點或某一條,多層防護更有利於系統的安全。

更多關於代碼審計、WEB×××、網絡安全的運維的知識,請關注微信公衆號:發哥微課堂。

CSRF漏洞詳解,一文看懂CSRF

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章