OWASP TOP10

作者 ro0t 于 2021-06-01 发布
预计阅读所需时间 12 分钟
3.2k

OWASP TOP10

SQL注入

CSRF

CSRF(Cross-Site Request Forgery)跨站请求伪造。旨在冒用用户身份发起请求。

利用原理

  1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
  2. 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
  3. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
  4. 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
  5. 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

防御方式:

  1. 严格校验referer
  2. GET转POST,同时添加并校验token

拓展:

token 怎么设计?

  • token不宜过长
  • token应与当前用户身份绑定,且验证完应立即失效
  • token应动态生成,本身应有固定的生命周期,不能长久有效

Referer 是个什么东西?

referer字段用来告诉服务器,用户的来源。referer就是一个URL,有可能是内网的URL,也有可能是功能URL,因此,为了隐私考虑,referer有时候需要发送,有时候不需要发送。

Referer作用

  • 页面统计
  • 防盗链
    • http请求发给服务器后,如果服务器要求必须是某个地址或者某几个地址才能访问,而你发送的referer不符合他的要求,就会拦截或者跳转到他要求的地址,然后再通过这个地址进行访问

Referer发送的场景

  • 用户点击网页上的链接
  • 用户发送表单
  • 网页加载静态资源,比如图片、脚本、样式

浏览器会将当前网址作为Referer字段放在Header头里发送。

Referer不发送的场景

  • https跳转到http

  • 直接在浏览器中输入URL

  • 从收藏夹访问

  • 单击「主页」或自定义的地址

  • 用js来打开,如:window.openlocation.hreflocation.replace

  • Referer Policy的值

    • no-referer

      不发送referer

    • no-referer-when-downgrade

      httpshttp,不发送referer,其他情况则发送,这是浏览器的默认行为。

    • same-origin

      链接到同源(协议、域名、端口)地址时发送,否则不发送。注意:httpshttp也属于跨域。

    • origin

      referer字段一律只发送源信息(协议、域名、端口),不管是否跨域。

    • strict-origin

      如果从 HTTPS 网址链接到 HTTP 网址,不发送Referer字段,其他情况只发送源信息。

    • origin-when-cross-origin

      同源时,发送完整的Referer字段,跨域时发送源信息。

    • strict-origin-when-cross-origin

      同源时,发送完整的Referer字段;跨域时,如果 HTTPS 网址链接到 HTTP 网址,不发送Referer字段,否则发送源信息。

    • unsafe-url

      Referer字段包含源信息、路径和查询字符串,不包含锚点、用户名和密码。

  • Referer Policy用法

    • HTTP头信息

      1
      Referer-Polify: origin
    • <meta>标签

      1
      <meta name="referer" content="origin">
    • refererpolicy属性

      <a><area><img><iframe><link>标签,可以设置referrerpolicy 属性

      1
      <a href="xxx" refererpolicy="origin" target="_blank">xxx</a>

XSS

SSRF

定义

SSRF,服务端请求伪造(Server-side Request Forge)的缩写。产生的原因是服务端提供了从其他服务器获取数据的功能,但没有对地址和协议等做过滤与限制。常见的一个场景就是:服务器通过用户输入的 URL 来获取图片。这个功能如果被恶意使用,可以利用存在缺陷的 Web 应用作为跳板来攻击远程和本地的服务器。

分类

ssrf 主要分为:

  1. 回显型 ssrf
  2. 无回显型 ssrf

​ 有回显型的 ssrf 就是会将访问到的信息返回给攻击者,而无回显的 ssrf 则不会,但是可以通过带外通道(比如 dnslog)或者 访问开放/未开放的端口导致的延时来判断。

利用方式

伪协议 - gopher://

gopher协议是一个在http 协议诞生前用来访问Internet 资源的协议可以理解为http 协议的前身或简化版,虽然很古老但现在很多库还支持gopher 协议而且gopher 协议功能很强大。也被称为「万金油」。

它可以实现多个数据包整合发送,然后gopher服务器将多个数据包捆绑着发送到客户端,这就是它的菜单响应。比如使用一条gopher 协议的curl 命令就能操作mysql 数据库或完成对redis 的攻击等等。

gopher 协议使用tcp 可靠连接。

协议格式

1
gopher://<host>:<port>/<gopher-path>

默认端口70

如果发起post请求,回车换行需要使用%0d%0a,如果多个参数,参数之间的&也需要进行URL编码

gopher的使用限制:

语言 限制
php –write-curlwrappers 且 php 版本至少为 5.3
Java < jdk1.7
curl 低版本不支持
perl 支持
asp.net <版本3
  • gopher发送get请求

    本地使用nc测试:两个终端,见图:

    image-20210529144759385

    可以发现,第一个s是不会发送过去的,这是gopher协议的特性,只需要在使用gopher协议时在url后加入一个字符(该字符可随意写)即可。

  • gopher发送post请求

需要注意:

  1. gopher 协议的默认端口为 70
  2. 分隔符后面的 TCP/IP 数据就是发出去的数据,数据部分如果有特殊字符必须要进行 url 编码,这样 gopher 协议才能正确解析
  3. 大部分 PHP 并不会开启 fopen 的 gopher wrapper
  4. PHP file_get_contents 的 gopher 协议不能 URLencode
  5. PHP file_get_contents 的 gopher 协议的 302 跳转有 bug,导致利用失败
  6. PHP 的 curl 默认不跟随 302 跳转
  7. curl/libcurl v7.43 上 gopher 协议存在 %00 截断,v7.49 可用

利用案例

可见ssrf + redis利用方式

伪协议 - dict://

dict协议指词典网络协议,允许客户端在使用过程中访问更多字典。

默认端口2628

协议格式

1
dict://serverip:port/命令:参数

dict特性

  • 向服务器的端口请求为「命令:参数」,并在末尾自动补上\r\n,方便漏洞利用
  • 通过dict协议,指令需要一条一条执行,而gopher协议执行一条命令即可

利用案例

可见ssrf + redis利用方式

伪协议 - file://

file协议主要用于访问本地计算机中的文件。格式为:

1
file://文件路径

file 和 http协议的区别?

  • file协议主要用于读取服务器本地文件,访问的是本地的静态资源
  • http是访问本地的html文件,相当于把本机当作http服务器,通过http访问服务器,服务器再去访问本地资源。简单来说file只能静态读取,http可以动态解析
  • http服务器可以开放端口,让他人通过http访问服务器资源,但file不可以
  • file对应的类似http的协议是ftp协议(文件传输协议)
  • file不能跨域

伪协议 - ldap://

伪协议 - data://

伪协议 - rmi://

常见绕过技巧

  1. 利用伪协议
  2. 添加端口可能绕过匹配正则:http://127.0.0.1/ 改为 http://127.0.0.1:80/
  3. 127.0.0.1 与 localhost 在大部分情况下都是等价的
  4. 利用 IPv6:http://[::]:80/ 相当于 http://127.0.0.1
  5. 利用 @ 可能绕过域名限定的正则:http://example.com@127.0.0.1 相当于 http://127.0.0.1
  6. 利用进制:以 127.0.0.1 为例,首先,ip 可以没 .,比如 2130706433(十进制),0x7F000001(十六进制);也可以有 .,比如 0x7F.0x000.0x001(十六进制)、0177.0000.0001(八进制),甚至可以混用,比如 0x7F.000.0x001(十六进制 加 十进制);还可以合并,127.0.0.1 == 127.0.1 == 127.1127.3.2.1 == 127.3.513 == 127.3.513 == 127.197121,注意这个合并注意只能从前到后合并,具体的计算方式,可以按照 . 分割,分别先转为 8 位二进制,然后从左到右每段直接拼在一起,最后再转为十进制或者十六进制即可,有一个比较特殊的是 00.0.0.0 == 0.0.0 == 0.0 == 0,即目标服务器监听了 0.0.0.0 的服务都可以用此方法访问到。以上这几种方式可以随意组合搭配,而且其实各个进制的补 0 可以填很多个:127.0.0000000000000000000000000000000000.1
  7. 利用跳转:比如,利用短链,http://dlj.bz/kA47FD 相当于 http://127.0.0.1,本质上是利用 301 跳转,所以完全可以自己打一个 301 跳转,想怎么跳就怎么跳,别忘记同时还可以转换协议:Location: file:///etc/passwd。状态码可以是 301、302、307
  8. 利用域名 A 记录:http://localhost.tr0y.wang/, 在域名上设置 A 记录,指向 127.0.0.1。如果你实在懒,可以用 xip.io/xip.name,它的子域名前缀就是解析的 ip 地址,比如 127.0.0.1.xip.io 的 A 记录就是 127.0.0.1
  9. 利用 IDN,ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ 等于 example.com127。0。0。1 相当于 127.0.0.1
  10. CRLF 头注入:比较经典的就是 Python 的 CVE,由于允许 \r\n 的存在,大大提升了通过 http:// 协议来利用的 ssrf 的杀伤力
  11. DNS 重绑定攻击:可见:https://www.tr0y.wang/2020/11/02/DNS-3-attack-by-dns/#DNS-重绑定攻击
    这个和「域名A记录」很像,但是DNS重绑定的优势是,有些 SSRF 防御策略的第一步是先提取域名,然后解析一下看 ip 是不是内网 ip,但是到最后发起请求的时候依旧用的是域名,第一次不是内网,再次发起请求的时候,就是内网了。可以绕过不规范的SSRF防御策略。

防御方式

明确此类功能的流程

  1. 提取 URL 的域名
  2. 解析 Host 的 ip
  3. 发出请求
  4. 如果有跳转,取出 Location URL,回到第 1 步;否则继续下一步
  5. 发出最终的请求,实现业务逻辑

需要注意

  1. 过滤返回的信息/统一错误信息:将有回显变成无回显,提升利用难度(比如 file:// 就直接废掉了)
  2. 限制请求的 ip 和端口:一般的业务禁掉私有 ip 完全可行;限制端口可有效降低攻击面
  3. 去除 URL 中的特殊字符:防止因为 url 解析模块造成的问题,往往是 host 提取解析结果存在问题(强烈建议阅读 资料 1)
  4. 只允许 http 协议,必要时强制使用 https 协议,可以很大程度提升攻击难度,因为 SSL/TLS 握手过程无法完成(骚操作请参考 资料 2)
  5. 解析/跳转(没必要就别跟随跳转了)后一定要进行检查:防止利用各种形式的 ip、跳转绕过
  6. 完善正则表达式:这个没啥通用的技巧,根据具体的业务需求定,需要经过完善测试(限制 @ 的使用、防止用子域名前缀绕过等等)
  7. 最后真正发起请求去获取资源的时候,可以把域名替换成第之前就已经解析的结果,这样来避免重复解析带来的 DNS 重绑定攻击问题。
  8. 可以考虑建立一个发起请求的代理集群。外网代理集群专门用于业务对外网发起请求;另一个代理集群专门用于业务对内网发起请求。然后在网络层面上保证外网代理集群无法与内网直接互通。

资料

  1. SSRF利用新纪元:
  1. SSRF 遇到 TLS 的利用方式:
  1. 猪猪侠在乌云大会上关于 ssrf 的分享:

如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !