轉:防止跨站攻擊,安全過濾

轉:http://blog.csdn.net/zpf0918/article/details/43952511

Spring MVC防御CSRF、XSS和SQL注入攻擊

本文說一下SpringMVC如何防御CSRF(Cross-site request forgery跨站請求偽造)和XSS(Cross site script跨站腳本攻擊)。

說說CSRF

對CSRF來說,其實Spring3.1、ASP.NET MVC3、Rails、Django等都已經支持自動在涉及POST的地方添加Token(包括FORM表單和AJAX POST等),似乎是一個tag的事情,但如果了解一些實現原理,手工來處理,也是有好處的。因為其實很多人做web開發,但涉及到web安全方面的都是比較資深的開發人員,很多人安全意識非常薄弱,CSRF是什么根本沒有聽說過。所以對他們來說,CSRF已經是比較高深的東西了。先說說什么是CSRF?你這可以這么理解CSRF攻擊攻擊者盜用了你的身份,以你的名義發送惡意請求。CSRF能夠做的事情包括:以你名義發送郵件,發消息,盜取你的賬號,甚至于購買商品,虛擬貨幣轉賬......造成的問題包括:個人隱私泄露以及財產安全。CSRF一般都是利用你的已登錄已驗證的身份來發送惡意請求。比較著名的一個例子就是2009年黑客利用Gmail的一個CSRF漏洞成功獲取好萊塢明星Vanessa Hudgens的獨家艷照。其攻擊過程非常簡單,給該明星的gmail賬戶發了一封email,標題是某大導演邀請你來看看這個電影,里面有個圖片:<img src="https://mail.google.com/mail?ui=2&fw=true&fwe=hacker@email.com">,結果她登錄Gmail,打開郵件就默默無聞的中招了,所有郵件被轉發到黑客的賬號。因為當時Gmail設置轉發的設置頁面有漏洞,其設置方法是打開一個窗口,點擊確定后實際URL是https://mail.google.com/mail?ui=2&fw=true&fwe=newMail@email.com:


?

其實即使不是在同一個頁面打開,在不同的tab打開也是一樣可以通過網站登錄驗證的,因為受害者首先已經登錄了網站,在瀏覽網站的過程中,若網站設置了Session cookie,那么在瀏覽器進程的生命周期內,即使瀏覽器同一個窗口打開了新的tab頁面,Session cookie也都是有效的,他們在瀏覽器同一個窗口的多個tab頁面里面是共享的(注:現在Gmail支持多個tab同時持有多個SessionID)。所以攻擊步驟是,第一,受害者必須在同一瀏覽器窗口(即使不是同一tab)內訪問并登陸目標站點;第二,這使得Session cookie有效,從而利用受害者的身份進行惡意操作。

再舉個實際的例子,假設我們界面上有刪除某一項的鏈接,例如:<a href="javascript:void(0)" οnclick="region_del.do?name=0000001">Delete</a>;

其Java Spring MVC后臺有個函數是刪除某個item,注意是GET不是POST:

復制代碼
@RequestMapping(value?=?"region_del.do",?method?=?RequestMethod.GET)
public?String?regionDel(@RequestParam?String?name,?Locale?locale)
{
????//Delete?region?name=@name....
????????
????return?"redirect:/region.html";
}
復制代碼

點擊界面上那個<a href="javascript:void(0)" οnclick="region_del.do?name=0000001">Delete</a>鏈接,就后臺刪除某項,看起來非常正常啊。

好,現在你登錄你的網站,然后在另外一個tab打開這個html文件:

復制代碼
<!DOCTYPE?html?PUBLIC?"-//W3C//DTD?XHTML?1.0?Transitional//EN"?"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html?xmlns="http://www.w3.org/1999/xhtml"?xml:lang="en"?lang="en">
<head>
????<meta?http-equiv="Content-Type"?content="text/html;?charset=utf-8"?/>
????<title>hack</title>
</head>
<body>
??<img?src="http://localhost/testsite/region_del.do?name=0000001"/>
?</body>
</html>
復制代碼

發現同樣被刪除了某項。試想,如果是網銀,你的錢已經被轉賬......(除了referer不一樣,session cookie被利用)

?

好了,現在 后臺改成POST(寫操作盡量用POST),前臺界面那個刪除的鏈接改成Form提交:

<form?action="region_del.do"?method="POST">
?<input?type="hidden"?name="name"?value="0000001">
????????<input?type="submit"?value="Delete"?/>
</form>

看起來安全多了。OK,現在你登錄你的網站,然后在另外一個tab打開這個html文件:

復制代碼
<!DOCTYPE?html?PUBLIC?"-//W3C//DTD?XHTML?1.0?Transitional//EN"?"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html?xmlns="http://www.w3.org/1999/xhtml"?xml:lang="en"?lang="en">
<head>
????<title>Hack</title>
????<script>
??????function?steal(){
????????var?mySubmit?=?document.getElementById('steal_form');
????????mySubmit.submit();
??????}
????</script>
??</head>
??<body?οnlοad='steal()'>
<form?id?=?"steal_form"?method="POST"?action="http://localhost/testsite/region_del.do">
???<input?type="hidden"?name="func"?value="post">
<input?type="hidden"?name="name"?value="0000001">
</form>
??</body>
</html>
復制代碼

?

發現同樣被刪除了某項。試想,如果是網銀,你的錢已經被轉賬......
當然,你如果前臺還是用鏈接,但改成js,用AJAX POST提交,也是一樣的效果:

?

$.ajax({
?type:?"POST",
?url:....
});

解決辦法就是在Form表單加一個hidden field,里面是服務端生成的足夠隨機數的一個Token,使得黑客猜不到也無法仿照Token

先寫一個類,生成足夠隨機數的Token(注:Java的Random UUID已經足夠隨機了,參考這個和這個)

復制代碼
package?com.ibm.cn.web.beans;

import?java.util.UUID;

import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpSession;

/**
*?A?manager?for?the?CSRF?token?for?a?given?session.?The?{@link?#getTokenForSession(HttpSession)}?should?used?to
*?obtain?the?token?value?for?the?current?session?(and?this?should?be?the?only?way?to?obtain?the?token?value).
*?***/

public?final?class?CSRFTokenManager?{

????/**
?????*?The?token?parameter?name
?????*/
????static?final?String?CSRF_PARAM_NAME?=?"CSRFToken";

????/**
?????*?The?location?on?the?session?which?stores?the?token
?????*/
????public?static?final??String?CSRF_TOKEN_FOR_SESSION_ATTR_NAME?=?CSRFTokenManager.class
????????????.getName()?+?".tokenval";

????public?static?String?getTokenForSession(HttpSession?session)?{
????????String?token?=?null;
????????
????????//?I?cannot?allow?more?than?one?token?on?a?session?-?in?the?case?of?two
????????//?requests?trying?to
????????//?init?the?token?concurrently
????????synchronized?(session)?{
????????????token?=?(String)?session
????????????????????.getAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME);
????????????if?(null?==?token)?{
????????????????token?=?UUID.randomUUID().toString();
????????????????session.setAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME,?token);
????????????}
????????}
????????return?token;
????}

????/**
?????*?Extracts?the?token?value?from?the?session
?????*?
?????*?@param?request
?????*?@return
?????*/
????public?static?String?getTokenFromRequest(HttpServletRequest?request)?{
????????return?request.getParameter(CSRF_PARAM_NAME);
????}

????private?CSRFTokenManager()?{
????};

}
復制代碼

打開Form頁面的時候在服務端生成Token并保存到Session中,例如:model.addAttribute("csrf", CSRFTokenManager.getTokenForSession(this.session));

然后在Form中添加Hidden field:?

<input type="hidden" name="CSRFToken" value="${csrf}" />

然后在后臺提交的時候驗證token :

?

復制代碼
@RequestMapping(value?=?"region_del.do",?method?=?RequestMethod.GET)
public?String?regionDel(@RequestParam?String?name,?@RequestParam?String?CSRFToken,?Locale?locale)
????{
????????if(CSRFToken?==?null?||?!CSRFToken.equals(session.getAttribute(CSRFTokenManager.CSRF_TOKEN_FOR_SESSION_ATTR_NAME).toString())){
????????????????logger.debug("CSRF?attack?detected.?URL:?region_edit.do");
????????????????return?"redirect:/login.form";
????????}?
????????????????
????//Delete?region?name=@name....
????????
????return?"redirect:/region.html";
}
復制代碼

?

你還可以把上面的步驟寫到BaseController里面,或者寫到攔截器里面,攔截所有POST請求,驗證CSRF Token。這里掠過....

如果你用AJAX POST的方法,那么后臺一樣,前臺也要有Hidden field保存Token,然后在提交AJAX POST的時候加上該csrf參數即可。(更多csrf參考這個和這個。)

?

AJAX POST的CSRF防御

?

首先在頁面進入的時候從后臺生成一個Token(每個session),放到一個Hidden input(用Spring tag或freemarker可以寫) 。然后在ajax post提交的時候放到http請求的header里面:

復制代碼
var?headers?=?{};
????headers['__RequestVerificationToken']?=?$("#CSRFToken").val();
????
????$.ajax({
????????type:?"POST",
????????headers:?headers,
????????cache:?false,
????????url:?base?+?"ajax/domain/delete.do",
????????data:?"id=123",
????????dataType:"json",
????????async:?true,
????????error:?function(data,?error)?{},
????????success:?function(data)
????????{
????????????
????????}
????});
復制代碼

然后在后臺controller里面校驗header里面這個token,也可以把這個函數放到baseController里面:

復制代碼
protected?boolean?isValidCsrfHeaderToken()?{
????????if?(getRequest().getHeader("__RequestVerificationToken")?==?null
????????????????||?session
????????????????????????.getAttribute(CSRFTokenManager.CSRF_TOKEN_FOR_SESSION_ATTR_NAME)?==?null
????????????????||?!this.getRequest()
????????????????????????.getHeader("__RequestVerificationToken")
????????????????????????.equals(session
????????????????????????????????.getAttribute(
????????????????????????????????????????CSRFTokenManager.CSRF_TOKEN_FOR_SESSION_ATTR_NAME)
????????????????????????????????.toString()))?{
????????????return?false;
????????}
????????return?true;
????}
復制代碼
?

xss

關于xss的介紹可以看這個和這個網頁,具體我就講講Spring MVC里面的預防:

web.xml加上:

<context-param>
???<param-name>defaultHtmlEscape</param-name>
???<param-value>true</param-value>
</context-param>

Forms加上:

?

<spring:htmlEscape defaultHtmlEscape="true" />

?

更多信息查看OWASP的頁面

?

第二種方法是手動escape,例如用戶可以輸入:<script>alert()</script> 或者輸入<h2>abc<h2>,如果有異常,顯然有xss漏洞。

首先添加一個jar包:commons-lang-2.5.jar ,然后在后臺調用這些函數:StringEscapeUtils.escapeHtml(string); StringEscapeUtils.escapeJavaScript(string); StringEscapeUtils.escapeSql(string);

前臺js調用escape函數即可。

?

第三種方法是后臺加Filter,對每個post請求的參數過濾一些關鍵字,替換成安全的,例如:< > ' " \ /? # &

方法是實現一個自定義的HttpServletRequestWrapper,然后在Filter里面調用它,替換掉getParameter函數即可。

首先添加一個XssHttpServletRequestWrapper:

復制代碼
package?com.ibm.web.beans;

import?java.util.Enumeration;

import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletRequestWrapper;

public?class?XssHttpServletRequestWrapper?extends?HttpServletRequestWrapper?{??
????public?XssHttpServletRequestWrapper(HttpServletRequest?servletRequest)?{
????????super(servletRequest);
????}
????public?String[]?getParameterValues(String?parameter)?{
??????String[]?values?=?super.getParameterValues(parameter);
??????if?(values==null)??{
??????????????????return?null;
??????????}
??????int?count?=?values.length;
??????String[]?encodedValues?=?new?String[count];
??????for?(int?i?=?0;?i?<?count;?i++)?{
?????????????????encodedValues[i]?=?cleanXSS(values[i]);
???????}
??????return?encodedValues;
????}
????public?String?getParameter(String?parameter)?{
??????????String?value?=?super.getParameter(parameter);
??????????if?(value?==?null)?{
?????????????????return?null;
??????????????????}
??????????return?cleanXSS(value);
????}
????public?String?getHeader(String?name)?{
????????String?value?=?super.getHeader(name);
????????if?(value?==?null)
????????????return?null;
????????return?cleanXSS(value);
????}
????private?String?cleanXSS(String?value)?{
????????????????//You'll?need?to?remove?the?spaces?from?the?html?entities?below
????????value?=?value.replaceAll("<",?"&?lt;").replaceAll(">",?"&?gt;");
????????value?=?value.replaceAll("\\(",?"&?#40;").replaceAll("\\)",?"&?#41;");
????????value?=?value.replaceAll("'",?"&?#39;");
????????value?=?value.replaceAll("eval\\((.*)\\)",?"");
????????value?=?value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']",?"\"\"");
????????value?=?value.replaceAll("script",?"");
????????return?value;
????}

}?
復制代碼

然后添加一個過濾器XssFilter :

復制代碼
package?com.ibm.web.beans;

import?java.io.IOException;??

import?javax.servlet.Filter;??
import?javax.servlet.FilterChain;??
import?javax.servlet.FilterConfig;??
import?javax.servlet.ServletException;??
import?javax.servlet.ServletRequest;??
import?javax.servlet.ServletResponse;??
import?javax.servlet.http.HttpServletRequest;??
import?javax.servlet.http.HttpServletResponse;

public?class?XssFilter?implements?Filter?{
????FilterConfig?filterConfig?=?null;

????public?void?init(FilterConfig?filterConfig)?throws?ServletException?{
????????this.filterConfig?=?filterConfig;
????}

????public?void?destroy()?{
????????this.filterConfig?=?null;
????}

????public?void?doFilter(ServletRequest?request,?ServletResponse?response,
????????????FilterChain?chain)?throws?IOException,?ServletException?{
????????chain.doFilter(new?XssHttpServletRequestWrapper(
????????????????(HttpServletRequest)?request),?response);
????}
}
復制代碼

最后在web.xml里面配置一下,所有的請求的getParameter會被替換,如果參數里面 含有敏感詞會被替換掉:

復制代碼
<filter>
?????<filter-name>XssSqlFilter</filter-name>
?????<filter-class>com.ibm.web.beans.XssFilter</filter-class>
??</filter>
??<filter-mapping>
?????<filter-name>XssSqlFilter</filter-name>
?????<url-pattern>/*</url-pattern>
?????<dispatcher>REQUEST</dispatcher>
??</filter-mapping>
復制代碼

?(這個Filter也可以防止SQL注入攻擊)?

?

登錄頁面的攻擊例子

假設登錄頁面有個輸入用戶名和密碼的輸入框,可以有很多Xss/csrf/注入釣魚網站/SQL等的攻擊手段,例如:

?

輸入用戶名 :??? >"'><script>alert(1779)</script>
?輸入用戶名:???? usera>"'><img src="javascript:alert(23664)">
?輸入用戶名:???? "'><IMG SRC="/WF_XSRF.html--end_hig--begin_highlight_tag--hlight_tag--">
?輸入用戶名:???? usera'"><iframe src=http://demo.testfire.net--en--begin_highlight_tag--d_highlight_tag-->
? ?

轉載于:https://www.cnblogs.com/Augur/p/7904288.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/390700.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/390700.shtml
英文地址,請注明出處:http://en.pswp.cn/news/390700.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux c編程

c語言標準 ANSI CPOSIX&#xff08;提高UNIX程序可移植性&#xff09;SVID&#xff08;POSIX的擴展超集&#xff09;XPG&#xff08;X/Open可移植性指南&#xff09;GNU C&#xff08;唯一能編譯Linux內核的編譯器&#xff09; gcc 簡介 名稱&#xff1a; GNU project C an…

html怎么注釋掉代碼_HTML注釋:如何注釋掉您HTML代碼

html怎么注釋掉代碼HTML中的注釋 (Comments in HTML) The comment tag is an element used to leave notes, mostly related to the project or the website. This tag is frequently used to explain something in the code or leave some recommendations about the project.…

k均值算法 二分k均值算法_使用K均值對加勒比珊瑚礁進行分類

k均值算法 二分k均值算法Have you ever seen a Caribbean reef? Well if you haven’t, prepare yourself.您見過加勒比礁嗎&#xff1f; 好吧&#xff0c;如果沒有&#xff0c;請做好準備。 Today, we will be answering a question that, at face value, appears quite sim…

您好,這是我的第一篇文章

您好我是CYL 這是一個辣雞博客 歡迎指教 轉載于:https://www.cnblogs.com/pigba/p/8823472.html

08_MySQL DQL_SQL99標準中的多表查詢(內連接)

# sql99語法/*語法&#xff1a; select 查詢列表 from 表1 別名 【連接類型】 join 表2 別名 on 連接條件 【where 篩選條件】 【group by 分組】 【having 分組后篩選】 【order by 排序列表】分類內連接&#xff08;重點&#xff09;&#xff1a; inner外連接 左外&#xff0…

java中抽象類繼承抽象類_Java中的抽象類用示例解釋

java中抽象類繼承抽象類Abstract classes are classes declared with abstract. They can be subclassed or extended, but cannot be instantiated. You can think of them as a class version of interfaces, or as an interface with actual code attached to the methods.抽…

新建VUX項目

使用Vue-cli安裝Vux2 特別注意配置vux-loader。來自為知筆記(Wiz)

衡量試卷難度信度_我們可以通過數字來衡量語言難度嗎?

衡量試卷難度信度Without a doubt, the world is “growing smaller” in terms of our access to people and content from other countries and cultures. Even the COVID-19 pandemic, which has curtailed international travel, has led to increasing virtual interactio…

Linux 題目總結

守護進程的工作就是打開一個端口&#xff0c;并且等待&#xff08;Listen&#xff09;進入連接。 如果客戶端發起一個連接請求&#xff0c;守護進程就創建&#xff08;Fork&#xff09;一個子進程響應這個連接&#xff0c;而主進程繼續監聽其他的服務請求。 xinetd能夠同時監聽…

《精通Spring4.X企業應用開發實戰》讀后感第二章

一、配置Maven\tomcat https://www.cnblogs.com/Miracle-Maker/articles/6476687.html https://www.cnblogs.com/Knowledge-has-no-limit/p/7240585.html 二、創建數據庫表 DROP DATABASE IF EXISTS sampledb; CREATE DATABASE sampledb DEFAULT CHARACTER SET utf8; USE sampl…

換了電腦如何使用hexo繼續寫博客

前言 我們知道&#xff0c;使用 Githubhexo 搭建一個個人博客確實需要花不少時間的&#xff0c;我們搭好博客后使用的挺好&#xff0c;但是如果我們有一天電腦突然壞了&#xff0c;或者換了系統&#xff0c;那么我們怎么使用 hexo 再發布文章到個人博客呢&#xff1f; 如果我們…

leetcode 525. 連續數組

給定一個二進制數組 nums , 找到含有相同數量的 0 和 1 的最長連續子數組&#xff0c;并返回該子數組的長度。 示例 1: 輸入: nums [0,1] 輸出: 2 說明: [0, 1] 是具有相同數量 0 和 1 的最長連續子數組。 示例 2: 輸入: nums [0,1,0] 輸出: 2 說明: [0, 1] (或 [1, 0]) 是…

實踐作業2:黑盒測試實踐(小組作業)每日任務記錄1

會議時間&#xff1a;2017年11月24日20:00 – 20:30 會議地點&#xff1a;在線討論 主 持 人&#xff1a;王晨懿 參會人員&#xff1a;王晨懿、余晨晨、鄭錦波、楊瀟、侯歡、汪元 記 錄 人&#xff1a;楊瀟 會議議題&#xff1a;軟件測試課程作業-黑盒測試實踐的啟動計劃 會議內…

視圖可視化 后臺_如何在單視圖中可視化復雜的多層主題

視圖可視化 后臺Sometimes a dataset can tell many stories. Trying to show them all in a single visualization is great, but can be too much of a good thing. How do you avoid information overload without oversimplification?有時數據集可以講述許多故事。 試圖在…

iam身份驗證以及訪問控制_如何將受限訪問IAM用戶添加到EKS群集

iam身份驗證以及訪問控制介紹 (Introduction) Elastic Kubernetes Service (EKS) is the fully managed Kubernetes service from AWS. It is deeply integrated with many AWS services, such as AWS Identity and Access Management (IAM) (for authentication to the cluste…

一步一步構建自己的管理系統①

2019獨角獸企業重金招聘Python工程師標準>>> 系統肯定要先選一個基礎框架。 還算比較熟悉Spring. 就選Spring boot postgres mybatis. 前端用Angular. 開始搭開發環境&#xff0c;開在window上整的。 到時候再放到服務器上。 自己也去整了個小服務器&#xff0c;…

面向對象面向過程

1、面向語句&#xff1a; 直接寫原生的sql語句&#xff0c;但是這樣代碼不容易維護。改一個方法會導致整個項目都要改動&#xff0c; 2、面向過程 定義一些函數&#xff0c;用的時候就調用不用就不調用。但是這也有解決不了的問題&#xff0c;如果要維護需要改動代碼&#xff0…

python邊玩邊學_邊聽邊學數據科學

python邊玩邊學Podcasts are a fun way to learn new stuff about the topics you like. Podcast hosts have to find a way to explain complex ideas in simple terms because no one would understand them otherwise &#x1f642; In this article I present a few episod…

react css多個變量_如何使用CSS變量和React上下文創建主題引擎

react css多個變量CSS variables are really cool. You can use them for a lot of things, like applying themes in your application with ease. CSS變量真的很棒。 您可以將它們用于很多事情&#xff0c;例如輕松地在應用程序中應用主題。 In this tutorial Ill show you …

vue 自定義 移動端篩選條件

1.創建組件 components/FilterBar/FilterBar.vue <template><div class"filterbar" :style"{top: top px}"><div class"container"><div class"row"><divclass"col":class"{selected: ind…