Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86378531

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

0x00 前言在上篇文章《VMware Workspace ONE Access漏洞调试环境搭建》 提到連接數據庫的口令加密保存在文件/usr/local/horizon/conf/runtime-config.properties中,本文將要基於調試環境,分析加密流程,介紹詳細的解密方法。

0x01 簡介本文將要介紹以下內容

加密流程

解密方法

數據庫操作

0x02 加密流程1.定位關鍵文件經過一段時間的尋找,找到實現加密功能對應的文件為/opt/vmware/certproxy/lib/horizon-config-encrypter-0.15.jar

反編譯獲得加密的實現代碼如下:

publicfinalStringencrypt(byte[]data){

if(data!=nulldata.length!=0){

if(!this.getKeyMgmt().randomKeyEnabled()!this.getKeyMgmt().customKeysAvailable()){

log.error('Nocustomencryptionkeysavailable,abortingencrypt.');

returnnull;

}else{

CipherencryptCipher=this.getEncryptCipher();

try{

if(encryptCipher!=null){

byte[]utf8=ArrayUtils.addAll(encryptCipher.getIV(),encryptCipher.doFinal(data));

ByteBufferkeyBuffer=ByteBuffer.allocate(2);

keyBuffer.putShort(this.getKeyMgmt().getCurrentKey());

utf8=ArrayUtils.addAll(keyBuffer.array(),utf8);

utf8=ArrayUtils.insert(0,utf8,newbyte[]{(byte)this.getKeyMgmt().getCurrentCipherVersion()});

byte[]dec=Base64.encodeBase64(utf8);

returnnewString(dec,StandardCharsets.US_ASCII);

}

}catch(IllegalBlockSizeException|IllegalStateException|BadPaddingExceptionvar6){

log.error(var6.getMessage(),var6);

}

returnnull;

}

}else{

returnnull;

}

}2.動態調試

為了提高分析效率,採取動態調試的方法,流程如下:

(1)新建Java工程

下載VMware Workspace ONE Accessd服務器中/opt/vmware/certproxy/lib/下的所有jar文件並保存,在Java工程導入以上jar文件

新建package:com.vmware.horizon.common.utils.config

新建文件ConfigEncrypterImpl.java,內容如下:

packagecom.vmware.horizon.common.utils.config;

importcom.google.common.annotations.VisibleForTesting;

importcom.vmware.horizon.api.ConfigEncrypter;

importcom.vmware.horizon.random.SecureRandomUtils;

importcom.vmware.horizon.security.SecurityProviderHelper;

importjava.nio.ByteBuffer;

importjava.nio.charset.Charset;

importjava.nio.charset.StandardCharsets;

importjava.security.InvalidAlgorithmParameterException;

importjava.security.InvalidKeyException;

importjava.security.NoSuchAlgorithmException;

importjava.security.SecureRandom;

importjavax.annotation.Nonnull;

importjavax.annotation.Nullable;

importjavax.crypto.BadPaddingException;

importjavax.crypto.Cipher;

importjavax.crypto.IllegalBlockSizeException;

importjavax.crypto.NoSuchPaddingException;

importjavax.crypto.SecretKey;

importjavax.crypto.spec.IvParameterSpec;

importjavax.crypto.spec.SecretKeySpec;

importorg.apache.commons.codec.binary.Base64;

importorg.apache.commons.lang3.ArrayUtils;

importorg.apache.commons.lang3.StringUtils;

importorg.bouncycastle.crypto.fips.FipsUnapprovedOperationError;

importorg.slf4j.Logger;

importorg.slf4j.LoggerFactory;

publicclassConfigEncrypterImplimplementsConfigEncrypter{

publicstaticfinalCharsetencodingCharset;

privatestaticfinalLoggerlog;

privatestaticfinalSecureRandomsrand;

privatestaticConfigEncrypterImplstaticKeyInstance;

privatestaticfinalConfigEncrypterImplrandomKeyInstance;

privatestaticfinalObjectkeyInstanceLock;

privateConfigEncrypterKeyMgmtkeyMgmt;

privatestaticConfigEncrypterImplcreateRandomKeyInstance(){

SecurityProviderHelper.initializeSecurityProvider();

returnnewConfigEncrypterImpl(false);

}

publicstaticConfigEncrypterImplgetInstance(){

synchronized(keyInstanceLock){

if(staticKeyInstance==null){

staticKeyInstance=newConfigEncrypterImpl(true);

}

returnstaticKeyInstance;

}

}

publicstaticConfigEncrypterImplgetRandomKeyInstance(){

returnrandomKeyInstance;

}

privateConfigEncrypterImpl(booleanuseStaticKey){

if(useStaticKeyBoolean.parseBoolean(ConfigPropertiesUtil.getProperties().getProperty('components.configEncrypter.kms.enable'))){

log.info('Notinitializingstaticconfigkeystore.UsingKMSforsecureconfigproperties');

this.keyMgmt=null;

}else{

this.keyMgmt=newConfigEncrypterKeyMgmt(useStaticKey);

}

}

@VisibleForTesting

ConfigEncrypterImpl(ConfigEncrypterKeyMgmtkeyMgmt){

this.keyMgmt=keyMgmt;

}

@Nullable

publicfinalStringdecrypt(Stringdata){

if(StringUtils.isBlank(data)){

returnnull;

}else{

byte[]encrypted=data.getBytes(encodingCharset);

booleanb64;

try{

b64=Base64.isBase64(encrypted);

}catch(ArrayIndexOutOfBoundsExceptionvar11){

b64=false;

}

if(b64){

encrypted=Base64.decodeBase64(encrypted);

}

if(ArrayUtils.isEmpty(encrypted)){

returnnull;

}else{

intcipherVersion=Math.abs(encrypted[0]);

CipherdecryptCipher=null;

if(cipherVersion=this.getKeyMgmt().getMinCipherVersion()cipherVersion0){

returnnewString(utf8,encodingCharset);

}

log.debug('zerolengthdecryption');

}catch(BadPaddingExceptionvar7){

log.debug('Failedtodecryptthegivenvalue(padding)');

}catch(IllegalBlockSizeExceptionvar8){

log.debug('Failedtodecryptthegivenvalue(blocksize)');

}catch(ArrayIndexOutOfBoundsExceptionvar9){

log.debug('Failedtodecryptthegivenvalue(macverification)');

}catch(IllegalStateExceptionvar10){

log.debug('Failedtodecryptthegivenvalue(illegalstate)');

}

}

returnnull;

}

}

}

@Nullable

publicfinalStringencrypt(@NonnullStringdata){

returnStringUtils.isBlank(data)?null:this.encrypt(data.getBytes(encodingCharset));

}

@Nullable

publicfinalStringencrypt(byte[]data){

if(data!=nulldata.length!=0){

if(!this.getKeyMgmt().randomKeyEnabled()!this.getKeyMgmt().customKeysAvailable()){

log.error('Nocustomencryptionkeysavailable,abortingencrypt.');

returnnull;

}else{

CipherencryptCipher=this.getEncryptCipher();

try{

if(encryptCipher!=null){

byte[]utf8=ArrayUtils.addAll(encryptCipher.getIV(),encryptCipher.doFinal(data));

ByteBufferkeyBuffer=ByteBuffer.allocate(2);

keyBuffer.putShort(this.getKeyMgmt().getCurrentKey());

utf8=ArrayUtils.addAll(keyBuffer.array(),utf8);

utf8=ArrayUtils.insert(0,utf8,newbyte[]{(byte)this.getKeyMgmt().getCurrentCipherVersion()});

byte[]dec=Base64.encodeBase64(utf8);

returnnewString(dec,StandardCharsets.US_ASCII);

}

}catch(IllegalBlockSizeException|IllegalStateException|BadPaddingExceptionvar6){

log.error(var6.getMessage(),var6);

}

returnnull;

}

}else{

returnnull;

}

}

@Nullable

privateCiphergetDecryptCipher(intcipherVersion,byte[]decryptionKey,byte[]iv){

CipherdecryptCipher=null;

if(!ArrayUtils.isEmpty(iv)){

try{

decryptCipher=Cipher.getInstance(this.getKeyMgmt().getCipher(cipherVersion),SecurityProviderHelper.getJceProvider());

IvParameterSpecivSpec=newIvParameterSpec(ArrayUtils.subarray(iv,0,this.getKeyMgmt().getCipherNonceSize(cipherVersion,decryptCipher.getBlockSize())));

SecretKeysecret=newSecretKeySpec(decryptionKey,this.getKeyMgmt().getCipher(cipherVersion));

decryptCipher.init(2,secret,ivSpec,srand);

}catch(InvalidAlgorithmParameterException|InvalidKeyException|NoSuchAlgorithmException|NoSuchPaddingException|IllegalArgumentException|FipsUnapprovedOperationErrorvar7){

log.error(var7.getMessage(),var7);

decryptCipher=null;

}

}

returndecryptCipher;

}

@Nullable

privateCiphergetEncryptCipher(){

CipherencryptCipher=null;

try{

encryptCipher=Cipher.getInstance(this.getKeyMgmt().getCipher(),SecurityProviderHelper.getJceProvider());

byte[]iv=newbyte[this.getKeyMgmt().getCipherNonceSize(encryptCipher.getBlockSize())];

srand.nextBytes(iv);

SecretKeysecret=newSecretKeySpec(this.getKeyMgmt().getKey(),this.getKeyMgmt().getCipher());

IvParameterSpecivSpec=newIvParameterSpec(iv);

encryptCipher.init(1,secret,ivSpec,srand);

}catch(InvalidAlgorithmParameterException|IllegalArgumentException|NoSuchPaddingException|NoSuchAlgorithmException|InvalidKeyException|FipsUnapprovedOperationErrorvar5){

log.error(var5.getMessage(),var5);

}

returnencryptCipher;

}

@VisibleForTesting

ConfigEncrypterKeyMgmtgetKeyMgmt(){

returnthis.keyMgmt;

}

@VisibleForTesting

publicvoidsetCustomEncryptionKeyst