0


Java代码审计安全篇-SSRF(服务端请求伪造)漏洞

前言:

堕落了三个月,现在因为被找实习而困扰,着实自己能力不足,从今天开始 每天沉淀一点点 ,准备秋招 加油

注意:

本文章参考qax的网络安全java代码审计,记录自己的学习过程,还希望各位博主 师傅 大佬 勿喷,还希望大家指出错误

SSRF漏洞

SSRF(Server-side Request Forge, 服务端请求伪造)。
由攻击者构造的攻击链接传给服务端执行造成的漏洞,一般用来在外网探测或攻击内网服务。

危害:

1.获取内网主机、端口、banner信息

2.对内网的应用程序 进行攻击,例如Redis、jboos

3.file等伪协议读取文件

4.造成内网程序的溢出

SSRF审计函数

SSRF漏洞一般位于远程图片加载与下载、图片或文章收藏功能、URL分享、通过URL在线翻译、转码等功能点处。当然,SSRF是由发起网络请求的方法造成。代码审计时需要关注的发起HTTP请求的类及函数,部分如下:

HttpURLConnection. getInputStream
URLConnection. getInputStream
Request.Get. execute
Request.Post. execute
URL.openStream
ImageIO.read
OkHttpClient.newCall.execute
HttpClients. execute
HttpClient.execute
……

Java里面SSRF支持的协议:

https,https,file,ftp等

所以使得JAVA并不能像PHP中一样使用gopher 协议来拓展攻击面,gopher 协议在jdk8 中就被移除了

gopher协议在SSRF中使用可以看下面这篇文章

gopher 协议在SSRF 中的一些利用

我们直接进入Webgoat的靶场进行测试

点击第二关得到

根据提示我们输入 jerry

这时候就说明 传入的参数可控,产生了SSRF漏洞

我们看一下源代码

@RestController
@AssignmentHints({"ssrf.hint1", "ssrf.hint2"})
public class SSRFTask1 extends AssignmentEndpoint {

  @PostMapping("/SSRF/task1")
  @ResponseBody
  public AttackResult completed(@RequestParam String url) {
    return stealTheCheese(url);
  }

  protected AttackResult stealTheCheese(String url) {
    try {
      StringBuilder html = new StringBuilder();

      if (url.matches("images/tom\\.png")) {
        html.append(
            "<img class=\"image\" alt=\"Tom\" src=\"images/tom.png\" width=\"25%\""
                + " height=\"25%\">");
        return failed(this).feedback("ssrf.tom").output(html.toString()).build();
      } else if (url.matches("images/jerry\\.png")) {
        html.append(
            "<img class=\"image\" alt=\"Jerry\" src=\"images/jerry.png\" width=\"25%\""
                + " height=\"25%\">");
        return success(this).feedback("ssrf.success").output(html.toString()).build();
      } else {
        html.append("<img class=\"image\" alt=\"Silly Cat\" src=\"images/cat.jpg\">");
        return failed(this).feedback("ssrf.failure").output(html.toString()).build();
      }
    } catch (Exception e) {
      e.printStackTrace();
      return failed(this).output(e.getMessage()).build();
    }
  }
}

主要看下面几行代码

public AttackResult completed(@RequestParam String url) {
    return stealTheCheese(url);
  }
// completed() 方法使用 @PostMapping 注解标记,表示它处理HTTP POST请求,并且映射到路径 "/SSRF/task1"。该方法接受一个名为 "url" 的请求参数,类型为字符串。

意思就是接受url的参数 并映射到到路径 "/SSRF/task1

然后看下一句

 protected AttackResult stealTheCheese(String url) {
    try {
      StringBuilder html = new StringBuilder();
//stealTheCheese() 方法是一个受保护的方法,用于处理传入的URL并返回相应的结果。它接受一个名为 "url" 的字符串参数。

方法逻辑:stealTheCheese() 方法首先创建了一个 StringBuilder 对象 html,用于构建HTML响应。

就是很明显没有对这个url进行过滤处理等,然后 就直接进入下面的url匹配,

这段代码是一个简单的SSRF攻击任务处理器。它接受一个URL作为输入,并根据URL的不同返回不同的HTML响应。然而,代码中存在一些潜在的安全风险,因为它没有对传入的URL进行充分的验证和过滤,可能导致安全漏洞,如SSRF攻击。

我们接着看下一关

我们先点击看看会是啥样

我们还是根据提示进行输入

url=http://ifconfig.pro

验证成功

说明url参数可控,可以通过恶意语句进行对内网主机信息的获取

我们分析源代码

@RestController
@AssignmentHints({"ssrf.hint3"})
public class SSRFTask2 extends AssignmentEndpoint {

  @PostMapping("/SSRF/task2")
  @ResponseBody
  public AttackResult completed(@RequestParam String url) {
    return furBall(url);
  }

  protected AttackResult furBall(String url) {
    if (url.matches("http://ifconfig\\.pro")) {
      String html;
      try (InputStream in = new URL(url).openStream()) {
        html =
            new String(in.readAllBytes(), StandardCharsets.UTF_8)
                .replaceAll("\n", "<br>"); // Otherwise the \n gets escaped in the response
      } catch (MalformedURLException e) {
        return getFailedResult(e.getMessage());
      } catch (IOException e) {
        // in case the external site is down, the test and lesson should still be ok
        html =
            "<html><body>Although the http://ifconfig.pro site is down, you still managed to solve"
                + " this exercise the right way!</body></html>";
      }
      return success(this).feedback("ssrf.success").output(html).build();
    }
    var html = "<img class=\"image\" alt=\"image post\" src=\"images/cat.jpg\">";
    return getFailedResult(html);
  }

  private AttackResult getFailedResult(String errorMsg) {
    return failed(this).feedback("ssrf.failure").output(errorMsg).build();
  }
}

咱们主要关注下面两行代码

public AttackResult completed(@RequestParam String url) {
    return furBall(url);
  }completed() 方法使用 @PostMapping 注解标记,表示它处理HTTP POST请求,并且映射到路径 "/SSRF/task2"。该方法接受一个名为 "url" 的请求参数,类型为字符串。

  protected AttackResult furBall(String url) {

//furBall() 方法是一个受保护的方法,用于处理传入的URL并返回相应的结果。它接受一个名为 "url" 的字符串参数。

下面就是常规的正则匹配,总体而言,这段代码是另一个简单的SSRF攻击任务处理器。它接受一个URL作为输入,并尝试访问该URL获取HTML内容,并根据结果返回相应的响应。如果访问成功,则返回包含HTML内容的成功响应;如果访问失败,则返回一个包含特定错误消息的失败响应。

具体的JAVA中 SSRF漏洞可以访问

https://www.freebuf.com/vuls/293473.html

SSRF修复

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

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

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

4,黑名单内网ip,(正确判断内网IP,正确获取host)

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

6.正确处理302跳转

标签: java 代码复审

本文转载自: https://blog.csdn.net/m0_63138919/article/details/136662531
版权归原作者 文大。 所有, 如有侵权,请联系我们删除。

“Java代码审计安全篇-SSRF(服务端请求伪造)漏洞”的评论:

还没有评论