防御思路
a.我们能不能区别一个请求是来自于自己的前端页面,还是第三方的网站。
b.怎么让自己的前端页面和伪造的请求变得不一样。
1.Referer
Referrer:引用页;引荐;来源页面 作用:跟踪来源,比如访问统计,广告效果
这里以dvwa的Medium靶场为例进行讲解
通过源码我们就能知道,检查当前请求的 HTTP 引用来源是否包含服务器的主机名,返回值如果不等于 false,说明请求来源于同一主机。假设我们这正常网站的网络请求的主机名是localhost,但通过该网站的后端就会审核某些请求的referrer是否包括localhost,如果没有说明该请求不是本机网站发出的请求,就就会将其过滤拦截。总结来说,if( stripos( $_SERVER[ 'HTTP_REFERER' ] , $_SERVER[ 'SERVER_NAME' ]) !== false )
用于确认用户请求来源于当前网站。
我们用bp进行抓包的时候就会得到该网络请求,该图则是正常的网络请求,如果是黑客进行攻击的时候,他的referer可能为空也有可能为其他,这时候黑客只需要通过bp等抓包工具将referrer值进行修改,改成包含服务器主机名的referer就能骗过服务器。
referer的不足:1)可以任意修改 2)可以为空
2.token
我们采用开头说的b思路,在请求中加入一些随机字段(第三方不知道也猜不出来),让第三方网站无法伪造请求
1)用户使用用户名密码登录,服务器下发一个随机的token字段给客户端,并且服务端把这个字段保存在session中。
2)客户端把这个token进行保存,放到隐藏字段。
3)用户在登录状态下,在之后访问的时候,都要携带这个token字段。
4)服务器从session中拿出token值进行对比,如果一致,说明请求合法。
if (hash_equals($_SESSION['token'], $_POST['token'])) 如果在第一步中没有执行,说明 token
存在,接着执行这一行。这里使用 hash_equals
函数来比较$_SESSION['token'], $_POST['token'])的值。这个函数用于安全地比较两个字符串,防止时间攻击。
5)用户退出,session销毁,token失效。
我们通过dvwa的源码来分析一下网站对于防御CSRF攻击的手段,这里就是先调用一个uniqid的函数来生成一个哈希值的token然后发送给客户端,然后结束后再销毁清空。
然后我们再查看网页的源代码发现这把有一个user_token,属性是hiden,客户端再后续进行访问的时候就会带上这个token,服务器收到后就会进行对比,相同后就会通过该请求。
如果拿不到token值得话就无法进行下一步攻击,但user_token的值也会泄露,甚至可能会被远程泄露,比如该网站刚好存在XSS漏洞,通过dvwa的high为例,在XSS的Reflected里输入下列命令,
<iframe src="../csrf" onload=alert(frames[0].document.getElementsByName('user_token')[0].value)>
这段代码是一个 HTML <iframe>
元素的示例,结合 JavaScript,意图从一个包含 CSRF(跨站请求伪造)保护令牌的页面中提取该令牌的值,并弹出一个警告框显示该值。
具体分析如下:
-
<iframe src="../csrf"
:这个部分创建了一个内嵌框架,尝试加载位于相对路径../csrf
的内容。 -
onload=alert(frames[0].document.getElementsByName('user_token')[0].value)
:当<iframe>
加载完成时,会执行这个 JavaScript 代码:frames[0]
访问第一个<iframe>
的内容。document.getElementsByName('user_token')[0]
查找该文档中名为user_token
的元素。.value
获取该元素的值。alert()
函数将该值以弹窗的形式展示出来。