当前位置: 首页 > news >正文

Burp Suite JS-RPC:将前端加密变为可调用测试探针

1. 这不是“绕过”而是把前端加密变成你的测试探针你有没有遇到过这种场景目标网站登录接口的密码字段前端用了一段混淆得密不透风的JS调用WebCrypto API生成AES密文再拼上时间戳、随机数、签名最后发给后端Burp Suite抓到的请求里password字段永远是一串32位十六进制乱码改一个字节就返回“签名无效”你试过重放、试过修改时间戳、试过替换密钥参数——全失败。这时候多数人会停在“前端加密太硬没法测”的结论上转头去翻源码、找JS入口、手动扣逻辑一耗就是半天还容易漏掉动态生成的salt或临时密钥。但其实你手里的Burp Suite从2021年正式支持JS-RPCJavaScript Remote Procedure Call机制起就已经具备了另一种能力不破解、不逆向、不扣代码直接让目标页面自己执行你指定的JS函数并把结果实时回传给你。这不是Burp的“隐藏功能”而是官方文档里明确标注为“用于与目标页面深度交互”的核心扩展能力。它把原本单向的“拦截-修改-转发”流程升级成了双向的“注入-调用-获取-验证”闭环。你不再需要理解那段加密JS到底用了多少层Base64嵌套、是否依赖window.crypto.subtle.generateKey的异步回调顺序你只需要告诉它“请用你自己的加密函数把‘admin123’加密成我能看到的格式”。这个思路的本质是把前端加密模块从“黑盒障碍”重新定义为“可调度服务”。它适用于所有使用标准WebCrypto、CryptoJS、SJCL等主流库实现的前端加解密逻辑也兼容Vue/React应用中封装在store或utils里的加密方法。只要那段JS在当前页面上下文中可访问、可调用JS-RPC就能把它拉出来为你所用。对渗透测试人员来说这意味着你的时间花在验证业务逻辑漏洞上而不是卡在加解密逆向里。本文接下来要讲的就是如何在真实项目中把这段“黑魔法”从概念落地为每天都能用的标准化操作流——包括环境准备的三个关键检查点、JS-RPC调用的三类典型模式、一次完整实战中如何从抓包发现加密特征到写出可复用的调用脚本再到批量爆破弱口令的全过程。所有步骤均基于Burp Suite Professional v2024.7实测不依赖任何第三方插件。2. JS-RPC不是“执行JS”而是建立一条可控的前后端通信隧道很多人第一次听说JS-RPC下意识反应是“这不就是浏览器控制台里敲document.getElementById()”——这是最典型的误解。JS-RPC和console执行JS有本质区别前者是Burp Suite主动发起、受控、带超时与错误捕获的远程过程调用后者是开发者工具被动响应、无状态、无上下文隔离的手动调试。这个区别直接决定了它能否稳定用于自动化测试。2.1 JS-RPC的底层通信机制为什么必须用Chrome DevTools ProtocolCDPBurp Suite本身不运行JavaScript引擎它通过Chrome DevTools ProtocolCDP与已连接的Chrome/Edge浏览器实例通信。当你在Burp中启用JS-RPC并触发调用时实际发生的是以下四步链路Burp向CDP发送Runtime.evaluate指令携带你编写的JS代码字符串、执行上下文ID通常是main、超时时间默认5秒Chrome接收指令在目标页面的主线程中创建独立执行环境这个环境与页面当前JS执行栈隔离但能访问全局对象如window、document和已加载的脚本作用域Chrome执行JS并捕获返回值若代码抛出异常CDP会返回结构化错误信息含堆栈若成功返回序列化后的结果字符串、数字、布尔值或简单对象Burp解析CDP响应将结果展示在UI或传递给后续处理模块如Intruder、Repeater。这个机制的关键优势在于上下文保真性你调用的encryptPassword(test)用的是目标页面加载的CryptoJS v4.2.0而不是你本地Node.js里装的v4.1.0它读取的window._cryptoKey是页面运行时动态生成的真实密钥不是你静态分析猜出来的占位符。这也是为什么JS-RPC能解决“密钥动态生成”这类传统方案束手无策的问题。提示必须使用Burp Suite Professional版本Community版不支持JS-RPC。且需确保Burp与浏览器通过CDP正确连接——常见失败原因是Chrome启动时未加--remote-debugging-port9222参数或防火墙拦截了本地9222端口。实测建议用Burp内置的Browser功能Proxy → Options → Browser它会自动配置好所有参数避免手动调试CDP连接。2.2 JS-RPC调用的三种典型模式从“取值”到“驱动”根据目标加密逻辑的封装方式JS-RPC调用可分为三类每种对应不同的编写策略和适用场景模式类型触发条件JS-RPC调用示例适用场景实测稳定性全局函数直调加密函数挂载在window上如window.encryptwindow.encrypt(123456)传统jQuery站点、老系统、未做模块化封装的页面★★★★★最稳模块导出调用使用ES6export或UMD打包需先import或requireawait import(./js/crypto.js).then(m m.encrypt(123456))Vue CLI/React Create App构建的现代SPA★★★☆☆需处理路径和异步实例方法调用加密逻辑封装在Vue组件data、React Hook或Class实例中document.querySelector(#login-form).__vue__.encryptPassword(123456)框架深度集成场景需DOM定位框架API★★☆☆☆易因框架版本变化失效其中“全局函数直调”是首选方案覆盖80%以上实战案例。它的稳定性源于两点一是无需解析模块依赖避免import()失败二是不依赖框架内部属性如__vue__不受Vue 2/3或React 17/18的API变更影响。我在某银行网银渗透中就靠window.doEncrypt这一行代码绕过了其自研的三层混淆加密JS整个过程从发现到调用成功仅用12分钟。2.3 为什么不能用eval()或Function()安全沙箱的硬性限制有读者会问“既然能执行JS那我直接写eval(atob(...))不就行了”——答案是否定的。Chrome CDP对Runtime.evaluate的执行环境施加了严格沙箱限制禁止动态代码生成eval()、new Function()、setTimeout(code)等API在CDP执行环境中被禁用调用会直接报错EvalError: Refused to evaluate a string as JavaScript禁止跨域资源加载fetch(https://attacker.com/payload.js)会被CSP策略拦截即使目标站未设CSPCDP也会主动拒绝禁止DOM写入副作用document.write()、location.href等会触发页面跳转的操作被静默忽略。这些限制不是Bug而是设计使然JS-RPC的定位是“安全地调用已有逻辑”而非“注入任意代码”。它强制你尊重目标页面的现有架构把精力放在理解其加密契约输入什么、输出什么、依赖哪些变量上而不是钻沙箱漏洞。这也解释了为什么“扣JS逻辑”仍是必要前置动作——你不需要逆向算法但必须知道函数名、参数名、返回格式。比如某电商登录加密函数名为genLoginToken它接受两个参数{pwd: xxx, salt: window.salt}返回一个base64字符串。这个契约就是你写JS-RPC调用的全部依据。3. 从抓包到调用一次完整的JS-RPC实战拆解我们以某政务服务平台的登录接口为例完整走一遍JS-RPC落地流程。该平台前端使用CryptoJS AES-256-CBC加密密码密钥由服务端下发的sessionKey派生IV固定为16字节0。传统方案需手动实现PBKDF2派生密钥、补位、加密全流程而JS-RPC让我们跳过所有这些。3.1 第一步精准识别加密特征——别只看password字段很多测试者一上来就盯着password字段的密文长度如64字符但这只是表象。真正关键的识别信号有三个请求体中的“非业务参数”除username、password外是否存在timestamp、nonce、sign等字段这些往往是加密配套参数响应中的“加密相关提示”返回{code:401,msg:invalid signature}比{code:401,msg:login failed}更可疑JS文件中的关键词线索在Burp的Target → Site map中右键JS文件 → Open in browser在浏览器控制台执行grep -r encrypt\|Crypto\|AES *.js需先安装Console Utilities快速定位加密逻辑。在该政务平台中我们发现请求体含enc_pwd非password、ts、nonce、sign四字段响应401时固定返回invalid sign主JS文件中有CryptoJS.enc.Utf8.parse、CryptoJS.AES.encrypt调用。这三点交叉验证确认了前端加密的存在。3.2 第二步定位并验证加密函数——用最小化JS调用确认契约打开该平台登录页按F12进入控制台执行以下三步验证// 1. 检查CryptoJS是否全局可用 console.log(typeof CryptoJS); // 输出 object // 2. 查找加密函数搜索所有函数名含enc的 for (let key in window) { if (typeof window[key] function /enc/i.test(key)) { console.log(key); // 发现 window.genEncPwd } } // 3. 手动调用验证用已知明文 try { const result window.genEncPwd(test123); console.log(Result:, result); // 输出 U2FsdGVkX1... } catch(e) { console.error(Call failed:, e); }这三步确认了window.genEncPwd是目标函数且接受字符串参数返回base64密文。注意这里不追求理解genEncPwd内部如何调用CryptoJS只确认输入输出契约——这就是JS-RPC的起点。3.3 第三步编写JS-RPC调用脚本——处理动态密钥与上下文依赖genEncPwd函数并非纯函数它依赖window.sessionKey由前序请求返回和window.nonce每次刷新生成。因此JS-RPC调用不能写死参数需动态读取// JS-RPC调用脚本保存为 encrypt_call.js (function() { // 1. 检查依赖是否存在 if (!window.sessionKey || !window.nonce) { throw new Error(Missing sessionKey or nonce); } // 2. 构造加密参数对象模拟真实调用 const params { pwd: {{input}}, // Burp将用实际值替换此占位符 key: window.sessionKey, iv: window.nonce.substring(0, 16) // 取前16字节作IV }; // 3. 调用目标函数此处假设genEncPwd接受对象参数 try { return window.genEncPwd(params); } catch (e) { throw new Error(Encrypt failed: e.message); } })();关键点说明{{input}}是Burp的内置占位符Intruder或Repeater中会自动替换为当前payloadwindow.sessionKey和window.nonce在页面加载后即存在无需额外请求整个脚本用IIFE包裹避免污染全局作用域符合CDP最佳实践。3.4 第四步在Burp中配置并测试——三处必填项与一个隐藏坑在Burp中启用JS-RPC调用需在四个位置配置Proxy → Options → Browser勾选“Enable browser for JS-RPC”并确认Chrome路径正确Repeater → Request tab右键enc_pwd字段 → “Send to Intruder” → 在Intruder中切换到“Positions”标签页Intruder → Payloads tab设置Payload type为“Simple list”输入测试密码如admin123、passwordIntruder → Resource tab点击“Add” → 选择“JavaScript RPC” → 粘贴上述脚本 → 点击“Test”验证。注意隐藏坑在于“Test”按钮的验证逻辑。它只检测脚本语法和能否执行不校验返回值是否符合预期。必须手动在Repeater中发送一次查看响应是否为200 OK且返回正常业务数据。我曾因window.nonce在测试时已过期导致JS-RPC返回空字符串而“Test”按钮显示成功浪费了20分钟排查。实测结果当{{input}}为admin123时JS-RPC返回U2FsdGVkX1abc123...与原始请求中enc_pwd值一致证明调用成功。4. 超越单次调用构建可复用的JS-RPC工程化工作流JS-RPC的价值绝不仅限于“这次能调通”。当它被纳入标准化工作流就能释放出指数级效率提升。以下是我在过去17个中大型项目中沉淀出的四步工程化方法。4.1 步骤一建立“加密契约”文档模板——用表格固化关键信息每次发现新目标的前端加密立即新建一个Markdown文档按以下表格填写。这不是形式主义而是为后续自动化铺路字段示例值说明来源方式函数名window.genEncPwd全局可调用的函数标识控制台for...in遍历输入参数{pwd: string, key: string, iv: string}必须传入的参数结构阅读函数源码或console.log(arguments)输出格式base64字符串长度64返回值的编码与长度特征btoa(JSON.stringify(...))或直接返回依赖变量window.sessionKey,window.nonce函数执行必需的全局变量控制台console.dir(window)搜索关键词调用时机表单提交前onsubmit事件函数被触发的上下文DOM事件监听器分析这个表格的好处是当项目交接或复测时新人无需重走逆向流程直接按表配置JS-RPC脚本即可。在某省社保系统渗透中这份文档让团队复用率提升至92%平均单次配置时间从45分钟压缩到6分钟。4.2 步骤二开发通用JS-RPC脚本生成器——用Python自动填充模板手动写JS-RPC脚本易出错尤其参数多时。我用Python写了一个轻量生成器50行输入上述表格内容自动生成可运行脚本def generate_jsrpc_script(func_name, params, dependencies, output_format): # 构建参数对象 param_obj , .join([f{k}: {v} for k, v in params.items()]) # 构建依赖检查 dep_check .join([fwindow.{d} for d in dependencies]) # 生成脚本 script f(function() {{ if (!({dep_check})) {{ throw new Error(Missing dependencies: {, .join(dependencies)}); }} const params {{{param_obj}}}; try {{ return {func_name}(params); }} catch (e) {{ throw new Error(Call failed: e.message); }} }})(); return script # 示例调用 print(generate_jsrpc_script( func_namewindow.genEncPwd, params{pwd: {{input}}, key: window.sessionKey, iv: window.nonce.substring(0,16)}, dependencies[sessionKey, nonce], output_formatbase64 ))运行后直接输出可粘贴到Burp的脚本杜绝手误。这个小工具已集成进我们团队的渗透测试IDEVS Code custom extension一键生成三秒完成。4.3 步骤三在Intruder中实现“加密-爆破”一体化——用Grep Extract提取动态参数JS-RPC调用依赖sessionKey和nonce它们来自前序请求如/api/session。传统做法是手动复制粘贴效率低且易错。Burp的Grep Extract功能可自动提取并注入在Intruder的“Resource”标签页勾选“Extract from response”点击“Add” → 设置Extract ruleName:sessionKeyResponse part:BodyMatch type:TextValue:sessionKey:([^])正则提取在JS-RPC脚本中将window.sessionKey替换为{{sessionKey}}Burp自动替换同理为nonce配置另一条Extract rule。这样Intruder在发送每个爆破请求前会先发一次/api/session提取sessionKey和nonce再注入到JS-RPC脚本中执行加密。整个流程全自动无需人工干预。实测某教育平台登录爆破1000个密码payload总耗时从手动操作的38分钟降至2分17秒。4.4 步骤四防御性测试——用JS-RPC反向验证后端解密逻辑JS-RPC不仅能“调用加密”还能“验证解密”。这是很多测试者忽略的高阶用法用前端加密结果反推后端是否做了正确解密。例如某APP的密码重置接口前端用RSA公钥加密新密码后端用私钥解密。我们怀疑后端未校验PKCS#1 v1.5填充于是这样做用JS-RPC调用window.rsaEncrypt(A*100)得到密文ciphertext1手动构造一个填充错误的密文ciphertext2如将第11字节改为0x00在Repeater中将ciphertext2发给后端观察响应若返回200 OK即后端未校验填充直接解密并存储垃圾数据则确认存在RSA填充 oracle 漏洞。这个思路把JS-RPC从“辅助工具”升级为“漏洞验证探针”在某金融APP中我们正是用此法发现了RSA解密逻辑的严重缺陷最终获得高危漏洞奖励。5. 踩过的坑与血泪经验那些文档里不会写的细节JS-RPC很强大但实战中布满陷阱。以下是我在32个不同技术栈项目中踩出的5个高频坑每个都附带解决方案。5.1 坑一Chrome版本不兼容导致Runtime.evaluate静默失败现象JS-RPC脚本在Burp中“Test”成功但实际调用时返回空或undefined且无任何错误日志。根因Chrome 115版本对CDP的Runtime.evaluate增加了更严格的上下文检查若目标页面启用了Cross-Origin-Opener-Policy: same-originCDP调用会被静默拒绝。解决方案降级Chrome至114.x稳定兼容或在Burp启动Chrome时添加参数--unsafely-treat-insecure-origin-as-securehttp://target.com --user-data-dir/tmp/chrome-test仅测试环境推荐做法用Burp内置BrowserProxy → Options → Browser它会自动适配CDP协议版本规避此问题。5.2 坑二Vue 3的script setup语法导致函数不可访问现象目标是Vue 3 SPAgenEncPwd函数定义在script setup中控制台执行window.genEncPwd报undefined。根因script setup中的变量默认是模块作用域不挂载到window需显式暴露。解决方案在Vue组件中添加defineExpose({ genEncPwd })或改用const genEncPwd defineGlobalProperty(genEncPwd, ...)需Vue 3.3实战技巧若无法修改源码用document.querySelector(body).__vue_app__.config.globalProperties.$encrypt访问需确认Vue实例挂载点。5.3 坑三CryptoJS的parse方法对UTF-8字符串处理不一致现象JS-RPC返回的密文与原始请求不一致差几个字节。根因CryptoJS.enc.Utf8.parse(中文)在不同环境下对Unicode处理有差异而CryptoJS.enc.Base64.stringify()又依赖此结果。解决方案统一使用CryptoJS.enc.Latin1.parse()处理所有输入Latin1可1:1映射字节或在JS-RPC脚本中先用encodeURIComponent编码字符串再CryptoJS.enc.Utf8.parse我的做法在契约文档中强制要求“输入参数必须为ASCII字符串”避免Unicode引发的歧义。5.4 坑四Intruder并发导致nonce重复使用现象Intruder设置10线程爆破部分请求返回nonce expired。根因nonce是单次有效多线程并发时多个JS-RPC调用共享同一个window.nonce值。解决方案将nonce提取逻辑移到JS-RPC脚本内部每次调用时动态生成如Date.now().toString(36)或在Intruder中为每个payload单独发一次/api/nonce请求用Resource池推荐方案改用timestamp作为IV的一部分因其天然唯一且服务端通常允许小范围偏差。5.5 坑五JS-RPC调用超时后Burp未重试导致漏报现象网络抖动时JS-RPC偶尔超时Intruder直接标记为error不重试。根因Burp默认超时5秒且无重试机制。解决方案在JS-RPC脚本开头添加await new Promise(r setTimeout(r, 100));强制等待100ms避开瞬时抖动或在Intruder的“Options”标签页勾选“Request engine” → “Threading” → “Retry on network error”终极方案用Burp Extender写一个简单的重试插件Java/Python捕获JSRPCException后自动重试2次。最后分享一个个人体会JS-RPC不是万能钥匙它解决的是“如何调用”而不是“调用什么”。真正的核心能力永远是你对前端加密逻辑的快速识别与契约抽象能力。我见过太多人花3小时配置JS-RPC却用5分钟就搞懂了加密函数的输入输出——后者才是决定渗透效率的瓶颈。所以别把JS-RPC当成炫技工具把它当作一把放大镜让你更快看清前端加密背后的业务逻辑真相。
http://www.gsyq.cn/news/1364336.html

相关文章:

  • 多模态SLU数据集评估:从任务对话到协作问题解决的演进与挑战
  • kNN×KDE算法:为缺失数据插补提供概率分布,提升天文数据分析可靠性
  • 几何量子机器学习:利用对称性原理破解贫瘠高原与设计高效算法
  • 2026中山市黄金回收门店指南:黄金 白银 铂金 彩金回收五家门店实测及联系方式推荐 - 盛世金银回收
  • 连续处理效应下的双重差分:从二元到连续的范式演进与DML应用
  • 基于图神经网络与LLM的Java空安全注解自动化推断技术解析
  • 别再手动开便签了!Win11开机启动文件夹的‘隐藏’用法与权限绕过实战
  • FreeRADIUS部署实战:从环境准备到动态VLAN分配
  • 2026中卫市黄金回收门店指南:黄金 白银 铂金 彩金回收五家门店实测及联系方式推荐 - 盛世金银回收
  • 量子软件不稳定测试检测:基于机器学习的自动化解决方案
  • 机器学习赋能密度泛函理论:构建半局域交换关联泛函攻克强关联体系
  • 量子机器学习在基因组分类中的实践:特征映射与模型选择指南
  • 2026忻州市黄金回收门店指南:黄金 白银 铂金 彩金回收五家门店实测及联系方式推荐 - 盛世金银回收
  • Win10更新后网卡驱动感叹号?先别重置网络!检查这两个服务项(WLAN AutoConfig/蓝牙支持)
  • 速腾RS-M1雷达点云初体验:Windows 11下用RSView 3.2.7从接线到显示的保姆级避坑指南
  • VMware里CentOS磁盘挂了别急着重装!记一次xfs文件系统修复实战,省下半天配置时间
  • 基于低秩分解与DLinear的流体动力学数据高效预测模型
  • 量子高斯过程在电网参数辨识中的应用:NISQ时代的工程实践
  • 拓扑信号处理进阶:狄拉克方程与IDESP算法解析
  • Windows 11 C盘救星:除了磁盘清理,这3个隐藏设置和命令行技巧能多腾出20G
  • CMS合作组:高能物理大科学协作模式与数据处理技术解析
  • 增长曲线模型缺失数据处理:传统统计方法为何优于机器学习插补?
  • Midjourney对比度黄金公式:Contrast = f(–sref, –style, –iw) × 0.942(基于12,846张生成图回归验证)
  • 2026周口市黄金回收门店指南:黄金 白银 铂金 彩金回收五家门店实测及联系方式推荐 - 盛世金银回收
  • Atmosphère系统架构深度解析:分层安全模型与模块化设计哲学
  • 2026信阳市黄金回收门店指南:黄金 白银 铂金 彩金回收五家门店实测及联系方式推荐 - 盛世金银回收
  • 智能电表数据填补技术对比:从Holt-Winters到Time-MoE的实战指南
  • 子黎曼几何与庞特里亚金原理:约束系统时间最优控制
  • IEMOCAP数据集预处理实战:用Python和Librosa搞定语音情感识别的数据准备
  • 洛雪音乐音源终极指南:3步解锁全网无损音乐资源