XSS
Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击.
XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。
对输入保持不可信。
XSS分类
存储型 (持久型)
- 注入型脚本永久存储在目标服务器上。当浏览器请求数据时,脚本从服务器上传回并执行
- blog,论坛易受此类攻击
反射型 (非持久型)
- 恶意代码并不存储在服务器上,而是在客户端打开网页时暂时存在.
- 动态网页和邮件应用尤其容易受到此类攻击
基于DOM型(本地XSS)
- 在这种情况下,web 服务器不参与, 破坏是由客户端的脚本引起的.
XSS防御
对输入过滤(过滤script标签)检查 不要相信用户的任何输入。
输出处理 (服务器的输出也可能会出现问题)
- 改成纯前端渲染, 把代码和数据分隔开, 明确的告诉浏览器:下面要设置的内容是文本(.innerText),还是属性(.setAttribute),还是样式(.style)等等. 纯前端渲染还需注意避免 DOM 型 XSS 漏洞(例如 onload 事件和 href 中的 javascript:xxx
- 对HTML转义
- Vue/React 不使用v-html/dangerouslySetInnerHTML
验证码:防止脚本冒充用户提交危险操作
HttpOnly防止窃取Cookie:
- 禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此 Cookie。
使用CSP(Content Security Policy):
- 内容安全策略,实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行。分两类
- Content-Security-Policy
- Content-Security-Policy-Report-Only
- CSP可以在服务端的配置响应头HTTP Header,(Apache,Nginx)配置,也可以在HTML Meta标签配置;
CSRF
Cross-site request forgery 跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求. 利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
一个典型的CSRF攻击有着如下的流程:
- 受害者登录a.com,并保留了登录凭证(Cookie)。
- 攻击者引诱受害者访问了b.com。
- b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会携带a.com的cookie
- a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
- a.com以受害者的名义执行了act=xx。
- 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。
cookie一般用于保存信息,你向同一个服务器发请求时会带上浏览器保存的对于那个服务器的cookie,而不管你从哪个网站发请求
ps. http请求都会带着请求目标域下的cookie的。只要你向A网站发了请求,就会带上A网站的cookie。所以重要操作的请求,认证信息都是不能存放在cookie中的。
Cookie 是紧跟域名的。同一个域名下的所有请求,都会携带 Cookie
攻击者借助受害者的 Cookie 骗取服务器的信任,但并不能拿到 Cookie,也看不到 Cookie 的内容
https://github.com/dwqs/blog/issues/68
常见的CSRF攻击类型
- GET类型的CSRF
GET类型的CSRF利用非常简单,只需要一个HTTP请求
<img src="http://bank.example/withdraw?amount=10000&for=hacker" >
在受害者访问含有这个img的页面后,浏览器会自动向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker发出一次HTTP请求。bank.example就会收到包含受害者登录信息的一次跨域请求。
- POST类型的CSRF
这种类型的CSRF利用起来通常使用的是一个自动提交的表单
<form action="http://bank.example/withdraw" method=POST>
<input type="hidden" name="account" value="xiaoming" />
<input type="hidden" name="amount" value="10000" />
<input type="hidden" name="for" value="hacker" />
</form>
<script> document.forms[0].submit(); </script>
- 链接类型的CSRF
链接类型的CSRF并不常见,比起其他两种用户打开页面就中招的情况,这种需要用户点击链接才会触发
CSRF防护
- 验证Header中的Referer 确定来源域名
- 在CSP设置
- 页面头部增加meta标签
- a标签增加referrerpolicy属性
- 加入验证码
- CSRF Token
- 加自定义Header (和token类似)
- Chrome Cookie的Samesite属性设置 strict
Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Set-Cookie: baz=3