SSRF漏洞讲解

2022-09-13 08:03:07 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

SSRF漏洞讲解

  • 一、初识SSRF漏洞
    • 1.定义
    • 2.产生原理
    • 3.会导致的危害
    • 4.常见产生SSRF的地方
    • 5.常见缺失函数
  • 二、SSRF漏洞利用
    • 1.函数
      • (1) file_get_contents
      • (2)fsockopen()
      • (3) curl_exec()
    • 2.协议
      • (1)file协议
      • (2)http协议
      • (3)dict协议
      • (4)gopher协议
  • 三、绕过
    • 1.绕过方式
      • (1)检查IP是否为内网IP
      • (2)Host获取与DNS绕过
      • (3)通过各种协议
      • (4)利用URL解析器滥用问题
  • 四、修复
    • 修复方案
  • 五、小结

一、初识SSRF漏洞

1.定义

SSRF漏洞(跨站服务器攻击)是一种在未能获取服务器权限时,利用服务器漏洞,由攻击者构造请求,服务器端发起请求的安全漏洞,攻击者可以利用该漏洞诱使服务器端应用程序向攻击者选择的任意域发出HTTP请求。 就相当于是你可以访问A网站,不可以访问B网站,A和B是都同一个服务器之下,通过服务器伪造命令,利用A网站的权限登录B网站。直接是SSRF漏洞最简单直接的理解,但是实现这个漏洞的过程还是很复杂的,需要用到代码审计也就是语言,这个也不是一定的,因为还是有一些个别的网站不是用JavaScript写的还是要针对不同的语言来找特殊的参数,尤其是在做白盒测试中,代码审计是很重要的。关键要看一些特征参数。

2.产生原理

很多web应用都提供了从其他的服务器上获取数据的功能。使用指定的URL,web应用便可以获取图片,下载文件,读取文件内容等。SSRF的实质是利用存在缺陷的web应用作为代理攻击远程和本地的服务器。一般情况下, SSRF攻击的目标是外网无法访问的内部系统,黑客可以利用SSRF漏洞获取内部系统的一些信息(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)。SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。

3.会导致的危害

从上面的示例代码可以看出,请求是从服务器发出的,那么攻击者可以通过构造恶意的url来访问原本访问不到的内网信息,攻击内网或者本地其他服务。这里根据后续处理逻辑不同,还会分为回显型ssrf和非回显型ssrf,所谓的回显型的ssrf就是会将访问到的信息返回给攻击者,而非回显的ssrf则不会,但是可以通过dns log或者访问开放/未开放的端口导致的延时来判断。 SSRF的最大的危害在于穿透了网络边界,但具体能做到哪种程度还需要根据业务环境来判断。例如我们在SSRF的利用中,如果需要更深一步扩展,第一反应通常是去攻击可利用的redis或者memcache等内网服务拿shell,但需要注意的是操作redis,memcache的数据包中是需要换行的,而http/https协议一般无法满足我们要求,所以即使内网存在可利用的redis,也并非所有的ssrf都能利用成功的。但是,对于memcache来说,即使只能使用https协议,利用memcache来getshell却并非不可能,本文会详细介绍一种新型的攻击方式。

4.常见产生SSRF的地方

平常在做渗透测试工作的过程中哪些地方容易产生SSRF漏洞,可以看到大部分相关资料都会显示,容易产生SSRF的地方在社交分享、图片加载、邮件系统、数据库等。为什么这些地方会出现呢,社交分享可能会分享到其他网址对吧,如果我们替换其网址为我们的本地地址呢,会出现什么样得情况?同一个地址更换不同的端口又会有什么不同,加载图片请求的服务器可能和你所访问的网站不是同一个服务器,这样是不是能探测内网的同一局域网段的情况呢,邮件系统也是同一道理,这些都是探测SSRF漏洞的手段。

5.常见缺失函数

二、SSRF漏洞利用

1.函数

(1) file_get_contents

这个函数的名称很简单 就是获取文件的参数 file_get_contents() 把整个文件读入一个字符串中。 该函数是用于把文件的内容读入到一个字符串中的首选方法

代码语言:javascript复制
<?php
echo file_get_contents("test.txt");
?>

输出:test.txt文本中所写的内容

(2)fsockopen()

这个函数的意思就是说可以从服务器获取用户的url数据 fsockopen函数实现获取用户制定url的数据(文件或者html)。这个函数会使用socket跟服务器建立tcp连接,传输原始数据。

代码语言:javascript复制
<?php
$fp = fsockopen("191.168.100.100", 80, &$errno, &$errstr, 10);
if(!$fp)
{ 
   
echo "$errstr ($errno)<br>n";
}
else { 
   
fputs($fp,"GET / HTTP/1.0nHost: 191.168.100.100nn");
while(!feof($fp)) { 
   
echo fgets($fp,128);
}
fclose($fp);
} ?>

(3) curl_exec()

执行一个curl会话 下面代码演示来源于菜鸟教程

代码语言:javascript复制
 <?php
// 创建一个cURL资源

$ch = curl_init();

// 设置URL和相应的选项
curl_setopt($ch, CURLOPT_URL, "http://www.w3cschool.cc/");
curl_setopt($ch, CURLOPT_HEADER, 0);

// 抓取URL并把它传递给浏览器
curl_exec($ch);

// 关闭cURL资源,并且释放系统资源
curl_close($ch);
?>

2.协议

(1)file协议

其实很简单看到file的就是读取文件 格式:file:///文件路径

(2)http协议

HTTP——(hypertext transfer protocol)超文本传输协议

GET——获取资源; POST——传输资源; PUT——更新资源; DELETE——删除资源; HEAD——获取报文首部;

(3)dict协议

这个协议主要是 数组的交互。是一种以键-值对形式存储数据的数据结构,就像电话号码簿中的名字和电话号码一样。这里的键是指你用来查找的东西,值是查找得到的结果

(4)gopher协议

gopher协议是一种信息查0找系统,他将Internet上的文件组织成某种索引,方便用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。利用此协议可以攻击内网的 Redis、Mysql、FastCGI、Ftp等等,也可以发送 GET、POST 请求。这拓宽了 SSRF 的攻击面.

三、绕过

1.绕过方式

(1)检查IP是否为内网IP

很多开发者认为,只要检查一下请求url的host不为内网IP,即可防御SSRF。

通常使用正则过滤以下5个IP段:

代码语言:javascript复制
192.168.0.0/16
​
10.0.0.0/8
​
172.16.0.0/12
​
127.0.0.0/8
​
0.0.0.0/8   #在Linux下,127.0.0.1与0.0.0.0都指向本地

这种通常可以用IP地址进制转换绕过

代码语言:javascript复制
利用八进制IP地址绕过 0177.0.0.1

利用十六进制IP地址绕过 0x7f000001

利用十进制的IP地址绕过 2130706433

(2)Host获取与DNS绕过

检查获取到的Host是否是内网IP防御SSRF 这种防御方法可以用DNS解析绕过 Host可能是IP形式,也可能是域名形式。 如果Host是域名形式,我们是没法直接比对的,只要其解析到内网IP上,就可以绕过。 网上有个神奇域名 http://xip.io (有墙),www.127.0.0.1.xip.io,会自动解析到127.0.0.1

(3)通过各种协议

GOPHER:通过GOPHER我们在一个URL参数中构造Post或者Get请求,从而攻击内网应用,例如Redis服务。 File:用File协议访问本地计算机中的文件,例如file:///etc/password.

(4)利用URL解析器滥用问题

某些情况下,后端程序可能会对访问的URL进行解析,对解析出来的host地址进行过滤。 这时候可能会出现对URL参数解析不当,导致可以绕过过滤 http://www.baidu.com@127.0.0.1 当后端程序通过不正确的正则表达式,对上述URL的内容解析的时候 会认为访问URL的host为www.baidu.com,而实际上请求的是127.0.0.1上的内容

四、修复

修复方案

SSRF的修复比较复杂,需要根据业务实际场景来采取不同的方案,例如前面说到的python中不同url库对url的解析就不一致,所以对于有条件的公司,建立一个代理集群是比较可靠的方案,将类似请求外部url的需求整理出来,分为纯外网集群和内网集群进行代理请求。 如果需要从代码层面来修复的话,需要注意一下几点:

  1. 去除url中的特殊字符
  2. 判断是否属于内网ip
  3. 如果是域名的话,将url中的域名改为ip
  4. 请求的url为3中返回的url
  5. 请求时设置host header为ip
  6. 不跟随30x跳转(跟随跳转需要从1开始重新检测) 其中第一步是为了防止利用url parse的特性造成url解析差异,第三步是为了防止dns rebinding,第5步是为了防止以ip请求时,某些网站无法访问的问题,第6步是为了防止30x跳转进行绕过。

五、小结

希望各位大佬指出错误,您的支持是给我的最大支持。小企鹅有义务提醒大家不可以利用技术做一些违法乱纪的事情,请熟悉了解《网络安全法》

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/152784.html原文链接:https://javaforall.cn

0 人点赞