Skip to content

Latest commit

 

History

History
205 lines (155 loc) · 13.7 KB

XSS & CSRF.md

File metadata and controls

205 lines (155 loc) · 13.7 KB

概览

  • XSS:XSS 全称是 Cross Site Scripting,为了与“CSS”区分开来,故简称 XSS,翻译过来就是“跨站脚本”。XSS 攻击是指黑客往 HTML 文件中或者 DOM 中注入恶意脚本,从而在用户浏览页面时利用注入的恶意脚本对用户实施攻击的一种手段。
  • CSRF: CSRF 英文全称是 Cross-site request forgery,所以又称为“跨站请求伪造”,是指黑客引诱用户打开黑客的网站,在黑客的网站中,利用用户的登录状态发起的跨站请求。简单来讲,CSRF 攻击就是黑客利用了用户的登录状态,并通过第三方的站点来做一些坏事
  • 中间人攻击:是指攻击者与通讯的两端分别创建独立的联系,在通讯中充当一个中间人角色对数据进行监听、拦截甚至篡改。
  • SQL注入:SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
  • DDoS 攻击:DDos 拒绝服务攻击(Denial of Service attack)是一种能够让服务器呈现静止状态的攻击方式。其原理就是发送大量的合法请求到服务器,服务器无法分辨这些请求是正常请求还是攻击请求,所以会照单全收。海量的请求造成服务器进入停止工作或拒绝服务的状态。
  • 上传文件限制:如果 web 网站没有对文件类型进行严格的校验,导致可执行文件被恶意上传到了服务器,恶意脚本就会执行
  • DNS 查询攻击:DNS 查询攻击就是攻击者通过精心构造 DNS报文 ,在 DNS 查询解析某个域名时,冒充真正的权威 DNS 做出回应,使得用户访问得到一个虚假响应。一旦本地接受了这个虚假响应并写入缓存,DNS 就会被攻击,用户也不清楚自己正在访问错误的地址或数据

XSS

Cross Site Scripting(跨站脚本攻击) 是指攻击者利用网站漏洞将代码注入到其他用户浏览器的攻击方式,又叫跨域脚本。常见类型有:反射型(非持久性)存储型(持久性)DOM 型

同源策略可以隔离各个站点之间的 DOM 交互、页面数据和网络通信。

支持页面中的第三方资源引用和 CORS 也带来了很多安全问题,其中最典型的就是 XSS 攻击。

类型

反射型(非持久性)

原理:攻击者通过在 URL 插入恶意代码,其他用户访问该恶意链接时,服务端在URL 取出恶意代码后拼接至 HTML 中返回给用户浏览器。

要点:
通过 URL 插入恶意代码。
有服务端参与。
需要用户访问特定链接。

例子:
攻击者诱导被害者打开链接hzfe.org?name=<script src="http://a.com/attack.js"/>。被攻击网站服务器收到请求后,未经处理直接将 URL 的 name 字段直接拼接至前端模板中,并返回数据。被害者在不知情的情况下,执行了攻击者注入的脚本(可以通过这个获取对方的Cookie 等)。

存储型(持久性)

原理:攻击者将注入型脚本提交至被攻击网站数据库中,当其他用户浏览器请求数据时,注入脚本从服务器返回并执行。

要点:
恶意代码存储在目标网站服务器上。
有服务端参与。
只要用户访问被注入恶意脚本的页面时,就会被攻击。

例子:
攻击者在目标网站留言板中提交了<script src="http://a.com/attack.js"/>。目标网站服务端未经转义存储了恶意代码,前端请求到数据后直接通过innerHTML 渲染到页面中。其他用户在访问该留言板时,会自动执行攻击者注入脚本。

DOM 型

原理:
攻击者通过在 URL 插入恶意代码,客户端脚本取出 URL 中的恶意代码并执行。

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

要点:
在客户端发生。

例子:
攻击者诱导被害者打开链接hzfe.org?name=<script src="http://a.com/attack.js"/>。被攻击网站前端取出 URL 的 name 字段后未经转义直接通过 innerHTML 渲染到页面中。被害者在不知情的情况下,执行了攻击者注入的脚本。

总结

存储型 XSS: 持久化,代码是存储在服务器中的

反射型 XSS: 非持久化,需要欺骗用户自己去点击链接才能触发 XSS 代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面

基于 DOM 的 XSS: 不经过后端,纯粹发生在客户端的攻击,属于前端 JavaScript 自身的安全漏洞

防范 XSS

  • 对于外部传入的内容进行充分转义。过滤特殊字符,或对特定字符进行编译转码

  • 开启 CSP(Content Security Policy,内容安全策略),规定客户端哪些外部资源可以加载和执行,降低 XSS 风险。

  • 设置 Cookie httpOnly 属性,禁止 JavaScript 读取 Cookie 防止被窃取。对重要的 cookie 设置 httpOnly

    • HttpOnly 最早由微软提出,至今已经成为一个标准。
    • 通过对重要的 Cookie 设置 httpOnly ,防止客户端通过 document.cookie 读取 cookie ,也就是说,JavaScript 读取不到此条 Cookie ,也就无法提交给恶意服务器了
    • 注意:此 HTTP 头由服务端设置
  • URLEncode 操作

    • 将不可信的值输出 URL参数之前,进行 URLEncode操作。对于从 URL 参数中获取值一定要进行格式检测(比如你需要的时URL,就判读是否满足URL格式)
  • Web 安全头支持 浏览器自带的防御能力,一般是通过开启 Web 安全头生效的。具体有以下几个:

    • CSP :W3C 的 Content Security Policy,简称 CSP,主要是用来定义页面可以加载哪些资源,减少 XSS 的发生。要配置 CSP , 需要对 CSP 的 policy 策略有了解,具体细节可以参考 CSP 是什么。
    • X-Download-Options: noopen :默认开启,禁用 IE 下下载框 Open 按钮,防止 IE 下下载文件默认被打开 XSS。
    • X-Content-Type-Options: nosniff :禁用 IE8 自动嗅探 mime 功能例如 text/plain 却当成 text/html 渲染,特别当本站点 server 的内容未必可信的时候。
    • X-XSS-Protection :IE 提供的一些 XSS 检测与防范,默认开启

Cross-site request forgery(CSRF)

案例

一个真实的案例:用户 David 在自己邮箱内点击了黑客恶意伪装的链接。黑客在点击的链接里冒充用户(cookie)向 Gmail 服务器发送邮件自动转发请求,导致 David 的邮件都被自动转发到了黑客的邮箱,从而被黑客利用盗取了用户数据。

原理

原理:攻击者诱导受害者进入第三方网站,在第三方网站中向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的身份凭证,达到冒充用户对被攻击的网站执行某项操作的目的。

要点:

  • 利用浏览器在发送 HTTP 请求时会自动带上 Cookie 的原理,冒用受害者身份请求。
  • 攻击一般发生在第三方网站上。
  • 攻击者只能“冒用”受害者的身份凭证,并不能获取。
  • 跨站请求有多种方式,常见的有图片 URL、超链接、Form 提交等。

CSRF 常见的攻击方式与防护策略

常见的攻击方式:

  • 自动发起 GET 请求的 CSRF
  • 自动发起 POST 请求的 CSRF
  • 引诱用户点击链接的 CSRF
  1. 自动发起 Get 请求
    GET类型的CSRF利用非常简单,只需要一个HTTP请求,一般会这样利用:
 ![](https://awps-assets.meituan.net/mit-x/blog-images-bundle-2018b/ff0cdbee.example/withdraw?amount=10000&for=hacker)

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

  1. 自动发起 POST 请求
    这种类型的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>

访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作。
POST类型的攻击通常比GET要求更加严格一点,但仍并不复杂。任何个人网站、博客,被黑客上传页面的网站都有可能是发起攻击的来源,后端接口不能将安全寄托在仅允许POST上面。

  1. 引诱用户点击链接
    链接类型的CSRF并不常见,比起其他两种用户打开页面就中招的情况,这种需要用户点击链接才会触发。这种类型通常是在论坛中发布的图片中嵌入恶意链接,或者以广告的形式诱导用户中招,攻击者通常会以比较夸张的词语诱骗用户点击,例如:
  <a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">
  重磅消息!!
  <a/>

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

CSRF 攻击的两个必要条件:

1. 目标站点一定要有 CSRF 漏洞;
2. 诱导用户从目标网站,打开一个第三方站点。

CSRF通常从第三方网站发起,被攻击的网站无法防止攻击发生,只能通过增强自己网站针对CSRF的防护能力来提升安全性。

上文中讲了CSRF的两个特点:

CSRF(通常)发生在第三方域名。 CSRF攻击者不能获取到Cookie等信息,只是使用。 针对这两点,我们可以专门制定防护策略,如下:

  • 阻止不明外域的访问
    • 同源检测
    • Samesite Cookie
  • 提交时要求附加本域才能获取的信息
    • CSRF Token
    • 双重Cookie验证

防范:

  1. 使用 CSRF Token 验证用户身份 原理:服务端生成 CSRF Token (通常存储在 Session 中),用户提交请求时携带上 Token,服务端验证 Token 是否有效。 优点:能比较有效的防御 CSRF (前提是没有 XSS 漏洞泄露 Token)。 缺点:大型网站中 Session 存储会增加服务器压力,且若使用分布式集群还需要一个公共存储空间存储 Token,否则可能用户请求到不同服务器上导致用户凭证失效;有一定的工作量。
  2. 双重 Cookie 验证(Cookie Hashing) 原理:利用攻击者不能获取到 Cookie 的特点,在 URL 参数或者自定义请求头上带上 Cookie 数据,服务器再验证该数据是否与 Cookie 一致。 优点:无需使用 Session,不会给服务器压力。
  3. 设置 Cookie 的 SameSite 属性可以用来限制第三方 Cookie 的使用,可选值有 Strict、Lax、None。(SameSite Cookie) Strict:完全禁止第三方 Cookie。 Lax:只允许链接、预加载请求和 GET 表单的场景下发送第三方 Cookie。 None:关闭 SameSite 属性。 设置为 Lax 或者 Strict,禁止发送第三方 Cookie。
  4. 设置白名单,仅允许安全域名请求
  5. 增加验证码验证:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,这个方案可以完全解决CSRF
  6. One-Time Tokens(不同的表单包含一个不同的伪随机值)

在实现One-Time Tokens时,需要注意一点:并行会话的兼容。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。

中间人攻击(MITM)

中间人攻击是一种通过各种技术手段入侵两台设备通信的网络攻击方法

成功的中间人攻击主要有两个不同的阶段:拦截和解密。

中间人攻击防范

  • 对于开发者来说:
    • 支持 HTTPS。
    • 开启 HSTS 策略。
  • 对于用户来说:
    • 尽可能使用 HTTPS 链接。
    • 避免连接不知名的 WiFi 热点。
    • 不忽略不安全的浏览器通知。
    • 公共网络不进行涉及敏感信息的交互。
    • 用可信的第三方 CA 厂商,不下载来源不明的证书。

SQL注入

案例

一般我们提交的表单数据(未经过滤的情况下)都会拼接到 SQL 查询语句中的,就例如:

SELECT * FROM users WHERE name='aaa'

其中 name 的参数就是从表单中传过来的数据,如果传的参数是一条 SQL 语句,那么就可能骗过了 SQL 数据库,从而执行了一段恶意的代码,达到了攻击效果。

防范

  • 把应用服务器的数据库权限降至最低,尽可能地减少 SQL 注入攻击带来的危害。

  • 避免网站打印出SQL错误信息,比如类型错误、字段不匹配等,把代码里的SQL语句暴露出来,以防止攻击者利用这些错误信息进行SQL注入。

  • 对进入数据库的特殊字符('"\尖括号&*;等)进行转义处理,或编码转换。

  • 所有的查询语句建议使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中,即不要直接拼接SQL语句。

  • 在测试阶段,建议使用专门的 SQL 注入检测工具进行检测。网上有很多这方面的开源工具,例如sqlmap、SQLninja等。

  • 善用数据库操作库,有些库包可能已经做好了相关的防护,只需阅读其文档,看是否支持相应的功能即可。