2025第十届 “磐石行动” java题目
字数 848 2025-09-23 19:27:38

2025第十届 "磐石行动" Java题目分析与利用

题目概述

这道Java题目包含两个部分:web-jaba_ezweb_ezyaml。主要考察Java安全相关的知识,包括反射调用、黑名单/白名单绕过、表达式注入等漏洞利用技术。

web-jaba_ez题目分析

漏洞点分析

题目提供了两个主要端点:

  1. /job/add - 添加任务
  2. /job/run/{jobName} - 执行任务

关键代码逻辑

@PostMapping({"/job/add"})
public Map<String, Object> addJob(@RequestBody ScheduledJob job) {
    Map<String, Object> result = new HashMap<>();
    if (containsBlacklist(job.getInvokeTarget())) {
        result.put(BindTag.STATUS_VARIABLE_NAME, "error");
        result.put("message", "包含非法字符");
        return result;
    }
    if (!containsWhitelist(job.getInvokeTarget())) {
        result.put(BindTag.STATUS_VARIABLE_NAME, "error");
        result.put("message", "目标不在白名单中");
        return result;
    }
    jobs.put(job.getJobName(), job);
    result.put(BindTag.STATUS_VARIABLE_NAME, "success");
    result.put("message", "任务添加成功");
    result.put("jobId", job.getJobName());
    return result;
}

@PostMapping({"/job/run/{jobName}"})
public Map<String, Object> runJob(@PathVariable String jobName) {
    Map<String, Object> result = new HashMap<>();
    ScheduledJob job = jobs.get(jobName);
    if (job == null) {
        result.put(BindTag.STATUS_VARIABLE_NAME, "error");
        result.put("message", "任务不存在");
        return result;
    }
    try {
        invokeMethod(job.getInvokeTarget());
        result.put(BindTag.STATUS_VARIABLE_NAME, "success");
        result.put("message", "任务执行成功");
    } catch (Exception e) {
        result.put(BindTag.STATUS_VARIABLE_NAME, "error");
        result.put("message", e.getMessage());
        result.put("stackTrace", e.getStackTrace()[0].toString());
    }
    return result;
}

黑名单与白名单机制

private static final String[] JOB_BLACKLIST = {
    "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", 
    "org.springframework", "org.apache", "rmi", "ldap", "ldaps", "http", "https"
};
private static final String[] JOB_WHITELIST = {"com.jabaez.FLAG"};

private boolean containsBlacklist(String str) {
    if (str == null) {
        return false;
    }
    String lowerStr = str.toLowerCase();
    for (String blackItem : JOB_BLACKLIST) {
        if (lowerStr.contains(blackItem.toLowerCase())) {
            return true;
        }
    }
    return false;
}

private boolean containsWhitelist(String str) {
    if (str == null) {
        return false;
    }
    for (String whiteItem : JOB_WHITELIST) {
        if (str.contains(whiteItem)) {
            return true;
        }
    }
    return false;
}

方法调用逻辑

private Object invokeMethod(String invokeTarget) throws Exception {
    int hashIndex = invokeTarget.indexOf(35); // #字符
    if (hashIndex == -1) {
        throw new IllegalArgumentException("Invalid format, expected: className#methodName(params)");
    }
    String className = invokeTarget.substring(0, hashIndex);
    String methodAndParams = invokeTarget.substring(hashIndex + 1);
    int paramStart = methodAndParams.indexOf(40); // (字符
    int paramEnd = methodAndParams.lastIndexOf(41); // )字符
    if (paramStart == -1 || paramEnd == -1) {
        throw new IllegalArgumentException("Invalid method format");
    }
    String methodName = methodAndParams.substring(0, paramStart);
    String paramStr = methodAndParams.substring(paramStart + 1, paramEnd);
    
    Class<?> clazz = Class.forName(className);
    List<Object> paramValues = new ArrayList<>();
    List<Class<?>> paramTypes = new ArrayList<>();
    
    if (!paramStr.trim().isEmpty()) {
        String[] params = splitParams(paramStr);
        for (String str : params) {
            String param = str.trim();
            if (param.startsWith("'") && param.endsWith("'")) {
                String value = param.substring(1, param.length() - 1);
                paramValues.add(value);
                paramTypes.add(String.class);
            } else if (param.equals(BeanDefinitionParserDelegate.NULL_ELEMENT)) {
                paramValues.add(null);
                paramTypes.add(String.class);
            } else if (param.matches("\\d+")) {
                paramValues.add(Integer.valueOf(Integer.parseInt(param)));
                paramTypes.add(Integer.TYPE);
            } else if (param.equals("true") || param.equals("false")) {
                paramValues.add(Boolean.valueOf(Boolean.parseBoolean(param)));
                paramTypes.add(Boolean.TYPE);
            } else {
                paramValues.add(param);
                paramTypes.add(String.class);
            }
        }
    }
    
    try {
        Method method = clazz.getMethod(methodName, (Class[]) paramTypes.toArray(new Class[0]));
        if (Modifier.isStatic(method.getModifiers())) {
            return method.invoke(null, paramValues.toArray());
        }
        Object instance = clazz.newInstance();
        return method.invoke(instance, paramValues.toArray());
    } catch (NoSuchMethodException e) {
        Method method2 = clazz.getDeclaredMethod(methodName, (Class[]) paramTypes.toArray(new Class[0]));
        method2.setAccessible(true);
        if (Modifier.isStatic(method2.getModifiers())) {
            return method2.invoke(null, paramValues.toArray());
        }
        Object instance2 = clazz.newInstance();
        return method2.invoke(instance2, paramValues.toArray());
    }
}

利用思路

  1. 黑名单绕过:需要绕过包含java.net.URL, javax.naming.InitialContext等危险类的检测
  2. 白名单满足:必须包含com.jabaez.FLAG
  3. 方法调用:可以通过反射调用任意类的任意方法(包括私有方法)

官方解法

上传一个.so文件,然后使用System.load进行加载

替代解法

使用EL表达式注入反弹shell:

  1. 构造一个包含com.jabaez.FLAG但不触发黑名单的类名
  2. 调用能够执行命令的方法
  3. 通过反射机制执行任意代码

具体利用步骤

  1. 构造一个合法的类名,如com.jabaez.FLAG${恶意代码}
  2. 利用反射调用能够执行命令的方法
  3. 绕过黑名单检测(大小写、编码等方式)
  4. 通过EL表达式注入执行系统命令

web_ezyaml题目分析

这是一个简单的YAML反序列化题目,主要考察:

  1. JNDI注入
  2. YAML反序列化漏洞利用
  3. 反序列化链构造

利用思路

  1. 构造恶意的YAML payload
  2. 利用SnakeYAML的反序列化特性
  3. 通过JNDI注入实现RCE

总结

这道题目综合考察了以下Java安全知识:

  1. Java反射机制的安全风险
  2. 黑名单/白名单绕过的技巧
  3. 表达式注入漏洞
  4. 反序列化漏洞利用
  5. JNDI注入攻击

关键点在于理解反射调用的危险性,以及如何绕过安全限制执行任意代码。通过分析黑名单和白名单的限制,找到合适的类和方法进行利用,最终实现命令执行或反弹shell。

2025第十届 "磐石行动" Java题目分析与利用 题目概述 这道Java题目包含两个部分: web-jaba_ez 和 web_ezyaml 。主要考察Java安全相关的知识,包括反射调用、黑名单/白名单绕过、表达式注入等漏洞利用技术。 web-jaba_ ez题目分析 漏洞点分析 题目提供了两个主要端点: /job/add - 添加任务 /job/run/{jobName} - 执行任务 关键代码逻辑 黑名单与白名单机制 方法调用逻辑 利用思路 黑名单绕过 :需要绕过包含 java.net.URL , javax.naming.InitialContext 等危险类的检测 白名单满足 :必须包含 com.jabaez.FLAG 方法调用 :可以通过反射调用任意类的任意方法(包括私有方法) 官方解法 上传一个.so文件,然后使用 System.load 进行加载 替代解法 使用EL表达式注入反弹shell: 构造一个包含 com.jabaez.FLAG 但不触发黑名单的类名 调用能够执行命令的方法 通过反射机制执行任意代码 具体利用步骤 构造一个合法的类名,如 com.jabaez.FLAG${恶意代码} 利用反射调用能够执行命令的方法 绕过黑名单检测(大小写、编码等方式) 通过EL表达式注入执行系统命令 web_ ezyaml题目分析 这是一个简单的YAML反序列化题目,主要考察: JNDI注入 YAML反序列化漏洞利用 反序列化链构造 利用思路 构造恶意的YAML payload 利用SnakeYAML的反序列化特性 通过JNDI注入实现RCE 总结 这道题目综合考察了以下Java安全知识: Java反射机制的安全风险 黑名单/白名单绕过的技巧 表达式注入漏洞 反序列化漏洞利用 JNDI注入攻击 关键点在于理解反射调用的危险性,以及如何绕过安全限制执行任意代码。通过分析黑名单和白名单的限制,找到合适的类和方法进行利用,最终实现命令执行或反弹shell。