• 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漏洞

    我们看一下源代码

    1. @RestController
    2. @AssignmentHints({"ssrf.hint1", "ssrf.hint2"})
    3. public class SSRFTask1 extends AssignmentEndpoint {
    4. @PostMapping("/SSRF/task1")
    5. @ResponseBody
    6. public AttackResult completed(@RequestParam String url) {
    7. return stealTheCheese(url);
    8. }
    9. protected AttackResult stealTheCheese(String url) {
    10. try {
    11. StringBuilder html = new StringBuilder();
    12. if (url.matches("images/tom\\.png")) {
    13. html.append(
    14. "\"Tom\"
    15. + " height=\"25%\">");
    16. return failed(this).feedback("ssrf.tom").output(html.toString()).build();
    17. } else if (url.matches("images/jerry\\.png")) {
    18. html.append(
    19. "\"Jerry\"
    20. + " height=\"25%\">");
    21. return success(this).feedback("ssrf.success").output(html.toString()).build();
    22. } else {
    23. html.append("\"Silly");
    24. return failed(this).feedback("ssrf.failure").output(html.toString()).build();
    25. }
    26. } catch (Exception e) {
    27. e.printStackTrace();
    28. return failed(this).output(e.getMessage()).build();
    29. }
    30. }
    31. }

    主要看下面几行代码

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

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

    然后看下一句

    1. protected AttackResult stealTheCheese(String url) {
    2. try {
    3. StringBuilder html = new StringBuilder();
    4. //stealTheCheese() 方法是一个受保护的方法,用于处理传入的URL并返回相应的结果。它接受一个名为 "url" 的字符串参数。
    5. 方法逻辑:stealTheCheese() 方法首先创建了一个 StringBuilder 对象 html,用于构建HTML响应。

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

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

    我们接着看下一关

    我们先点击看看会是啥样

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

    url=http://ifconfig.pro

     验证成功

     

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

    我们分析源代码

    1. @RestController
    2. @AssignmentHints({"ssrf.hint3"})
    3. public class SSRFTask2 extends AssignmentEndpoint {
    4. @PostMapping("/SSRF/task2")
    5. @ResponseBody
    6. public AttackResult completed(@RequestParam String url) {
    7. return furBall(url);
    8. }
    9. protected AttackResult furBall(String url) {
    10. if (url.matches("http://ifconfig\\.pro")) {
    11. String html;
    12. try (InputStream in = new URL(url).openStream()) {
    13. html =
    14. new String(in.readAllBytes(), StandardCharsets.UTF_8)
    15. .replaceAll("\n", "
      "
      ); // Otherwise the \n gets escaped in the response
    16. } catch (MalformedURLException e) {
    17. return getFailedResult(e.getMessage());
    18. } catch (IOException e) {
    19. // in case the external site is down, the test and lesson should still be ok
    20. html =
    21. "Although the http://ifconfig.pro site is down, you still managed to solve"
    22. + " this exercise the right way!";
    23. }
    24. return success(this).feedback("ssrf.success").output(html).build();
    25. }
    26. var html = "\"image";
    27. return getFailedResult(html);
    28. }
    29. private AttackResult getFailedResult(String errorMsg) {
    30. return failed(this).feedback("ssrf.failure").output(errorMsg).build();
    31. }
    32. }

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

    1. public AttackResult completed(@RequestParam String url) {
    2. return furBall(url);
    3. }completed() 方法使用 @PostMapping 注解标记,表示它处理HTTP POST请求,并且映射到路径 "/SSRF/task2"。该方法接受一个名为 "url" 的请求参数,类型为字符串。
    4. protected AttackResult furBall(String url) {
    5. //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跳转 

     

     

  • 相关阅读:
    机器学习笔记只隐马尔可夫模型(三)求值问题——前向算法(Forward Algorithm)
    最新AIGC创作系统ChatGPT网站源码,Midjourney绘画系统,支持最新GPT-4-Turbo模型,支持DALL-E3文生图
    java线程生命周期
    4.开放-封闭原则
    Py2neo:一种快速导入百万数据到Neo4j的方式
    【MATLAB教程案例27】基于matlab的图像配准算法的仿真与分析——sift,surf,kaze等
    解锁前端Vue3宝藏级资料 第五章 Vue 组件应用 1( Props )
    Facebook又双叒崩了!网友:扎克伯格一周只用上三天班?
    命名空间和作用域
    请解释Java中的Hibernate框架
  • 原文地址:https://blog.csdn.net/m0_63138919/article/details/136662531