1. 程式人生 > >web安全之跨站請求偽造

web安全之跨站請求偽造

CSRF(Cross-site request forgery),中文名稱:跨站請求偽造.
因為這個不是使用者真正想發出的請求,這就是所謂的請求偽造;因為這些請求也是可以從第三方網站提交的,所以字首跨站二字。

CSRF發生的場景如下圖所示:

使用者登入訪問了一個受信任的站點,
在使用者還沒有退出登入的時候,開啟另外一個tab頁,訪問了網站B。
在B網站中,有CSRF攻擊程式碼訪問網站A。
發生的原因是,網站是通過cookie來識別使用者的,當用戶成功進行身份驗證之後瀏覽器就會得到一個
標識其身份的cookie,只要不關閉瀏覽器或者退出登入,以後訪問這個網站會帶上這個cookie。
1.登入受信任網站A,並在本地生成Cookie。
2.在不登出A的情況下,訪問危險網站B。
你也許會說:“如果我不滿足以上兩個條件中的一個,我就不會受到CSRF的攻擊”。
是的,確實如此,但你不能保證以下情況不會發生:
1.你不能保證你登入了一個網站後,不再開啟一個tab頁面並訪問另外的網站。
2.你不能保證你關閉瀏覽器了後,你本地的Cookie立刻過期,你上次的會話已經結束。
(事實上,關閉瀏覽器不能結束一個會話,但大多數人都會錯誤的認為關閉瀏覽器就等於
退出登入/結束會話了)如記住密碼功能等。
3.上圖中所謂的攻擊網站,可能是一個存在其他漏洞的可信任的經常被人訪問的網站。
下面來看一個程式碼例項,在網站A釋出了下面的程式碼
使用者login,然後可以在input.jsp提交資料,提交的資料被dataupdate.jsp更新到後臺。
dataupdate.jsp會檢查使用者是否登入,如果沒有登入會跳到login.jsp要求使用者登入。

  1. login.jsp  
  2. <body>
  3. <formaction="input.jsp"method="post">
  4. name<inputtype="text"name="name"size="50"><br>
  5. pwd<inputtype="password"name="password"size="50"><br>
  6. <inputtype="submit"value="submit">
  7. </form>
  8. <br>
  9. </body>
  10. </html>
  11. input.jsp  
  12. <
    body>
  13. <%  
  14.     //Session session = request.getSession();  
  15.     String username = (String)session.getValue("username");  
  16.     System.out.println("username " + username);  
  17.     if(null==username){  
  18.         String uname = request.getParameter("name");  
  19.         session.putValue("username", uname);  
  20.     }  
  21. %>
  22. <formaction="dataupdate.jsp"method="post">
  23. <inputtype="text"name="comment"size="50"><br>
  24. <inputtype="submit"value="submit">
  25. </form>
  26. <br>
  27. </body>
  28. dataupdate.jsp  
  29. <body>
  30. <%  
  31.     String username = (String)session.getValue("username");  
  32.     System.out.println("username " + username);  
  33.     if(null==username){  
  34.         System.out.println("has not logged in");  
  35.         response.sendRedirect("login.jsp");  
  36.     }else{  
  37.         String comment = request.getParameter("comment");  
  38.         System.out.println("add a comment: " + comment);  
  39.         out.write("comment is : " + comment);  
  40.     }  
  41. %>
  42. </body>
  43. </html>
表面上看起來好像沒有問題。
假設我們有另外一個網站B,它有一個網頁檔案如下
如果在使用者登入訪問網站A的同時訪問了網站B,訪問者在網站A的資料就會被假冒更新。
可以在後臺看到有如下的輸出:add a comment: fromcsrf
  1. <body>
  2. use a img element to send a get request <br>
  3. <imgsrc="http://www.a.com/prjWebSec/csrf/dataupdate.jsp?comment=fromcsrf">
  4. </body>
  5. </html>
這裡網站A違反了HTTP規範,使用GET請求更新資源。那是不是用post請求就不會發生CSRF呢?
結果是同樣會發生。可以通過構造javascript構造form提交,如下面的程式碼
  1. <body>
  2. </body>
  3.     <scripttype="text/javascript">
  4.         var frmdocument.getElementById("viframe");  
  5.         function sendcsrf()    
  6.         {    
  7.             var form1 = document.createElement("form");    
  8.             form1.id = "form1";    
  9.             form1.name = "form1";    
  10.             document.body.appendChild(form1);    
  11.             var input = document.createElement("input");    
  12.             input.type = "text";    
  13.             input.name = "comment";    
  14.             input.value = "from csrf post";    
  15.             form1.appendChild(input);    
  16.             form1.method = "POST";    
  17.             form1.action = "http://www.a.com/prjWebSec/csrf/dataupdate.jsp";    
  18.             form1.submit();    
  19.             document.body.removeChild(form1);    
  20.         }   
  21.         sendcsrf();  
  22.     </script>
  23. </html>
防止方法:
1,利用referer判斷,
但是使用者有可能設定瀏覽器使其在傳送請求時不提供 Referer,這樣的使用者也將不能訪問網站。
2,在請求中新增 token 並驗證
關鍵在於在請求中放入黑客所不能偽造的資訊,並且該資訊不存在於 cookie 之中,

可以在伺服器端生成一個隨機碼,然後放在form的hidden元素中,form提交的時候在伺服器端檢查。

轉自:http://blog.csdn.net/kkdelta/article/details/17503947