跨站请求伪造 CSRF / XSRF<二:应用>
防御的方法主要有两种<java示例>
1.检查Referer字段
HTTP头中有一个Referer字段,这个字段用以标明请求来源于哪个地址。在处理敏感数据请求时,通常来说,Referer字段应和请求的地址位于同一域名下。以上文银行操作为例,Referer字段地址通常应该是转账按钮所在的网页地址,应该也位于www.examplebank.com之下。而如果是CSRF攻击传来的请求,Referer字段会是包含恶意网址的地址,不会位于www.examplebank.com之下,这时候服务器就能识别出恶意的访问。
这种办法简单易行,工作量低,仅需要在关键访问处增加一步校验。
***但这种办法也有其局限性,因其完全依赖浏览器发送正确的Referer字段。虽然http协议对此字段的内容有明确的规定,但并无法保证来访的浏览器的具体实现,亦无法保证浏览器没有安全漏洞影响到此字段。并且也存在攻击者攻击某些浏览器,篡改其Referer字段的可能。
检查Referer字段如下:
@Override
public void doFilter(ServletRequest servletrequest,
ServletResponse servletresponse, FilterChain filterchain)
throws IOException, ServletException { HttpServletRequest httpReq = (HttpServletRequest)servletrequest;
HttpServletResponse httpResp = (HttpServletResponse)servletresponse;
String path = httpReq.getContextPath();
String basePath = servletrequest.getScheme() + "://" + servletrequest.getServerName()
+ ":" + servletrequest.getServerPort() + path + "/"; // 防CSRF 之:HTTP 头设置 Referer过滤
String referer = httpReq.getHeader("Referer"); // REFRESH
if (referer != null && referer.indexOf(basePath) < 0) { //***
//判断为不安全的访问
String ctxPath = httpReq.getContextPath();
httpResp.sendRedirect(ctxPath+"/common/goNoSecurity.do");
return;
}
filterchain.doFilter(servletrequest, httpResp);
}
2.添加校验token
由于CSRF的本质在于攻击者欺骗用户去访问自己设置的地址,所以如果要求在访问敏感数据请求时,要求用户浏览器提供不保存在cookie中,并且攻击者无法伪造的数据作为校验,那么攻击者就无法再执行CSRF攻击。这种数据通常是表单中的一个数据项。服务器将其生成并附加在表单中,其内容是一个伪乱数。当客户端通过表单提交请求时,这个伪乱数也一并提交上去以供校验。正常的访问时,客户端浏览器能够正确得到并传回这个伪乱数,而通过CSRF传来的欺骗性攻击中,攻击者无从事先得知这个伪乱数的值,服务器端就会因为校验token的值为空或者错误,拒绝这个可疑请求。
token的校验规则:
a. 账户登录时产生一个token字段,且将token传入session中;
b.前端发送请求时,利用jsp中的session对象获取到token,一并传到后台;
c.在过滤器中校验请求中的token参数和session中的token参数是否一致;
d.如果一致,则通过;不一致则跳转到不安全页面。
代码如下:
a. 账户登录时产生一个token字段,且将token传入session中;
private void mainLoginDirect(HttpServletRequest request,Map<String, Object> respMap, Integer isLogin, RegAccout account) {
//salt加密
RegSalt rs=regAccoutService.getRegSaltbyAccname(account.getAcc_name());
if (rs==null) {
respMap.put(Const.AJAX_SERVICE_MESSAGE, "无效用户!");
}else{
String password=account.getPassword();
String password1=request.getParameter("password");
String isVip=request.getParameter("isVip");
String salt=rs.getSalt();
if(CryptoUtils.verify(password, password1, salt)){//密码正确
SessionUtil.setAttribute(Const.SESSION_CSRFTOKEN,SRMStringUtil.getUUID());//***创建token,防CSRF
respMap.put("pw", true);
}else{//密码不正确
respMap.put(Const.AJAX_SERVICE_MESSAGE, "密码错误!请重新输入。");
respMap.put("pw", false);
}
}
}
b.前端发送请求时,利用jsp中的session对象获取到token,一并传到后台;
function asyncAjaxMethod(url,params,isasync,fn){
params.csrftoken ="${sessionScope.csrftoken }";//*** 这里获取token
$.ajax({
type: "POST",
async:isasync,
url: getwebroot()+url,
dataType:'json',
data:params,//***
beforeSend: function () {
$("body").append("<div id='spin_wrap'></div>");
$("#spin_wrap").addClass("spin_mask");
spinner.spin(document.getElementById("spin_wrap"));
},
success:function(result){
//关闭loding效果
spinner.spin();
$("body #spin_wrap").remove();
if(result.success==false){
//人为抛出异常,但是要求设置success=false
if(result.ajaxErrorCode==999){
if(hasRemainLoginPop()){//有弹出过登录框
remindLogin_flag=true;
}
if(!remindLogin_flag){
window.wxc.xcConfirm("登录超时,请重新登录", window.wxc.xcConfirm.typeEnum.confirm,
{
onClose:function(){//超时,则弹出登录框
window.plugLogin();
}
});
}
}else if(result.ajaxErrorCode==970){
go_redirect("error/noSecurity.htm");
}else if(result.ajaxErrorCode==980){
go_redirect("error/beKick.html");
}else if( result.ajaxErrorCode==300)
{
var option ={title:"提示",btn:parseInt("0001",2)};
window.wxc.xcConfirm(result.message, window.wxc.xcConfirm.typeEnum.custom,option);
}
else
{
//300:请求参数异常
window.wxc.xcConfirm("操作失败,请稍后再试", window.wxc.xcConfirm.typeEnum.error);
}
}else{//默认success==true
if(result.ajaxErrorCode==200){
if(fn!=null && typeof(fn)=="function"){
fn(result);
}
}else{
window.wxc.xcConfirm('抱歉,返回标志错误,请稍后再试或与管理员联系', window.wxc.xcConfirm.typeEnum.error);
}
}
},
//异常未捕获时,跳转到这里
error: function (XMLHttpRequest, textStatus, errorThrown) {
//关闭loding效果
spinner.spin();
$("body #spin_wrap").remove();
if(XMLHttpRequest.status==404){
go_redirect("error/404.html");
}else if(XMLHttpRequest.status==500){
go_redirect("error/500.html");
}else{
window.wxc.xcConfirm('抱歉,程序异常未捕获,请稍后再试或与管理员联系', window.wxc.xcConfirm.typeEnum.error);
}
}
});
return remindLogin_flag;
}
c.在过滤器中校验请求中的token参数和session中的token参数是否一致;
d.如果一致,则通过;不一致则跳转到不安全页面。
if(tarUri.endsWith(".do") && !isWithoutUri(tarUri) && httpReq.getContentType() != null){
String contentType = httpReq.getContentType();
String post_csrftoken = "";
if(contentType != null && contentType.contains("multipart/form-data")){
MultipartHttpServletRequest multiReq = multipartResolver.resolveMultipart(httpReq);
post_csrftoken=multiReq.getParameter(Const.SESSION_CSRFTOKEN);
req = multiReq;
}else{
post_csrftoken=httpReq.getParameter(Const.SESSION_CSRFTOKEN);
}
//csrf防御:判断是否带token
String csrftoken=(String)SessionUtil.getAttribute(Const.SESSION_CSRFTOKEN);
if(post_csrftoken==null || !csrftoken.equals(post_csrftoken)){//***判断token正确性
//判断为不安全的访问
httpResp.sendRedirect(ctxPath+"/common/goNoSecurity.do");
return;
}
}
跨站请求伪造 CSRF / XSRF<二:应用>的更多相关文章
- 跨站请求伪造 CSRF / XSRF<一:介绍>
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一 ...
- .NET Core实战项目之CMS 第十四章 开发篇-防止跨站请求伪造(XSRF/CSRF)攻击处理
通过 ASP.NET Core,开发者可轻松配置和管理其应用的安全性. ASP.NET Core 中包含管理身份验证.授权.数据保护.SSL 强制.应用机密.请求防伪保护及 CORS 管理等等安全方面 ...
- 跨站请求伪造(CSRF)-简述
跨站请求伪造(CSRF)-简述 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 ...
- 跨站请求伪造(CSRF)攻击原理解析:比你所想的更危险
跨站请求伪造(CSRF)攻击原理解析:比你所想的更危险 跨站请求伪造(Cross-Site Request Forgery)或许是最令人难以理解的一种攻击方式了,但也正因如此,它的危险性也被人们所低估 ...
- PHP安全编程:跨站请求伪造CSRF的防御(转)
跨站请求伪造(CSRF)是一种允许攻击者通过受害者发送任意HTTP请求的一类攻击方法.此处所指的受害者是一个不知情的同谋,所有的伪造请求都由他发起,而不是攻击者.这样,很你就很难确定哪些请求是属于跨站 ...
- django之跨站请求伪造csrf
目录 跨站请求伪造 csrf 钓鱼网站 模拟实现 针对form表单 ajax请求 csrf相关的两个装饰器 跨站请求伪造 csrf 钓鱼网站 就类似于你搭建了一个跟银行一模一样的web页面 , 用户在 ...
- ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击 (转载)
什么是反伪造攻击? 跨站点请求伪造(也称为XSRF或CSRF,发音为see-surf)是对Web托管应用程序的攻击,因为恶意网站可能会影响客户端浏览器和浏览器信任网站之间的交互.这种攻击是完全有可能的 ...
- 跨站请求伪造CSRF(Cross-site request forgery)
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站 ...
- 跨站请求伪造(csrf)中间件整理
一. CSRF中间件 字面意思跨站请求伪造; 即模仿个请求朝服务器发送,django中对跨站伪造的请求有相应的校验 from django.views.decorators.csrf import c ...
随机推荐
- ZooKeeper的Znode剖析
在ZooKeeper中,节点也称为znode.由于对于程序员来说,对zk的操作主要是对znode的操作,因此,有必要对znode进行深入的了解. ZooKeeper采用了类似文件系统的的数据模型,其节 ...
- Android -- 常见控件的小效果
1,EditText控件 ① 修改光标颜色 自定义drawable 创建cursor.xml文件 <?xml version="1.0" encoding="utf ...
- iOS开发:(线程篇-上)线程和进程
iOS开发多线程篇—多线程简单介绍 一.进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ.Xcod ...
- 纳尼,java可以在接口中实现非抽象方法了?
纳尼,接口中可以定义实例方法了?! 纳尼,接口中还可以定义静态方法了?! 没错,在Java8中新增了很多新的特性,其中就包括可以在接口中添加方法和变量. 首先我们来看下代码 public interf ...
- 在Excel表格中输入一大段文字
1.有时为了注释的需要,在excel中需要输入一大段文字,这时候可以使用—视图-工具-绘图,然后选择下面的文本框,即可自定义文本框大小,如需要文本框和表格边框完全重合,在鼠标画文本框时按住 Alt键.
- BabelMap 9.0.0.3 汉化版(2016年12月27日更新)
软件简介 BabelMap 是一个免费的字体映射表工具,可辅助使用<汉字速查>程序. 该软件可使用系统上安装的所有字体浏览 Unicode 中的十万个字符,还带有拼音及部首检字法,适合文献 ...
- [Effective JavaScript 笔记]第45条:使用hasOwnProperty方法以避免原型污染
之前的43条,44条讨论了属性的枚举,但都没有彻底地解决属性查找中原型污染的问题.看下面关于字典的一些操作 'zhangsan' in dict; dict.zhangsan; dict.zhangs ...
- java第六次作业(老师讲过后)
import java.util.*; public class Draw { private ArrayList list; public Draw() { list= new ArrayList( ...
- ASP.NET MVC异常处理
ASP.NET MVC异常处理方案 如何保留异常前填写表单的数据 ASP.NET MVC中的统一化自定义异常处理 MVC过滤器详解 MVC过滤器使用案例:统一处理异常顺道精简代码 ASP.NET MV ...
- 基于CNN的人脸相似度检测
人脸相似度检测主要是检测两张图片中人脸的相似度,从而判断这两张图片的对象是不是一个人. 在上一篇文章中,使用CNN提取人脸特征,然后利用提取的特征进行分类.而在人脸相似度检测的工作中,我们也可以利用卷 ...