文章总结: 本文围绕Apifox供应链攻击事件展开,攻击者篡改了其公网SaaS版外部JS文件,植入恶意代码实现用户行为追踪、系统信息采集及远程代码执行。作者使用AiPy工具结合不同大模型对被篡改的混淆JS进行逆向分析,揭示了国产模型在无Skill配置下易产生幻觉(将恶意域名误判为apifox.it.co而实际为apifox.it.com),而Gemini模型配合自定义Skill能更准确还原代码逻辑。文章还提供了基于AiPy的自查方法,帮助用户检测浏览器localStorage等是否中招,并分享了完整的混淆JS逆向分析流程与Skill编写规范,强调以原始样本为第一证据链、区分验证事实与推测的重要性。 综合评分: 74 文章分类: 供应链安全,逆向分析,代码审计,AI安全,漏洞分析
Apifox 供应链攻击事件(AiPy自查)
heige heige
黑哥虾撩
2026年3月26日 14:29 美国
这次的“Apifox 供应链攻击事件” 可以参考:
官方公告:关于 Apifox 公网 SaaS 版外部 JS 文件受篡改的风险提示与升级公告
另外还有一个最早发布的一个完整分析:
https://rce.moe/2026/03/25/apifox-supply-chain-attack-analysis/
这类的分析其实在 使用Zoomeye 和 AiPy 捕获 Coruna 样本已经有过例子了,秉承AI Agent 下半场 文章中“结果导向”的理念,在这次分析中出现了一个非常典型的 “幻觉”,另外在这几天直播中有人问我:是Skill重要还是模型能力重要,包括这段时间翻炒的 IHarness Engineering 当然这个问题我其实在以往的文章都提到过, 然后这个例子正好用来说明这个问题。
启动AiPy (我用的Cli版本,大家也可以去www.aipyaipy.com 去使用gui版本)
帮我分析下
https://web.archive.org/web/20260305051418if_/https://cdn.apifox.com/www/assets/js/apifox-app-event-tracking.min.js
幻觉(国产模型+没有配置skill)
开始我使用的国内模型(具体就不说了),然后一顿分析后的结果:
解密后发现的域名
https://api.apifox.comhttps://apifox.it.co ← ⚠️ 恶意域名https://cm.bilibili.comhttps://convert.dop.360.cnhttps://ocpc.p4p.sogou.comhttps://us.i.posthog.comhttps://www.google-analytics.com
关键发现
在 deobfuscated_complete.js 第 22 行:
// 远程服务器 URLconstREMOTE_JS_URL = 'https://apifox.it.co/xxx';constAPIFOX_USER_API = 'https://api.apifox.com/api/v1/user';
确认:版本 1 使用 https://apifox.it.co/xxx 作为远程代码请求地址
随后我还追问了下:
当时我也差点被幻觉误导了,注意看他这里找出来的是 apifox.it.co , 于是我审查了一下整个过程,发现了问题:在编写deobfuscate.js的代码的时候,他直接估计混淆的js脑补了一个地址
原本的混淆的JS源码:
这种幻觉还是非常隐蔽的,不容易被发现,如果不是review下整个过程,很可能就被误导了,这个也对后续的排查也会埋下漏报祸根!
逆向 (AiPy + Gemini31.1 pro)
🚀 Python use – AIPython (0.6.0b17) [https://aipy.app]
[Main] Please enter an instruction or
/helpfor more information/llm use tt-gemini-3
Success
帮我逆向下
https://web.archive.org/web/20260305051418if_/https://cdn.apifox.com/www/assets/js/apifox-app-event-tracking.min.js
这里分析出来的是 apifox.it.com 生成的md报告:
Apifox App Event Tracking 逆向分析报告
概述
对 apifox-app-event-tracking.min.js 文件进行了深度逆向分析,这是一个高度混淆的JavaScript文件,主要用于收集用户行为数据并与远程服务器通信。
文件基本信息
-
原始大小
: 80,255 字节
-
混淆类型
: 字符串数组 + RC4加密 + 控制流平坦化
-
目标环境
: 浏览器/Electron桌面应用
-
主要功能
: 用户行为追踪、远程代码加载、系统信息采集
代码结构分析
1. 混淆机制
-
字符串数组
:
_0x70b33e包含 400+ 个混淆字符串 -
RC4解密
:
_0x3fb9函数实现RC4流密码解密 -
字符串洗牌
: 通过复杂的数学运算重新排列字符串数组
-
函数重命名
: 所有函数和变量都使用
_0x[0-9a-f]+格式
2. 核心功能模块
2.1 网络通信模块
// 远程JS URL (经过混淆)
REMOTE_JS_URL = "https://apifox.it.com/..."
// API接口
APIFOX_USER_API = "/api/v1/user"
// 代理服务器
PROXY_SERVER = "https://web-proxy.apifox.com/api/v1/request"
2.2 加密模块
-
RSA加密
:
rsaEncrypt()/rsaDecrypt() -
私钥
: 硬编码在代码中(PEM格式)
-
用途
: 加密敏感数据(用户ID、设备信息等)
2.3 系统信息采集
// 采集的数据包括:
- MAC地址
- CPU型号
- 操作系统版本
- 主机名
- 网络接口信息
2.4 持久化存储
-
localStorage键
:
-
_rl_mc: 机器标识
-
common.headers: 请求头信息
-
eventTracking.firstVisit: 首次访问标记
-
eventTracking.dailyReportUsers: 日报用户记录
3. 主要执行流程
3.1 初始化阶段
- 加载字符串数组并解密
- 获取或生成设备指纹
- 建立网络连接测试
3.2 数据采集阶段
- 收集系统信息(CPU、OS、网络)
- 生成唯一设备标识符
- 加密敏感数据
3.3 远程通信阶段
- 向API发送心跳包
- 获取远程JS代码 (
loadAndExecute()) - 执行远程代码 (
eval(rsaDecrypt(response)))
3.4 定时任务
-
随机间隔
: 4小时 – 24小时
-
任务类型
:
-
数据上报 (
scheduleNext) -
页面访问统计 (
reportPageview) -
用户行为追踪 (
report)
4. 安全分析
4.1 潜在风险点
-
远程代码执行
: 从
REMOTE_JS_URL动态加载并执行JS代码 -
数据泄露
: 收集详细的系统信息和用户行为
-
持久化跟踪
: 使用多种存储机制维持长期跟踪
-
加密绕过
: 使用弱加密算法保护传输数据
4.2 反调试措施
- 复杂的字符串混淆
- 自修改代码
- 定时器干扰
5. 关键发现
5.1 远程服务器
-
主服务器
:
https://apifox.it.com -
API端点
:
/api/v1/request,/api/v1/user -
代理服务
:
web-proxy.apifox.com
5.2 跟踪功能
- Google Analytics集成
- 百度统计集成
- PostHog统计集成
- SLS日志服务
5.3 用户识别
- 基于硬件信息的设备指纹
- 用户ID绑定 (
common.currentUserId) - 会话跟踪 (
projectCid)
技术细节
6.1 字符串解密算法
functionrc4_decrypt(key, data) {
// 初始化S盒
// 密钥调度算法
// 伪随机生成算法
// 异或解密
}
6.2 设备指纹生成
functiongenerateDeviceId() {
const components = [
macAddress,
cpuModel,
osVersion,
hostname,
networkInterfaces
];
returnsha256(components.join('-'));
}
6.3 定时调度算法
functionrandomInterval() {
const min = 4 * 60 * 60 * 1000; // 4小时
const max = 24 * 60 * 60 * 1000; // 24小时
return min + Math.random() * (max - min);
}
结论
这是一个功能完整的用户行为追踪SDK,具有以下特点:
-
高度混淆
: 使用多层加密和混淆技术保护代码
-
全面采集
: 收集系统和用户行为数据
-
远程控制
: 支持动态更新和执行远程代码
-
持久跟踪
: 使用多种机制维持长期跟踪能力
-
多平台支持
: 同时支持Web和Electron环境
建议
-
安全审计
: 建议对远程服务器进行安全评估
-
隐私合规
: 确保符合GDPR等隐私法规
-
代码加固
: 考虑使用更安全的加密算法
-
监控机制
: 建立异常行为检测机制
分析时间: 2026-03-26 分析工具: 静态分析 + 动态调试 风险等级: 高
自查
有这个分析结果了就非常简单了
帮我查一下是否中招
当然这个前提是你有给他分析那个js,如果不想发时间逆向分析,你也可以随便找一个分析报告让AiPy阅读下也是可以的
看起来还是查得比较仔细的包括浏览器localStorage啥的。
Skill (AiPy+国产模型+Skill)
按AI Agent 下半场 里提到的套路:
Code-use Agent –> 任务 –> 自动总结生成并安装 Skills –> 分发 到 Skills 市场 –> 其他用户下载安装使用
我用国外的模型自动提炼了个Skill:
---name: reverse-obfuscated-jsdescription: Use this skill to reverse engineer obfuscated JavaScript loaders, telemetry scripts, and suspected staged payloads. It focuses on evidence-first analysis, controlled execution, IOC extraction, deobfuscation, and preventing AI hallucinations from entering the evidence chain.---# Reverse Obfuscated JS## When to use this skillUse this skill when the target is a minified or obfuscated JavaScript sample and you need to:- recover important constants, URLs, keys, and storage names- understand loader chains and second-stage payload fetches- inspect telemetry, tracking, or suspicious desktop/Electron behavior- distinguish verified facts from guesses- produce readable deobfuscated output and a defensible reportThis skill is optimized for samples where pure regex extraction is not enough because key strings are restored at runtime.## Core ruleDo not let generated artifacts become evidence.Primary evidence is limited to:- the original sample- controlled runtime interception of the original sample- first-party response bodies returned by the sampleSecondary artifacts are useful for explanation but cannot prove original behavior:- AI-written reports- manually reconstructed code- flowcharts- deobfuscated templates## Output modelEvery conclusion should be labeled as one of:- `Verified`: directly supported by primary evidence- `Inferred`: supported indirectly and should be stated as inference- `Unknown`: not yet establishedNever fill an unknown IOC with a plausible-looking placeholder such as `https://example.com/xxx`.## Workflow### 1. Preserve the original sample- save the raw script exactly as collected- compute and record a hash if practical- avoid editing the original sample### 2. Perform a static sweepUse fast text search first.Recommended commands:```bashrg -n "https?://|localStorage|sessionStorage|fetch|eval|Function\\(|XMLHttpRequest|require\\(|crypto|posthog|gtag|electron|userAgent" sample.jsrg -n "_0x|atob|btoa|fromCharCode|decodeURIComponent|TextDecoder|subtle|createDecipheriv|createHash" sample.js```During the static pass, extract:- obvious URLs- storage keys- crypto API usage- `eval` or code-generation sinks- environment checks such as `Electron`, `window.require`, `process`- identifiers for string-decoder functions and lookup arrays### 3. Build a controlled runtimeIf important values are restored dynamically, execute the original sample in a constrained environment.Prefer Node.js `vm` or an equivalent sandbox with stubbed globals.Intercept at minimum:- `fetch`- `XMLHttpRequest`- `eval`- `Function`- `localStorage.getItem` and `localStorage.setItem`- `sessionStorage`- `window.require`- `setTimeout` and `setInterval`- DOM insertion points such as `document.createElement`, `appendChild`, `insertBefore`For Electron-oriented samples, stub:- `window.require('crypto')`- `window.require('os')`- `window.require('fs')` only if neededThe goal is not full emulation. The goal is to capture:- resolved constants- runtime-decoded strings- fetched URLs- custom request headers- storage keys and values- decryption inputs and outputs- the final code execution sink### 4. Recover dynamic constantsFor values such as `REMOTE_JS_URL`, `LS_HEADERS`, or API paths:- prefer runtime interception over regex guessing- if the script computes headers, log the computed object- if the script writes a storage key, capture the exact key used at runtimeIf a string-decoder function is isolated cleanly, you may evaluate just that decoder and dump its outputs. Still treat the original sample as the source of truth.### 5. Analyze loader and crypto behaviorMap the execution chain in order:- what condition enables the loader- what identifiers or fingerprints are collected- how request headers are built- which endpoint is fetched- whether content is encrypted, compressed, or encoded- which decryptor/decoder is used- where execution finally occurs, such as `eval(decryptedCode)`When describing crypto behavior, be precise:- identify algorithm and mode only if verified- identify hash function only if verified- if key material is partial or hidden, mark it `Unknown`### 6. Reconstruct readable codeAfter evidence is collected, produce a readable reconstruction.Rules for reconstruction:- preserve verified constants exactly- mark approximate logic with comments such as `// inferred`- do not silently replace unknown behavior with plausible logic- keep dangerous calls visible, for example `eval`, network fetches, local fingerprinting### 7. Produce an evidence tableFor each high-value conclusion, include:- claim- status: `Verified`, `Inferred`, or `Unknown`- evidence source- file or runtime referenceExample:```textClaim: REMOTE_JS_URL = https://apifox.it.com/public/apifox-event.jsStatus: VerifiedEvidence: controlled runtime interception of fetch() from original sample```## Hallucination prevention checklistBefore finalizing, verify all of the following:- no IOC came only from an AI-generated report- no generated deobfuscated file is being used as proof of original behavior- all placeholder values are clearly marked- all critical URLs were observed in the sample or during controlled execution- all storage keys were observed exactly, not abbreviated- all API field names were read from real responses or real access paths- every important claim is tagged `Verified`, `Inferred`, or `Unknown`If a guessed value appears in a draft, remove it or relabel it before shipping.## DeliverablesThe default deliverables for this skill are:- a concise finding summary- a readable deobfuscated or reconstructed code file- an evidence-backed notes file- if relevant, a short hallucination-risk section explaining what was verified vs inferred## Practical biasPrefer runtime truth over elegant static theory.If static extraction and runtime behavior disagree, trust the original sample plus controlled interception, then explain the discrepancy.
然后AiPy安装这个skill 使用国产模型跑了下,一次就跑出结果了:
效果还是非常好的。
所以在现在阶段Skills的存在是,其实也就是之前的提示词工程的还是有存在的价值和意义的,这个也让我想起在直播的时候提到的Claud 与 Openai在当时还是提示词工程这个词比较火的时代的PK,这个跟AI Agent 下半场 里提到的MCP/Skills 其实也是一样的:
过度的开发者依赖不符合 AGI 的追求
但是你也不得不承认在先阶段,好的提示词(包括Skill)还是能有效提升模型工作能力的!当然他们两者也不冲突,还有一个就是通用Agent设计也非常重要,在现阶段这三方面都有发挥的空间~
总结:
以“结果为导向”才是AI Agent的下半场的唯一衡量标准!AiPy其实一直都是以“让AI成为您的真正干活牛马”
无耻广告:
我正在体验新一代超级人工智能助手AiPy!现在使用我的专属邀请码:sE5B,立即获得 2,000,000 Tokens额外奖励!
使用方式如下:
① 进入AiPy官网:https://www.aipyaipy.com/,下载最新版AiPy客户端。
② 注册登录时填写上方邀请码即可。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:黑哥虾撩 heige heige《Apifox 供应链攻击事件(AiPy自查)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论