1.什么是XSS攻击
XSS也叫CSS,是Cross Site Script的简称,为了和CSS(样式)区分开来,所以改名为XSS。XSS是web常见的攻击手段之一,是通过向目标网站注入可执行的恶意代码,以达到攻击的目的。黑客能够通过XSS攻击,窃取用户的信息想要进行XSS攻击,盗取用户的登陆凭证发起CSRF攻击。想要达到XSS攻击必须达到两个条件,第一是向目标网站注入恶意代码,第二是这部分代码是可以被客户端浏览器执行的。从攻击的方式划分,XSS攻击又分为反射型XSS和持久型XSS。
2.反射型XSS:
反射型XSS,是用户点击恶意链接,服务器接收解析响应后,在返回的响应中包含恶意的代码,被客户端浏览器执行,这样一来,XSS的攻击代码,是通过服务器的响应反射回来的,所以被称为反射型XSS攻击。一般攻击者会在邮件,聊天记录,钓鱼网站中添加恶意的URL,用户在不知情的情况下点击,就很容易发生XSS反射攻击。
比如:
<div>
<img id="img1" src="~/StaticFiles/Backend/Images/@Request.QueryString["Id"].ToString()" />
</div>
单从源码中看,这是一个正常的页面,每次当页面加载的时候,会读取QueryString的值,加载相应的图片。但是黑客往往就会利用这个安全漏洞,在钓鱼网站,邮件,贴吧中发出一个恶意链接:
http://localhost:7286/Home/Test?Id=default_user.jpg“/><script>console.log(/xss/)<script/>
用户在不知情的情况下,点击了这个恶意链接,则浏览器会执行这一段脚本:
<script>console.log(/xss/)<script/>
用户在不知情的情况下就已经遭受到XSS攻击。
3. 持久型XSS
持久型XSS,持久型XSS具有较强的隐秘性和持久性,攻击者通常通过在博客,论坛等社交网站评论内容,将恶意的代码保存到web服务器中,当用户加载页面内容时,客户端浏览器会加载并执行这部分恶意代码。持久型XSS具有两个特点:一是恶意代码保存到了web服务器中,二是攻击者一般是利用博客,论坛等社交网站中评论留言功能,将恶意代码注入到web服务器。比起反射型XSS,持久型XSS的隐秘性更强,而且每当用户浏览论坛,博客的评论或留言时,就会受到XSS攻击,攻击范围非常广。
比如:
黑客会在评论留言中添加这么一串代码:
<script>console.log(“XSS”)</script>
每当用户加载评论区中的内容时,就会将这部分的恶意代码加载到客户端的浏览器中,并能够成功执行,这时,用户在不知道的情况下,就遭受到了XSS攻击。可以看出,持久型XSS具有很强的隐秘性,用户在刷博客,刷论坛的时候,不知不觉可能就已经被攻击了,而且这种攻击的范围非常的广泛,并不是只针对某一用户。
4. XSS攻击能够诱发CSRF攻击
为什么XSS攻击能够诱发CSRF攻击呢?(什么是CSRF攻击?本文后面会详细讲解。)原理很简单,上面我们说过了,XSS攻击是将恶意的代码注入带我们的网站中,那么用户在不知情的情况下,攻击者则可以通过document.cookie这个脚本,将我们的cookie发到黑客的指定网站,当黑客窃取到我们当前的登陆凭据(cookie)后,会以我们的用户身份做一个伪造请求,登陆我们的网站,做一系列的违规操作,窃取我们的数据。
5. 如何防御XSS攻击:
”<“ 转成 ”<”
”>“ 转成 ”>“
"&” 转成 "&"
\" 转成 """
“'” 转成 "'"
“\” 转成 “\\”
“/” 转成 "\/"
var cookie = new HttpCookie("username", "lyq");
cookie.HttpOnly=true;
但是将cookie的HttpOnly属性设置成true也不是万无一失的方法,因为在低版本的浏览器中,是不支持HttpOnly属性的。
1. 什么是CSRF攻击?
CSRF是跨站请求伪造(Cross Site Request Forgery)的简称,是通过盗取客户端用户的合法登陆凭据,冒用了用户的合法身份,对服务器发起请求,但是这种请求对服务器来说又是合法合理的。比如:黑客能够盗用我们的合法身份,对他们的博客进行关注,评论,也能够向他们的银行账户转账。用户被攻击,首先要具备两个条件:一是用户成功登陆A网站,并且没有登出,在客户端浏览器保留了登陆凭据(cookie),二是用相同的浏览器访问恶意的网站。
2. CSRF攻击的原理:
用户lyq登陆了A网站,服务器在接收到请求后,会在服务端存放一个session,并响应客户端一个cookie,这就在用户lyq电脑的客户端保留了一个合法的登陆凭据。
用户lyq在保留了A网站的登陆凭据的前提下,用相同的浏览器访问了B网站(恶意的钓鱼网站)
B网站盗取到了A网站的登陆凭据,则黑客可以利用lyq的登陆凭据,成功的访问了A网站,并且窃取到了用户LYQ的信息,做一系列的违规操作。
3.实例分析:
现在A网站是通过这么一个接口向可以向某人转账:
http://www.lyq.com:5002/Home/TransferMoney?transferTo=someone&money=100
碰巧lyq在A网站有一个账户。某天,lyq登陆了A网站。正常情况下,lyq登陆A网站后,会在服务器内存中存放一个session, 并且服务器会响应一个cookie给客户端浏览器,作为登陆凭据。
粗心大意的lyq在没有登出A网站的情况下(登陆凭据没有注销),用相同的浏览器访问了B网站。
http://www.hacker.com:5003/
B网站是一个钓鱼网站。在B网站中有这么一串代码。
<iframe src="http://www.lyq.com:5002/Home/TransferMoney?transferTo=Jack&money=1000"></iframe>
当lyq访问B网站时,黑客Jack在lyq不知情的情况下,就盗用了lyq的登陆凭据,仿造lyq的请求,向A网站发送了一个转账的请求。服务器在接收到这个请求后,后认为这就是lyq自己发起的请求,认为是一个合法的请求,这就将lyq账户中的1000元转到黑客Jack的账户下。
由于iframe的src属性,B网站跨站的调用了A网站的转账接口,B网站发起的转账请求和A网站在客户端存留的cookie在同一个域下,则B网站每次向A网站服务器请求的时候,都会自动带上这个合法的登陆凭据(cookie),伪造成一个合法的请求。
知道这个安全漏洞后,A网站的工作人员迅速修复了这么一个安全漏洞,将这个接口设置成post请求。但是道高一尺,魔高一丈。黑客Jack也迅速对B网站做了升级。
<form action="http://www.lyq.com:5002/Home/TransferMoney" method="post" id="form1">
<input type="text" name="transferTo" value="Jack" />
<input type="text" name="money" value="1000" />
<button type="submit" id="btnSubmit">提交</button>
</form>
<script>
window.onload = function () {
document.getElementById("form1").submit();
}
</script>
当lyq访问到B网站时,同样会对A网站发送一个合理post请求,将lyq账户中的前转到黑客jack的帐下。当然,为了增加B网站的隐秘性,还可以下B网站下面再次嵌套一个ifram,防止页面的刷新。
4. 那如何能做到有效的防御CSRF攻击呢?
对于敏感的请求,尽量使用post请求代替get请求。这样会增加CSRF攻击的难度,从一定程度上能避免CSRF攻击。
对于表单请求,可以加上一个验证码。客户端在每次请求时,都要带上这个验证码,和服务器上的验证码进行匹配,如果匹配失败,则请求无效。这样能够有效的避免90% 以上的CSRF攻击。但是这样缺点也十分的明显,若对于一个项目来说,有很多的表单请求,如果每一个表单请求都要用验证码验证,对于用户来说会是一个很糟糕的体验。
服务器在每次接收http请求时,先判断这个http请求的来源地址Refer。如果这个http请求不是从受信任的域名发起的,我们则认为这是一个非法的请求。
以 ASP.NET MVC为例:
public void OnActionExecuting(ActionExecutingContext filterContext)
{
//获取受信任域名
var TrustedDomain = Initialize.GetTrustedDomain;
var httpContext = filterContext.HttpContext;
if (httpContext.Request.UrlReferrer != null && !TrustedDomain.Contains(httpContext.Request.UrlReferrer.Host))
{
if (httpContext.Request.IsAjaxRequest())
{
filterContext.Result = new JsonResult()
{
Data = new JsonData() { Info = $"403 Forbidden.", Status = "403" },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
else filterContext.Result = new RedirectResult("/Error/NotFound");
}
}
但是缺点就是依赖于浏览器的Refer属性,如果用户关闭掉客户端浏览器的这一功能后,则正常的用户每次访问网站时,都会被视为一个非法的请求,无法正常使用。