SSRF攻击

SSRF(Server-Side Request Forgery)是一种通过构造请求,由目标系统服务端发起请求的安全漏洞。SSRF攻击可被用于非法访问内网地址,甚至直接访问被攻击主机的文件内容,通常都有较大危害。

SSRF攻击的典型场景

可能存在SSRF漏洞的系统通常具备这样的特点:支持用户输入一个URL地址,服务端接收URL并根据它请求数据,最后将获得的数据进一步处理或是直接返回给用户。举例来说,如果服务端存在接收类似这种请求参数的功能:http://127.0.0.1/getFileData?url=http%3A%2F%2F192.168.1.101%2Ffiles%2F1.jpg,那么就有可能存在SSRF漏洞!攻击者可能会精心构造URL参数,来用HTTP、FTP等协议非法访问内网资源,或是使用File协议访问主机上的文件。

补充知识:URL全名为统一资源定位符,除了HTTP外还支持许多种协议,各类编程语言对URL协议的支持可能各不相同,例如Java的URL类支持httphttpsftpfilegopher协议等。

SSRF漏洞代码示例

下面是使用SpringBoot编写的例子程序,其中/getFileData接口接收urlBase64参数,它是一个URL地址(为了方便作为GET参数而进行了Base64编码),服务端程序接收到请求后会读取URL地址的内容并返回给客户端。然而实际上该接口存在严重漏洞,攻击者构造一个读取file协议的请求就可以读取主机上的文件。

package com.gacfox.demo.demoboot;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;

@Controller
public class DemoController {
    @GetMapping("/getFileData")
    public void getFileData(String urlBase64, HttpServletResponse httpServletResponse) {
        try {
            Base64 base64 = new Base64();
            String urlStr = new String(base64.decode(urlBase64), StandardCharsets.UTF_8);
            URL url = new URL(urlStr);
            URLConnection urlConnection = url.openConnection();
            urlConnection.connect();
            try (InputStream inputStream = urlConnection.getInputStream();
                 ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream()) {
                IOUtils.copy(inputStream, servletOutputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

构造攻击请求的思路如下:

  1. 假设我们要读取的文件为D://flag.txt,其对应file协议写法为:file:///d:/flag.txt
  2. file:///d:/flag.txt按服务端的处理格式进行Base64编码:ZmlsZTovLy9kOi9mbGFnLnR4dA==
  3. 使用构造的请求调用/getFileData接口:http://localhost:8080/getFileData?urlBase64=ZmlsZTovLy9kOi9mbGFnLnR4dA==

此时我们就可以读取到主机上的文件了。

防御SSRF攻击

SSRF漏洞主要是由于后端开发人员缺乏安全意识造成的,我们编写类似功能时,需要注意以下几点:

  1. 白名单方式限制协议,比如只允许HTTP协议,禁用File等协议
  2. 对访问的内网地址进行白名单处理,禁止访问不在白名单内的系统
  3. 使用其它参数传递方式,比如接入系统提供一个token参数,目标系统再根据token向接入系统请求URL地址,禁止用户随意构造URL地址
作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap