LinkFinder:基于正则表达式的JavaScript端点探测工具原理与实战

📅 2026/7/6 9:32:59
LinkFinder:基于正则表达式的JavaScript端点探测工具原理与实战
1. 项目概述为什么我们需要一个“JavaScript端点探测器”在渗透测试、安全审计或者仅仅是日常的Web应用分析中我们常常会遇到一个棘手的问题目标应用的功能接口API端点到底藏在哪里现代Web应用尤其是单页应用SPA其核心业务逻辑和大量的数据交互接口往往都打包在那些动辄几兆、经过压缩和混淆的JavaScript文件里。手动去翻阅这些代码无异于大海捞针效率极低且容易遗漏关键信息。这就是LinkFinder诞生的背景。它不是一个复杂的漏洞扫描器而是一个非常精准的“端点探测器”。它的任务很纯粹像一台高精度的金属探测器在JavaScript代码的沙滩上把所有看起来像URL、路径、API接口的“金属碎片”都给你找出来并清晰地陈列在你面前。无论是完整的https://api.target.com/v1/user还是相对路径/admin/panel甚至是RESTful风格的api/products/123都逃不过它的眼睛。我最初接触它是在一次对某大型Web应用进行资产梳理时手动翻JS文件翻到眼花直到用了LinkFinder几分钟内就整理出了上百个潜在接口其中不乏一些未在公开文档中提及的“隐藏”管理端点为后续的测试打开了突破口。对于安全研究员、渗透测试工程师和开发人员尤其是做API集成或逆向分析的来说这绝对是一个能极大提升效率的“瑞士军刀”。2. 核心原理深度拆解正则表达式如何成为“火眼金睛”LinkFinder的核心战斗力几乎全部来自于其精心设计的一套正则表达式。很多人把它当黑盒工具用输入输出就完事了但理解其内在的匹配逻辑不仅能让你用得更得心应手还能在它“失手”时知道问题可能出在哪里甚至自己动手调整规则。它的匹配引擎主要由四组核心正则表达式构成分别针对不同形态的端点。我们不妨把它想象成一个有四层滤网的筛子每一层负责捕捉特定大小的“鱼”。2.1 第一层滤网捕获完整的网络地址这层网眼最大目标是捞起那些带有完整协议和域名的“大鱼”也就是我们一眼就能认出的URL。((?:[a-zA-Z]{1,10}://|//) [^/]{1,}\. [a-zA-Z]{2,}[^]{0,})我们来拆解一下(?:[a-zA-Z]{1,10}://|//)这是一个非捕获分组匹配两种开头。一是像http://、https://、ftp://这样的协议头协议名长度1到10个字母。二是双斜杠//这是协议相对URL比如//cdn.example.com/lib.js它会继承当前页面的协议http或https。[^/]{1,}\.匹配域名主体。[^/]表示匹配任何不是引号或斜杠的字符这样可以确保域名不会错误地包含进路径分隔符或字符串结束符。最后必须跟一个点.用于分隔域名和顶级域。[a-zA-Z]{2,}[^]{0,}匹配顶级域如.com,.io及其之后的路径、查询参数等。[a-zA-Z]{2,}确保顶级域至少两个字母排除了单个字符的误匹配。[^]{0,}会一直匹配到遇到引号或字符串结束为止从而抓取完整的URL。实战心得这层规则非常有效但要注意它可能会匹配到一些注释中举例的URL如// example.com或硬编码在字符串里的图片、字体等静态资源CDN地址。这些虽然不是API端点但对于绘制完整的应用外部依赖图很有帮助。2.2 第二层滤网抓取绝对与相对路径当URL不以协议开头时它很可能是一个站内路径。这层滤网专门捕捉这些。((?:/|\.\./|\./) [^,;| *()(%%$^/\\\[\]] [^,;|()]{1,})(?:/|\.\./|\./)匹配路径的开头。可以是根路径/上级目录../或者当前目录./。这覆盖了绝大多数相对路径的写法。[^,;| *()(%%$^/\\\[\]]这是一个关键的“首字符过滤器”。它定义了路径的第一个字符不能是什么。这个列表包含了HTML标签符()、命令分隔符(;,|)、空格、括号以及一些特殊符号。这个设计非常精妙它能有效过滤掉大量看起来像路径但不是路径的代码片段比如函数调用func(、比较运算a b等极大减少了误报。[^,;|()]{1,}匹配路径的剩余部分同样要避开那些可能表示字符串结束或代码逻辑的特殊字符。注意事项这个规则对于现代前端路由中常见的、不带文件扩展名的路径如/dashboard/user/profile匹配得很好。但它可能无法完美处理所有边缘情况比如路径中包含编码后的特殊字符。2.3 第三层滤网锁定带扩展名的资源文件Web应用中有大量具体的资源文件如.js、.css、.json、.png等。这层滤网的目标就是它们。([a-zA-Z0-9_\-/]{1,}/ [a-zA-Z0-9_\-/.]{1,} \.(?:[a-zA-Z]{1,4}|action) (?:[\?|#][^|]{0,}|))[a-zA-Z0-9_\-/]{1,}/匹配目录路径允许字母、数字、下划线、中划线和斜杠。[a-zA-Z0-9_\-/.]{1,}匹配文件名允许包含点.这能兼容类似index.min.js这样的文件名。\.(?:[a-zA-Z]{1,4}|action)匹配点号加上扩展名。扩展名可以是1到4个字母如jsjsonhtml或者特殊的action常见于一些Java Web框架。(?:[\?|#][^|]{0,}|)非捕获分组匹配可选的查询字符串?paramvalue或URL片段标识符#section或者什么都没有。常见问题这个规则假设文件路径中至少包含一个斜杠/。这意味着它可能会漏掉那些直接在根目录下引用的文件比如script.js。不过在实际的、模块化的前端代码中资源文件通常都有一定的目录结构所以这个假设在大多数情况下是成立的。2.4 第四层滤网嗅探RESTful API端点现代API设计特别是RESTful风格其端点往往没有文件扩展名而是由路径和资源标识符组成。这是LinkFinder最值得称道的部分之一。([a-zA-Z0-9_\-/]{1,}/ [a-zA-Z0-9_\-/]{3,} (?:[\?|#][^|]{0,}|))[a-zA-Z0-9_\-/]{1,}/同样是匹配API的路径前缀比如api/v1/。[a-zA-Z0-9_\-/]{3,}关键在这里。它要求路径的最后一段资源标识符至少要有3个字符。这是一个非常聪明的启发式规则。因为像/a、/b这样的单字符或双字符片段在JS代码中有极高概率是变量名、参数名而非API路径例如function get(a, b)。这个简单的长度限制过滤掉了海量的误报。(?:[\?|#][^|]{0,}|)同上用于捕获查询参数。实操心得这个“至少3个字符”的规则是平衡召回率和精确度的艺术。在实际使用中它极大地提升了结果的信噪比。你会发现它找出来的/api/users/12345、/v2/config/security这类端点十有八九就是真正的后端接口。3. 从安装到实战手把手玩转LinkFinder理解了原理我们来看看怎么把它用起来。整个过程非常轻量几乎没有环境依赖的烦恼。3.1 环境准备与安装LinkFinder基于Python 3所以首先确保你的系统里有Python 3和pip。安装过程就是标准的Git克隆和Python包安装流程。# 1. 克隆仓库 git clone https://github.com/GerbenJavado/LinkFinder.git # 如果GitHub访问慢可以使用国内的镜像源例如 # git clone https://gitcode.com/gh_mirrors/li/LinkFinder.git # 2. 进入工具目录 cd LinkFinder # 3. 安装工具本身将其安装为可全局调用的Python模块 python3 setup.py install # 4. 安装依赖库主要是jsbeautifier用于格式化混淆的JS代码 pip3 install -r requirements.txt安装完成后你可以在命令行直接输入linkfinder来验证是否成功。如果显示帮助信息说明安装无误。注意我强烈建议在虚拟环境如venv或conda中完成安装避免污染系统的Python环境。使用python3 -m venv linkfinder-env创建并激活虚拟环境后再执行上述步骤。3.2 基础用法与核心参数解析LinkFinder的命令行界面很简洁核心参数不多但组合起来威力很大。场景一分析单个JS文件这是最直接的用法。你可以分析一个本地文件也可以直接给它一个网络URL。# 分析本地JS文件结果输出到同目录下的results.html linkfinder -i ./static/main.bundle.js -o results.html # 分析远程JS文件 linkfinder -i https://target.com/assets/app.js -o cli-i (--input)指定输入源。可以是本地文件路径也可以是URL。-o (--output)指定输出。可以是cli在终端打印也可以是一个文件名如results.html工具会生成一个带有高亮和上下文预览的HTML报告。生成的HTML报告是其一大亮点。它不仅仅列出端点还会展示该端点在JS代码中原生的上下文前后几行代码这对于判断该端点的用途是登录接口、数据获取接口还是配置接口至关重要。场景二递归抓取整个域名的JS文件这是真正的“大杀器”。-d参数会让LinkFinder先爬取目标首页提取所有JS文件链接然后逐个分析。linkfinder -i https://target.com -d -o target_scan.html这个过程可能会发出大量网络请求速度取决于目标网站的规模和网络状况。务必在获得授权的前提下进行。同时有些网站可能有反爬机制需要适当调整速度或配合代理使用。场景三精准过滤结果分析大型应用可能会得到成百上千个端点其中很多可能是静态资源。-r参数允许你用正则表达式对结果进行过滤只保留你关心的。# 只关心以 /api/ 开头的端点 linkfinder -i https://target.com -d -o cli -r ^/api/ # 只关心包含 admin、manage、config 等敏感关键词的端点 linkfinder -i ./js_files/ -o cli -r (admin|manage|config|backup|test)这里的-r参数接的是一个Python风格的正则表达式。掌握一点基本的正则能让你在结果挖掘时事半功倍。3.3 高级技巧与组合拳单纯使用LinkFinder已经很强但如果能把它嵌入到你自己的工作流中或者与其他工具结合效率还能再上一个台阶。技巧一批量处理本地JS文件有时我们通过其他方式如爬虫工具gau、waybackurls或浏览器开发者工具手动保存已经下载了一堆JS文件到本地一个目录。# 使用find命令配合LinkFinder批量分析当前目录及子目录下所有.js文件 find . -name *.js -exec linkfinder -i {} -o cli \;这样会逐个分析并输出结果会混在一起。更好的做法是写一个简单的Shell脚本将每个文件的输出重定向到独立的文件或者先合并所有JS内容。# 将所有JS文件内容合并到一个大文件中然后一次性分析注意文件可能很大 cat *.js all_js_combined.js linkfinder -i all_js_combined.js -o combined_results.html技巧二与子域名枚举工具联动在渗透测试的信息收集阶段我们常会先枚举目标的子域名。可以将子域名枚举的结果作为LinkFinder的输入进行批量的端点发现。假设你使用subfinder和httpx获得了存活的子域名列表alive_subs.txt# 一个简单的循环示例需根据实际情况调整并注意速率限制 for url in $(cat alive_subs.txt); do echo [*] Scanning $url; linkfinder -i $url -d -o cli all_endpoints.txt 2/dev/null; done这个脚本会遍历每个存活的子域名进行递归JS分析并将所有结果追加到all_endpoints.txt中。务必谨慎使用避免对目标造成负载压力。技巧三结果后处理与去重LinkFinder本身有基础去重但有时我们还需要更精细的处理。比如将结果中的相对路径根据其来源URL补全为绝对路径。# 一个简单的Python后处理脚本示例 import re base_url https://target.com with open(linkfinder_raw_output.txt, r) as f: endpoints set(f.readlines()) # 用集合自动去重 processed set() for endpoint in endpoints: endpoint endpoint.strip() if endpoint.startswith(http): processed.add(endpoint) elif endpoint.startswith(/): processed.add(base_url.rstrip(/) endpoint) elif endpoint.startswith(./): # 这里需要更复杂的逻辑来处理相对路径示例简化处理 processed.add(base_url endpoint[1:]) # 可以添加更多判断... for url in sorted(processed): print(url)这个脚本可以将形如/api/user的路径补全为https://target.com/api/user便于后续直接用于测试。4. 实战案例剖析从JS文件到攻击面地图我们模拟一个完整的微型实战场景看看如何将LinkFinder的发现转化为实际的测试线索。目标一个假设的在线笔记应用noteapp.demo。步骤初始访问打开https://noteapp.demo。用浏览器开发者工具的Sources面板或Network面板观察加载了哪些JS文件。假设发现主应用文件是https://noteapp.demo/static/app.abc123.js。初步扫描linkfinder -i https://noteapp.demo/static/app.abc123.js -o initial_scan.html打开initial_scan.html我们可能看到诸如/api/notes,/api/users/profile,/static/config.json等端点。深度递归扫描linkfinder -i https://noteapp.demo -d -o deep_scan.html这次扫描会爬取首页发现更多JS文件比如vendor.chunk.js、admin.panel.js假设存在。报告会丰富得多。结果分析与过滤用户功能相关/api/notes(GET/POST),/api/notes/{id}(GET/PUT/DELETE),/api/notes/search?q身份认证相关/api/login,/api/register,/api/logout,/api/session管理功能相关关键发现在admin.panel.js的上下文中发现了/admin/api/users(GET),/admin/api/users/{id}/disable(POST),/admin/system/config。内部调试接口高危发现在某个JS的注释或未使用的代码段里发现了/debug/console和/api/v1/test/clear_cache。构建攻击面地图 将以上发现分类整理认证模块登录、注册、会话管理端点。可测试暴力破解、会话固定等。核心业务模块笔记CRUD增删改查接口。可测试权限绕过如未授权访问他人笔记、SQL/NoSQL注入、XSS等。管理后台模块用户管理、系统配置接口。这些通常是高权限接口需要重点测试垂直越权普通用户能否访问。隐藏/调试接口/debug/console可能是一个Web Shell或诊断界面/api/v1/test/clear_cache可能是一个未移除的测试接口存在SSRF或DoS风险。制定测试策略 根据整理的端点优先测试高危和高权限接口。例如直接尝试访问/admin/api/users看是否在未登录或普通用户权限下返回数据越权漏洞。用Burp Suite或Postman对/api/notes进行参数模糊测试注入漏洞。通过这个流程LinkFinder帮助我们将杂乱无章的JS文件转化为了一个结构清晰、优先级分明的“API攻击面地图”使得后续的渗透测试工作能够有的放矢高效深入。5. 避坑指南与效能提升技巧任何工具都有其局限性和使用技巧LinkFinder也不例外。下面是我在大量使用中总结的一些“坑”和“捷径”。5.1 常见问题与解决方案问题1扫描大型网站时卡住或输出混乱。原因-d递归模式会爬取页面并查找JS链接如果网站规模大、结构复杂或网络不佳过程会很长。终端直接输出(-o cli)可能因为数据太多而滚动过快。解决使用HTML输出始终使用-o scan.html结果更清晰易读。限制范围如果知道JS文件大概在哪个路径下可以先手动收集JS文件URL然后用文件列表作为输入避免爬取整个站。分而治之针对不同的子域名或路径分别扫描最后合并结果。问题2误报太多比如匹配到了代码中的变量名或字符串片段。原因正则表达式再精密也无法100%准确尤其是一些短的、像路径的字符串如变量名apiUrl 字符串”/a/b”但被拆分行。解决善用-r过滤用正则过滤掉明显不是端点的结果例如-r ‘^(https?://|/api/|/v[0-9]/)’只保留HTTP(S)开头的或类似API的路径。人工复审上下文HTML报告提供了代码上下文这是区分误报和真端点的最关键依据。一个真正的API端点其上下文通常会有fetch,axios,$.ajax,url:,endpoint:等关键词。理解规则局限记住第四层滤网3字符规则已经过滤了大量误报。如果仍有大量单字符误报可能是代码格式特殊可以考虑轻微调整正则高级用法需修改源码。问题3漏报有些明显的端点没找到。原因端点被动态拼接例如var endpoint “/api/” resource “/” id;。LinkFinder基于静态正则匹配无法解析这种运行时拼接的字符串。代码极度混淆或加密字符串被编码如Base64、加密或拆分成碎片在静态分析下不可读。端点存储在JSON配置或后端渲染端点可能不在JS里而是在HTML的meta标签、初始化的全局变量window.CONFIG中或者由后端直接注入到模板。解决动态分析配合浏览器自动化工具如Puppeteer, Playwright在页面加载后执行提取网络请求。这样可以捕获所有实际发出的请求包括动态拼接的。代码审计对于重要目标静态分析工具只是辅助最终仍需人工审计关键JS文件寻找字符串拼接模式。多源收集不要只依赖JS文件。同时使用爬虫抓取所有HTML页面提取表单action、链接href检查浏览器开发者工具Network面板的所有XHR/Fetch请求。5.2 高阶效能提升技巧技巧一优化正则表达式针对特定目标如果你发现目标网站有独特的端点命名风格比如所有内部API都以/internal/开头你可以直接修改linkfinder.py中的正则表达式添加一条专属规则以提高命中率和准确性。但这需要一定的Python和正则表达式知识。技巧二集成到自动化扫描流水线将LinkFinder作为你信息收集自动化脚本中的一个环节。例如子域名枚举 - 2. 存活探测 - 3. 爬取每个存活域的JS文件链接 - 4. 用LinkFinder分析所有JS文件 - 5. 结果去重、补全、分类 - 6. 导入到漏洞扫描器或手动测试工具中。技巧三关注“上下文”中的秘密LinkFinderHTML报告中的“上下文”栏价值极高。除了看端点本身更要看它周围的代码HTTP方法附近是否有method: ‘POST’、type: ‘DELETE’请求头是否有headers: {‘Authorization’: ‘Bearer …’}这里可能泄露硬编码的令牌或认证方式。参数是否有data: {username: …, password: …}这直接指明了请求体结构。注释JS注释中可能包含开发者留下的说明如// TODO: Remove this debug endpoint before production。6. 与其他工具对比及选用建议LinkFinder并非市场上唯一的JS端点提取工具。了解它的“兄弟姐妹”有助于你在不同场景下做出最佳选择。工具名称语言核心特点优点缺点适用场景LinkFinderPython基于多组精密正则的静态分析提供代码上下文。精度高误报相对少HTML报告直观规则设计巧妙如3字符规则。无法处理动态拼接纯静态分析。快速、精准地梳理已知JS文件中的端点用于手动审计和攻击面绘制。JSFinderPython通过递归爬取页面提取JS链接并分析也支持从JS中提取子域名。更侧重于信息收集的自动化集成了爬取和简单分析。提取端点的正则规则可能不如LinkFinder全面和精确。需要全自动收集JS文件并初步分析作为资产发现的一部分。Burp Suite 插件 (JS Link Finder)Java (Burp)作为Burp Suite的插件在代理流量中自动分析JS响应。无缝集成到代理工作流可分析经过Burp的所有JS能与Burp的其他工具联动。依赖Burp环境可能增加Burp内存占用。在主动代理测试过程中实时、被动地发现端点无需额外步骤。浏览器控制台手动提取-在浏览器Console中执行自定义JavaScript代码来提取端点。最灵活可以编写复杂逻辑处理动态拼接、解析特定框架结构。完全手动效率低需要较高的JS知识。针对极端混淆、加密或特定框架如React, Vue的应用进行深度定制化分析。选用建议日常快速审计首选LinkFinder。给你一个JS文件或URL快速出结果报告漂亮精度够用。集成到自动化资产测绘流水线可以考虑JSFinder或自己用LinkFinder写脚本包装。正在进行的手动渗透测试务必加载Burp Suite 的 JS Link Finder 插件。让它在你浏览网站时在后台默默工作不断丰富你的目标站点地图。遇到“硬骨头”当上述工具都失效时回到本源打开浏览器开发者工具使用Console手动提取。可以尝试搜索fetch、axios、XMLHttpRequest、endpoint、url等关键词或者检查window全局对象下的配置。LinkFinder在我个人的工具链中始终占据着一个“先锋侦察兵”的位置。它不负责直接攻击但它提供的精准情报是后续所有深度测试的基石。花点时间掌握它理解它的原理和脾气能让你的Web安全测试工作从一开始就赢在起跑线上。