【NodeJS渗透】提取和分析.asar文件的案例研究

news/2025/1/19 15:35:34/文章来源:https://www.cnblogs.com/o-O-oO/p/18679606

免责声明

⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!

硬编码密钥(在SQLite中)和加密算法(在AesFormula.js文件中)信息泄露导致真实凭据被泄露

一、案例研究

本节案例研究将讨论我们的一项测试结果,涉及基于Electron的应用程序中的客户端-服务器模型。

二、情况描述

在首次运行相关桌面应用程序时,我们注意到该应用程序具有记住输入凭据的功能。这似乎是合理的,因为应用程序提供的默认凭据相当复杂且难以记住。

(为了维护程序所有者的隐私,在本案例研究中我们不会使用真实的图像和代码。然而,为了便于讨论,我们将尝试绘制示意图并重写代码,以大致代表我们提供的解释内容)。

然而,在原生应用程序的概念中,有一个我们需要理解的原则。当我们使用应用程序提供的“记住我”功能时,本质上该应用程序会将我们的凭据存储在当前操作系统的本地环境中。尽管存储方法和形式有所不同,但为了清晰地理解流程,这一原则必须被牢牢遵守。

那么,这些数据存储在哪里呢?从技术角度来看,第三方应用程序数据的存储位置因操作系统而异。
【例如】,macOS上的应用程序数据通常存储在用户“Library”目录中的“Application Support”文件夹中。而在Windows上,第三方应用程序数据通常存储在用户“AppData”目录中的一个隐藏文件夹中。在Linux系统中,应用程序数据通常存储在用户目录中的“.config”文件夹中。

由于此次测试是在适用于macOS的应用程序上进行的,因此接下来的说明将重点关注macOS的相关细节。

三、 信息收集

注意:为了分析该应用程序的行为,我们需要尝试先登录,并勾选“记住我的密钥”选项。

3.1 检查 Application Support 和 Preferences 目录

在macOS环境中的初步实验中,我们检查了应用程序的目录,这些目录通常位于“Application Support”和“Preferences”中。

需要说明的是,“Application Support”目录主要用于macOS应用程序存储运行应用程序所需的数据,或者至少是与用户相关的应用程序数据。这些数据可能包括配置文件、本地数据库、缓存,或其他用于确保应用程序平稳运行的文件。例如,一个数据处理应用程序可能会在此存储文档模板,而一个游戏应用程序可能会在此存储用户的游戏进度数据。

另一方面,“Preferences”目录主要用于存储用户自定义的应用程序配置文件。它包括用户偏好设置,例如显示设置、语言偏好、键盘设置等。在这种情况下,用户设置通常“存储”在.plist文件中。

那么我们该如何操作呢❓ 在这种情况下,我们使用了一种相当传统的方法,即利用 grep 命令并结合针对我们用于登录应用程序的用户名的特定搜索。

以下是我们使用的命令:

grep -r username_of_the_apphere /Users/username/Library/Application\ Support/target_app/

以下是对该命令的简单解释:

  • grep:这是一个用于匹配给定输入中指定字符串模式的命令。

  • -r:这是一个选项,用于递归地搜索目录及其子目录中的内容。

  • username_of_the_apphere:这是我们要搜索的字符串,即我们在应用程序中使用的用户名。

  • /Users/username/Library/Application Support/target_app/:这是我们想要执行搜索的目录。
    在这种情况下,grep 将在目录 /Users/username/Library/Application\ Support/target_app/ 及其子目录中的所有文件内搜索该字符串。

我们同样对首选项目录下的 “target_app” 文件进行了相同的操作。

grep -r username_of_the_apphere /Users/username/Library/Preferences/com.electron.target-app.plist

那么结果如何❓ 简而言之,通过这次分析,我们没有发现任何与用户名相关的数据。随后,我们尝试转向另一个位置进行检查。

可能有人会问,为什么我们如此确信该用户名是以明文(未保护的)形式存储的?实际上,我们并不确定该用户名的存储状态,但尝试搜索并无妨。

3.2 检查隐藏目录(点目录)的可能性

我们需要注意的一点是,在 macOS(以及通用的 Unix 系统)中,有一些目录对用户是隐藏的。这些目录通常以一个点(.)开头,位于 /Users/username 路径下。

在实际应用中,第三方应用程序有时会利用这些类型的目录来存储与应用程序相关的信息,而这些信息从技术角度讲并不需要用户访问。

注意:有时也会有应用程序将其数据存放在 /Users/Username/.local/share 目录中。

基于这种情况,我们决定检查 /Users/Username 路径,看看是否存在这类目录。长话短说,我们找到了一个肯定的结果,也就是目标应用(target_app)确实拥有这样一个目录。

当我们首次发现.data.db文件的存在时,我们就已经相当确信该文件可能包含我们正在寻找的凭据。然而,为了确认这一点,我们按照之前提到的方法使用grep进行了传统搜索。果然,结果如我们所预料,这个用户名确实存在于相关的.db文件中。

3.3 使用 DB Browser for SQLite 打开 .db 文件

通常,一个应用程序(无论是移动端还是桌面端)都会使用轻量级的数据库管理系统(DBMS)在本地计算机上进行存储。
一种常见的选择是 SQLite

在确认该文件确实是 SQLite 格式后,我们使用了一个名为 DB Browser for SQLite 的简单工具将其打开(尽管也可以使用其他工具)。

长话短说,我们找到了我们想要的内容,也就是存储用户名、URL 和密钥的列。

然而,在进一步检查我们使用的值后,发现密钥的值与预期的值不符。从它的格式来看,我们认为这是一种AES加密格式,这是常用的数据安全算法。

Value: eLy2xThk+y7Rki4J13zvGVxrnqZbrOtznvNbhOKIgWo=

再次需要指出的是,为了简化讨论,同时隐藏任何加密值和代码,我们已经用其他样本替换了它们(是的,这是从ChatGPT重制的)。

3.4 寻找加密算法

根据我们描述的情况,我们继续测试,探索用于“保护”密钥值的潜在算法和公式。简而言之,考虑到target_app应用程序是基于Electron构建的,我们尝试提取包内容中的app.asar文件。

请注意:

要了解如何检测基于Electron的应用程序以及提取过程,可以参考前几篇文章。

成功提取后,我们可以继续搜索应用程序使用的算法和公式,以保护前面提到的密钥值。

3.5 找到加密算法

在仔细检查提取目录中的每个文件后,我们发现了一个引起我们注意的文件,即AesFormula.js

3.6 理解加密流程

在检查AesFormula.js文件中的代码流程时,我们发现了一个负责动态生成加密密钥和初始化向量(IV)的代码段。该代码段包含两个函数:generateEncryptionKey和generateIV。

在generateEncryptionKey函数中,使用crypto.randomBytes方法生成一个随机的密钥组件,长度由KEY_LENGTH指定。随后,使用generatePBKDF2Salt函数生成一个盐值(SALT)。

这些随机密钥组件和默认密钥通过按位异或(XOR)操作结合,生成一个唯一的密钥。这个生成的密钥与生成的SALT一起,通过PBKDF2算法进行密钥派生,最终得到一个派生密钥(pbkdfKey)。最后,从这个派生密钥中选取前部分(等于KEY_LENGTH字节)作为AES加密的加密密钥。

类似地,在generateIV函数中,使用crypto.randomBytes方法生成一个随机的初始化向量(IV),其长度由IV_LENGTH指定。这个IV将在AES加密过程中作为唯一的初始化向量使用。

这些动态生成过程确保每次加密操作使用不同的密钥和初始化向量(IV),从而增强了加密机制的安全性。

从技术上讲,AesFormula通过为每次加密操作动态生成加密密钥和IV,提供了安全的加密功能。

为了验证我们的假设,我们尝试多次登录和登出,并观察SQLite中密钥的变化。

那么,结果如何?结果是积极的。在三次有效的登录尝试中,我们发现SQLite中的密钥值确实发生了变化。
以下是相同值的三次不同加密结果:

接下来是什么呢?当然是要找到由这段代码生成的salt、key和IV的值。至于过程,我们继续研究现有代码的流程,直到最终遇到了以下这段代码:

这段代码显示,所有密钥生成过程的结果将存储在一个名为“encryptionMaterial”的部分中。

3.7 找到“Key”存储位置

在这种情况下,我们需要查找存储在encryptionMaterial中的值。长话短说,在尝试分析SQLite数据库的内容后,我们最终发现encryptionMaterial的值硬编码存储在同一张表中,即t_user表的some_secret_name列中。

四、解密密钥值

我们已经得到了密钥的加密值,并且我们也有用来加密的密钥值(iv、keyComponentBuf和salt),接下来我们将尝试解密现有的密钥值。

要执行此解密操作,最简单的方法之一是利用程序本身(在本例中,是AesFormula.js文件中可用的函数)。

以下是一个简单的代码,可以用来解密密钥值:

const AesFormula = require('./AesFormula');const encryptedValue = 'VQwSxZiICNhGjzLpcLSz1CDP11bEib26LFw+4av6VmE=';
const encryptionMaterial = {iv: Buffer.from([0xb0, 0xe3, 0x88, 0x26, 0x7c, 0xe3, 0xc3, 0x91, 0x5d, 0x95, 0xec, 0x72, 0xa7, 0x67, 0xd5, 0x20]),keyComponentBuf: Buffer.from([0xb8, 0x02, 0x63, 0x02, 0xe6, 0xcf, 0x1e, 0x61, 0xa9, 0x56, 0x1f, 0x49, 0xb1, 0x74, 0x77, 0x23, 0xb0, 0x59, 0xca, 0xa3, 0xa2, 0x8b, 0x34, 0x71, 0x23, 0x6c, 0xa5, 0x4d, 0x34, 0x85, 0x78, 0xeb]),pbkdf2SaltBuf: Buffer.from([0x4e, 0xc4, 0x6f, 0x21, 0x4b, 0x55, 0xc7, 0x58, 0x38, 0x9d, 0x6e, 0x31, 0xc0, 0x37, 0xaa, 0x68])
};const decryptValue = async () => {try {const decryptedResult = await AesFormula.decryptWithAES(encryptedValue, encryptionMaterial);console.log('Decrypted value:', decryptedResult);} catch (error) {console.error('Error while decrypting:', error);}
};decryptValue();

我们需要做的就是将来自encryptionMaterial的值(iv、keyComponentBuf和salt)输入到其中。将这段代码保存(例如命名为:decrypt.js)。然后,将AesFormula.js文件放在与此代码相同的目录中。

要执行这段代码,我们需要借助node.js。
以下是运行程序后的最终结果:

总之,PoC(概念验证)过程包括:

1、从data.db文件中的t_user表的key列获取key值。
2、从data.db文件中的t_user表的some_secret_name列获取encryptionMaterial值。
3、将key值复制到我们之前创建的decrypt.js代码中。
4、将encryptionMaterial值(逐个为iv、keyComponentBuf和salt)复制到我们创建的decrypt.js代码中。
5、将AesFormula.js文件放置在与decrypt.js文件相同的目录中。
6、使用node.js运行decrypt.js代码,命令为node decrypt.js

五、其他信息

5.1 观点

从这个案例中,我们也可以认识到,应用程序实施的加密相当稳健,例如使用动态密钥,这无疑使得攻击者猜测变得困难。然而,关键问题最终集中在密钥公式和密钥本身的存储方式。
这个问题的执行可能引发一个问题:“获得本地访问权限的攻击者是否能够直接通过启用‘记住我的密钥’功能的target_app登录?”
本质上,这是一个有效的问题。然而,我们需要更深入地思考,因为攻击者在本地目标上的存在通常是有时间限制的。攻击者要想探索target_app中的每一条数据,无疑会受到限制,并且对于攻击者来说并不理想。
因此,通过利用本报告中描述的问题,攻击者将不再受时间限制,从用户的target_app中窃取数据。因为攻击者可以快速执行窃取操作,通过访问存储在SQLite数据库中的硬编码用户名、URL、key和encryptionMaterial。随后,攻击者可以从本地目标之外的各种位置进行探索。
尽管关于某些程序中这个问题的有效性的争论仍然存在,但在红队演习中无疑是有益的。

5.2 SafeStorage模块

需要注意的是,Electron框架提供了一个名为SafeStorage[1]的模块,用于保护存储在磁盘上的数据,以免被其他应用程序或具有完全磁盘访问权限的用户访问。从技术上讲,Electron中的safeStorage利用操作系统本地的安全存储API,以加密形式存储数据(因此,这可能是一个不错的替代方案)。
References

[1] SafeStorage: https://www.electronjs.org/docs/latest/api/safe-storage

原创 白帽子左一

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/871723.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring,Spring Ioc,Bean详解

Spring框架Spring框架是Java应用最广的框架,其的成功来自于理念,并非是技术,其中几个理念非常重要,例如IoC(控制反转),AOP(面向切面编程)Spring的优势低耦合/低侵入(解耦)Spring通过IoC(控制反转)和DI(依赖注入)来实现低耦合高内聚声明式事务管理Spring基于AOP的方式,使其能够在…

远程桌面键盘记录器

针对远程桌面协议 (RDP) 相关进程的击键记录器,它利用键盘输入挂钩,允许其记录某些上下文中的击键(例如在 mstsc.exe 和 CredentialUIBroker.exe 中) 使用vs直接编译就可以了运行TakeMyRDP.exe打开mstsc,输入ip地址,输入账号密码密码直接显示出来,这个exe不需要高权限运行…

【nginx】Nginx重定向方法

Nginx重定向配置是一个功能强大且灵活的工具,可以根据具体需求实现各种重定向规则。 以下是对Nginx请求重定向配置方法的详细解析:1、基本概念 请求重定向是指当客户端向服务器发送一个请求时,服务器根据一定的规则将客户端的请求引导到另外一个URL的过程。在Nginx中,通过r…

利用mybatis拦截器记录sql,辅助我们建立索引(二)

背景 上一篇中讲述了mybatis的mapper初始化过程和执行过程,这篇再讲讲具体的拦截器的使用,以实现记录sql到持久化存储,通过分析这些sql,我们就能更方便地建立索引。 利用mybatis拦截器记录sql,辅助我们建立索引(一) 我本地项目的大概版本: spring boot版本2.7,mybatis版…

JMeter通过JSON提取器获取任意一行数据中的多个字段

存在如下响应信息: { "result": { "data": [ { "字段1": "DK-01", "字段2": null, "字段3": "210(3mm/40kg)",}, {&q…

Windows7 64位系统ODBC数据源配置方法

Windows7 64位系统ODBC数据源配置方法 注意以下所说的步骤是在安装好SQL2000或者端内有绿色SQL的情况下,已经在查询分析器内一键建立并还原好数据库之后才进行的,请不要跳步骤进行,否则会出错。一键端可直接操作。(win7系统架设传奇3前请将UAC账户权限调至最低) Windows7…

【clang-format】Windows11下代码格式化工具clang-format.exe下载

官方项目地址:https://github.com/llvm/llvm-project/releases下滑找到win64.exe下载慢的可以去这个github代下网站:https://d.serctl.com/下载好后不用安装,直接解压这个exe文件 把目录bin里面的clang-format.exe文件复制出来,放到一个新文件夹里,比如我放到了D盘根目录下…

聊一聊 操作系统蓝屏 c0000102 的故障分析

一:背景 1. 讲故事 今年以来不知道为啥总有些朋友加我微信,让我帮忙分析下操作系统蓝屏问题,我也觉得挺好奇的,就问了其中一位朋友,说是B站来的,我就在拼命回忆,为啥会找我分析蓝屏?突然想到了去年好像录了一集关于 CrowdStrike 的热点事件。。。我本来是做.NET程序的故…

4-01-(C++类 this指针)

结构体传参,传递的是副本 结构体里面写函数,结构体的大小不变 函数的地址不在结构体里面。 类里面的函数都要传一个this指针,即 lea ecx,[s] 普通的函数结构体传参 this指针的特点 1、你用或者不用,它就在那里 2、参数个数确定的时候,用ecx来传递 3、参数个数不确…

协议通道版iMessage蓝号检测,iMessages数据筛选,无痕检测是否开启iMessage服务

一、实现iMessage数据检测的两种方式:1.人工筛选,将要验证的号码输出到文件中,以逗号分隔。再将文件中的号码粘贴到iMessage客户端的地址栏,iMessage客户端会自动逐个检验该号码是否为iMessage账号,检验速度视网速而定。红色表示不是iMessage账号,蓝色表示iMessage账号。2…

【开源】一款功能全面的商用级溯源防伪系统,适用于各种溯源场景

项目介绍 HiPi是一款开源、功能全面的商用级溯源防伪系统,一物一码系统,适用于各种溯源场景的大、中、小、微规模企业。系统能够追踪记录产品的生命周期各个环节,并将产品信息保存在系统中,实现品牌保护、产品营销、防止假冒伪劣产品、防窜货、产品追踪溯源等功能。 应用场…