You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// codingmay/views/index.pughtmlheadtitle=titlebodyuleachdatainlist//- [call onclick js function and pass param from pug](https://github.com/pugjs/pug/issues/2933)li=data.titlebutton(onclick=`deleteArticle(${data.id})`)="删除"elseli="没有文章了"script.asyncfunctiondeleteArticle(id){constresponse=awaitfetch(`/api/delete/article/${id}`,{method: 'POST'})if(response.status===401){returnalert(`Delete article failed with message: ${response.statusText}`);}if(response.status===200){alert(`Delete article success`);location.reload();return;}}
模拟 “黑客君” 伪造请求
创建 hacker/app.js 文件,设置服务端口为 4000,渲染页面。
// hacker/app.jsconstexpress=require('express')constpath=require('path')constapp=express()constPORT=4000app.set('views',path.join(__dirname,'views'));app.set('view engine','pug')app.get('/',(req,res)=>{res.render('index',{title: '黑客网站'})});app.listen(PORT,()=>console.log(`Example app listening at http://localhost:${PORT}`))
在黑客自己伪造的页面,自动触发请求,如何是 GET 请求就更好模拟了,<script src="">、<img src=""、<a href=""/> 这些标签本身不受同源策略限制,可直接发起请求。
有些网站服务端提供的接口为 POST,我们可构建一个隐藏的表单伪造 POST 请求,当用户 “五月君” 打开 “黑客君” 伪造的页面后,表单会自动提交,服务器在收到请求后执行删除文章操作。
跨站请求伪造(Cross-Site Request Forgery,简称 CSRF)是一种冒充受信任用户在当前已登陆 Web 应用程序上执行非本意操作的攻击方式。
CSRF 攻击细节
CSRF 攻击简单来说,是黑客通过一种技术手段诱骗用户浏览器访问一个曾经受信任的网站去执行一些非法操作。这利用了 Web 中用户身份验证的一个漏洞:“简单的身份验证只保证了请求是发自用户的浏览器,却不能验证请求本身是否为用户自愿发出的”。
CSRF 攻击模拟
假设 “五月君” 是某内容管理系统网站
www.codingmay.com
的管理员,拥有删除文章的操作权限。/api/user/auth
登陆网站,此时网站会将该用户信息放入 cookie 中,用于后续身份验证。POST: /api/delete/article/:id
接口,传递文章 id 使用 POST 请求删除一篇文章。www.hacker.com
伪造了一个 CSRF 请求。www.hacker.com
。模拟两个站点
修改本地
/etc/hosts
文件,模拟两个站点:www.codingmay.com
表示 “五月君” 要登陆的内容管理系统。www.hacker.com
这是 “黑客君” 模拟 CSRF 的网站。另外一个知识点:由于在本地模拟,两个站点主机都使用的
localhost
通过port
区分,而 cookie 的存储需要根据域名做区分,本示例中 cookie 存放在www.codingmay.com
中。初始化项目
使用 Node.js Express 框架和 pug 模版引擎模拟 CSRF 攻击,创建项目和安装依赖。
模拟内容管理系统
创建
codingmay/app.js
文件,设置服务端口为 3000,提供如下接口:/user/auth
:模拟用户授权,保存用户信息到 cookie 中,设置 cookie 过期时间为 10 分钟。/article/list
:文章列表,授权成功跳转至该页面。/delete/article/:id
:模拟删除文章,如果 cookie 不存在,提示未授权删除失败。基于 pug 模版引擎,模拟简单的内容管理页面,在这个页面可查看和删除文章。
模拟 “黑客君” 伪造请求
创建
hacker/app.js
文件,设置服务端口为 4000,渲染页面。在黑客自己伪造的页面,自动触发请求,如何是 GET 请求就更好模拟了,
<script src="">
、<img src=""
、<a href=""/>
这些标签本身不受同源策略限制,可直接发起请求。有些网站服务端提供的接口为 POST,我们可构建一个隐藏的表单伪造 POST 请求,当用户 “五月君” 打开 “黑客君” 伪造的页面后,表单会自动提交,服务器在收到请求后执行删除文章操作。
操作演示
通过一个 Gif 动图演示,如果不理解的,最好是能够跟着上面的 Demo 在本地实践下。
在看一张图,如下所示,这是在黑客伪造的网站上发起的请求信息,且 Cookie 是浏览器自动为我们获取带上的。
CSRF 攻击预防
CSRF 攻击的特点是利用受害者已登陆网站的凭证,冒充受害者在第三方网站发起操作,这里攻击者只能使用 cookie,而不能获取。针对性的提出防范策略:
检查 Referer/Origin 字段
HTTP 请求头包含一个 Referer 字段标明了请求来源于哪个地址,在处理敏感数据请求时应位于同一域名下,该包含了 URL 路径,除此之外还有一个 Origin 字段包含了域名信息。
我们可以优先判断 Origin 字段,再根据具体情况选择性的判断 Referer 字段。
Cookie SameSite 属性
上面示例中我们在黑客伪造的网站
www.hacker.com
上引导发出的 Cookie 称为第三方 Cookie。为了减少安全风险,可设置 Cookie 的 SameSite 属性用来限制发送第三方 Cookie。Cookie 的 SameSite 属性有三个值:
<form method="GET">
)、链接 (<a></a>
)、预加载(<link rel="prerender"/>
) 这三种情况下会发送 Cookie 信息。CSRF Token
解决 CSRF 攻击另一个常用的解决方案是 CSRF Token 验证,第一步是浏览器向服务器请求时,服务器返回一个随机 Token。
浏览器将该 Token 以隐藏形式植入页面中,当需要请求数据时,携带上 Token 信息,最好的方式是放在 Headers 请求头中,让请求发生跨域。此处为了简单测试,放在 query 传递。
服务器对传递的 Token 信息增加验证,现在从第三方网站发起的请求,即便取到 Cookie,也很难取到 CSRF Token 值,进一步增强安全性。
Node.js 中有一个中间件 expressjs/csurf 也可用来预防 CSRF 攻击。
Reference
The text was updated successfully, but these errors were encountered: