CSRF(Cross-site request forgery),即跨站请求伪造,是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
比如说,用户之前登录了网银网站A,又去访问了含有恶意内容的网站B。网站 B 的某些内容会请求网银网站 A 的内容,发起转账操作(这些操作通过一个请求即可完成)。因为用户之前登录过网银网站 A,访问时就会自动携带上 Cookie。网银网站 A 在请求中解析了 Cookie,认为是用户的操作,就会直接执行。由此造成财产的损失。如图:
需要注意的是,这种攻击策略在现在已经难以实现了,因为浏览器的策略限制了 Cookie 的自动发送。详见下面的章节。
为了模拟之前的情况,我们安装了一个 Windows 7 的虚拟机,并安装 Google Chrome 78 版本。
在安装虚拟机的过程中,安装 Vmware Tools 时可能会报错,参见这个博客。历史版本的 Chrome 在此处下拉选择下载。虚拟机的安装和配置有很多资料,在这里就不赘述了。
这里需要注意的是,一定要禁止 Chrome 自动更新,否则更新为最新版本后就无法复现了。参考此文章。
要先点击左侧的 Logout 后,使用 admin/password 登录,将等级调整为 Low 后,点击左侧 CSRF,可以看到大概如下的页面:
正常情况下,我们先修改密码:
注意看,修改密码的请求出现在了地址栏上(即使没有出现在地址栏,也可以通过捕包的方式查看到 HTTP 请求详情,这为我们后续的操作埋下了伏笔)。之后可以点击 TestCredentials 验证新的密码是否生效,如图:
如果我们能够构造一个假网站,在网页中向正常网站发出修改密码的请求。然后诱骗 访问过这个正常网站修改密码页面的用户 来访问,就可以神不知鬼不觉的修改该用户的密码了不是?
我们先编写一下假网站的代码,如下(注意修改其中的具体地址):
<!DOCTYPE html>
<html>
<meta charset="utf-8" />
<head>
<title>这是一个用于 CSRF 的假网站</title>
</head>
<body>
<img src="http://192.168.117.131/vulnerabilities/csrf/?password_new=1234567890&password_conf=1234567890&Change=Change#" />
<br />
一张美女图片,请欣赏!
</body>
</html>
在这个假网站中,我们通过嵌入 img 标签的形式(因为天生可以跨域)悄悄地发送修改密码为 1234567890 的请求。
最后将该网站部署在 192.168.117.129 这台机器上,端口号为 8080。
在点击 Logout 重新登陆、调整难度为 Low、修改完密码为 123456 这三个步骤后,假装“鬼使神差”地打开了这个网站XD。“咦~,美女图片怎么看不了啊,算了算了不看了”。 此时返回正常页面,再次点击 TestCredentials 按钮,发现密码 123456 已经不正确了,我们的密码已经在暗中被修改了!!!
扮演受害者需要注意的是,因为调整的难度等级也存在 cookie 中,因此一定要点击 Logout 后重新登录,调整难度为 Low,否则无法达到预期的效果。
通过 F12 可以看到,在 Request Header 中向正常网站发送了 Cookie,让正常网站以为是用户的操作。而此时,一心要查看“美女图片”的用户是毫无察觉的。
查看下源代码,发现通过 stripos 函数对 HTTP 请求的 Referer 头进行了包含性验证。如果我们拦截请求并篡改了 Referer 头为它想要的值,是不是就可以了?
通过观察正常请求,可以发现:
在正常的请求头中添加 Referer 字段为此值即可。修改我们的恶意“美女图片”网站如下:
<!DOCTYPE html>
<html>
<meta charset="utf-8" />
<head>
<title>这是一个用于 CSRF 的假网站</title>
</head>
<body>
<img src="jia_zhuang_shi_yi_zhang_tu_pian" />
<br />
一张美女图片,请欣赏!
<script>
// 在此处发送一个请求,并尝试手动设置为 Referer 为 http://192.168.117.131/vulnerabilities/csrf/
var req = new XMLHttpRequest();
req.open("GET", "http://192.168.117.131/vulnerabilities/csrf/?password_new=12345678&password_conf=12345678&Change=Change#", true);
req.setRequestHeader("Referer", "http://192.168.117.131/vulnerabilities/csrf/");
req.send();
</script>
</body>
</html>
假装受害者访问下,发现浏览器报错了:
可以看到主要报了两个错误:
通过查询资料学习了解到,可以配合 XSS 来实现攻击。大概原理是:向正常网站嵌入恶意的内容,这样在用户访问包含该内容的网页时,就不知不觉地执行了敏感操作。关于 XSS,这里就先挖个坑吧。
此处其实还有一个漏洞,就是只判断了 Referer 头的字符串值是否包含 网站地址,在我的测试环境中,$_SERVER[ 'SERVER_NAME' ] 的值为 192.168.117.131,也就是说,如果请求从该网站其它位置发出,也可以通过验证。这也是我们可以通过 XSS 的形式攻击的重要条件之一。
通过查看源代码发现,新添加了一个每次访问都不同的 user_token 字段,企图来阻止我们的恶意访问。但是,我们如果手动获取这个 token,拼接到我们的请求中不就可以绕过了?
结果自然是同样的翻车先锋,因为请求跨域了,并且目标网站并不支持请求跨域,因此我们无法获取到 user_token,便无法进行接下来的攻击。不过同样地,可以配合 XSS 来实现。
从以上可以看出,单纯地使用 CSRF 攻击几乎很难取得效果了,除非真的没有一点验证(这还得是在 N 年前的浏览器环境下)。而现在:
这里由于内容较多,可以参阅 DVWA 给出的文档 和 网上的其它文档。粗暴的理解就是,原来浏览器会自动发送 Cookie 的场景,现在可能不自动发送了。
在我现在的 Chrome 浏览器中,按照难度等级为 Low 的方式操作:
可以看到此时并没有向目标网站发送 Cookie。反而因此还接收了目标网站的 Set-Cookie 的指令。至于红框中的感叹号,也可以参考 DVWA 给出的文档。
CSRF 攻击的基本依赖点是 Cookie 是浏览器默认情况下自动发送的。而现在的后台网站框架很多使用 JWT Token 来验证。JWT Token 并不会由浏览器自动发送,都是在请求时由用户前端程序发出。
Dvwa csrf之low、medium、high级别漏洞实战
【Windows】win7虚拟机安装VMware Tools
当SameSite属性为默认值Lax时,绕过它并获得一个CSRF
手机扫一扫
移动阅读更方便
你可能感兴趣的文章