SSRF
SSRF是什么
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。
SSRF漏洞原理
可以理解为,服务器可以从其他的服务器获取信息。然而却没有对这个服务器的地址做限制
就比如说,我们可以指定一个有缺陷的url,或者自己的作为外部服务器。
SSRF漏洞挖掘
分享
通过URL分享网页的内容
转码
通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览:由于手机屏幕大小的关系,直接浏览网页内容的时候会造成许多不便,因此有些公司提供了转码功能,把网页内容通过相关手段转为适合手机屏幕浏览的样式。例如百度、腾讯、搜狗等公司都有提供在线转码服务
翻译
通过URL地址翻译对应文本的内容。提供此功能的国内公司有百度、有道
图片、文章收藏功能
图片、文章收藏中的文章收藏就类似于分享功能中获取URL地址中title以及文本的内容作为显示,目的还是为了更好的用户体验,而图片收藏就类似于功能四、图片加载。
http://title.xxx.com/title?title=http://title.xxx.com/as52ps63de
例如title参数是文章的标题地址,代表了一个文章的地址链接,请求后返回文章是否保存,收藏的返回信息。如果保存,收藏功能采用了此种形式保存文章,则在没有限制参数的形式下可能存在SSRF
未公开的api实现以及其他调用URL的功能
图片加载与下载
通过URL地址加载或下载图片,图片加载远程图片地址此功能用到的地方很多,但大多都是比较隐秘,比如在有些公司中的加载自家图片服务器上的图片用于展示
URL关键字中寻找
share
wap
url
link
src
source
target
u
display
sourceURl
imageURL
domain
产生SSRF的相关函数
PHP
file_get_contents
将整个文件读入到字符串
1
2
3
4
5
6
7
8
9
10
11
12<?php
if (isset($_POST['url']))
{
$content = file_get_contents($_POST['url']); //获取用户输入的url
$filename ='./images/'.rand().';img1.jpg'; //蒋文件储存为为一个
file_put_contents($filename, $content); //将获取的内容写入文件
echo $_POST['url']; //输出用户输入的url
$img = "<img src=\"".$filename."\"/>"; //输出图片
}
echo $img;
?>sockopen
以下代码使用fsockopen函数实现获取用户制定url的数据(文件或者html)。这个函数会使用socket跟服务器建立tcp连接,传输原始数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<?php
function GetFile($host, $port, $link)
{
$fp = fsockopen($host, intval($port), $errno, $errstr, 30); // 使用fsockopen函数建立与指定主机和端口的连接,设置超时时间为30秒
if (!$fp) {
echo "$errstr (错误号 $errno) \n"; // 如果连接失败,输出错误信息
} else {
$out = "GET $link HTTP/1.1\r\n"; // 构建HTTP GET请求头,使用HTTP/1.1协议,这对于保持连接很重要
$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; // 返回获取的内容
}
}curl_exec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<?php
if (isset($_POST['url']))
{
$link = $_POST['url'];
$curlobj = curl_init();
curl_setopt($curlobj, CURLOPT_POST, 0);
curl_setopt($curlobj,CURLOPT_URL,$link);
curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($curlobj);
curl_close($curlobj);
$filename = './curled/'.rand().'.txt';
file_put_contents($filename, $result);
echo $result;
}
?>curl_exec
关于curl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<?php
// 检查是否设置了POST请求中的'url'参数
if (isset($_POST['url'])) {
$link = $_POST['url']; // 获取POST请求中的'url'参数值
$curlobj = curl_init(); // 初始化一个cURL会话
curl_setopt($curlobj, CURLOPT_POST, 0); // 设置cURL请求为GET请求
curl_setopt($curlobj, CURLOPT_URL, $link); // 设置要访问的URL
curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1); // 设置cURL执行后不直接输出结果,而是返回到变量中
$result = curl_exec($curlobj); // 执行cURL请求并将结果保存到$result变量
curl_close($curlobj); // 关闭cURL会话
$filename = './curled/' . rand() . '.txt'; // 生成一个随机文件名
file_put_contents($filename, $result); // 将cURL获取的结果保存到文件中
echo $result; // 输出cURL获取的结果
}fsockopen
java
仅支持 HTTP/HTTPS 协议的类:HttpClient 类、HttpURLConnection 类、 OkHttp 类、 Request
类
支持 sun.net.www.protocol 所有协议的类:URLConnection 类、URL 类、ImageIO 类
SSRF中URL的伪协议
file:/// 从文件系统中获取文件内容,如,file:///etc/passwd
dict:// 字典服务器协议,访问字典资源,如,dict:///ip:6739/info:
sftp:// SSH文件传输协议或安全文件传输协议
ldap:// 轻量级目录访问协议
tftp:// 简单文件传输协议
gopher:// 分布式文档传递服务,可使用gopherus生成payload
SSRF漏洞利用(危害)
读取敏感文件
使用file协议读取文件内容
file://
本地文件传输协议,用于读取本地计算机里面的文件。
就像是使用win里面的打开或者右键打开
读取/etc/password
在Linux 中 /etc/passwd文件中每个用户都有一个对应的记录行,它记录了这个用户的一些基本属性。
系统管理员经常会接触到这个文件的修改以完成对用户的管理工作。
读取/etc/host
hosts文件主要作用是定义IP地址和主机名的映射关系,是一个映射IP地址和主机名的规定。可以用文
本文件打开!当用户在浏览器中输入一个网址时,系统会首先自动从hosts文件中寻找对应的IP地址,
一旦找到,浏览器会立即打开对应网页,如果没有找到,则浏览器会将网址提交DNS服务器进行IP地址解析。简单来说就是负责ip地址与域名快速解析的文件,读取文件可以得到内网所在网段。
可以理解为这个是本地的DNS解析器
探测内网的服务
使用dict协议
dict://
dict 协议是一个在线网络字典协议,这个协议是用来架设一个字典服务的。不过用的比较
少,所以网上基本没啥资料(包括谷歌上)。在SSRF漏洞利用中,常常用来探测内网的应用信息
攻击内网应用
通过dict://协议攻击redis
可以导致任意用户利用ssrf漏洞攻击内网中的未授权Redis以及读取Redis的数据。
攻击者在未授权访问Redis的情况下可以利用Redis的相关方法,如果运行 redis 的用户是 root 用户,攻击者可以通过写定时任务的方式进行反弹shell。
测试是否存在漏洞
dcit://ip:port/info
写定时任务
写定时任务的目录
centos,在/var/spool/cron/目录下
ubuntu 的定时任务在 /var/spool/cron/crontabs/ 目录下
可以根据服务器是否存在以下文件判断服务器的信息
# Centos
/etc/redhat-release
# Ubuntu
/etc/lsb-release
SSRF中url解码编码
HTTP
现在我们有一个url是:
如果现在xxx
里含有%xx
格式,这个数据先是被接受之后才会被解码
gopher
还是这个url
如果xxx里面含有%xx格式的数据,那么会在发送方就处理成接收方接受的数据
漏洞类型
有回显:页面有返回具体内容。
无回显:页面没有返回具体内容
SSRF利用
内网访问
ctfhub 技能树
伪协议读取文件
伪协议:
类型
file:///
dict://
sftp://
ldap://
tftp://
gopher://
这里使用ctfhub技能树的题做演示
file:///var/www/html/flag.php
注意这个是web目录
端口扫描
端口扫描使用的是dict://
协议
但是请你注意,我们使用dict扫描出端口之后,需要使用url直接访问,而不是继续使用dict协议
下面是做题逻辑,他说了端口在8000~9000,直接使用bp扫
访问:
http://challenge-a30959492eed8566.sandbox.ctfhub.com:10800/?url=127.0.0.1:8017
POST请求
这次还是使用ctfhub 的技能树作为例子
题目是:
这次是发一个HTTP POST请求.对了.ssrf是用php的curl实现的.并且会跟踪302跳转.加油吧骚年
要求我们发一个POST请求包,但是这个发包需要利用gopher协议
首先我们可以利用index.php的url访问flag.php和index.php
URL Bypass
ctfhub技能树里面的一道题
打开过后发现必须带有
这里我们需要知道一个东西
请求的都是192.168.0.1里面的内容
是所以我们直接构造
IP Bypass
这道题我觉得比较鸡贼,因为他会有到你想ip,ban掉了127/172
但是我们有一个回环地址localhost
所以直接构造poc
?url=localhost/flag.php
302跳转
不知道这个怎么回事,我尝试在http添加Localtion字段发现没有什么用,直接访问这个就没有问题
?url=localhost/flag.php
redis
使用ctfhub 进行演示
可以发现存在ssrf
然后尝试使用redis 对内网进行攻击
制作出webshell
然后尝试使用访问,会发现不行,得再次url 加密一下
然后访问
出现了504 但是不要紧
这个是时候shell.php 是已经写好的