文章总结: 这篇文章介绍了一种在未授权访问漏洞测试中提取JavaScript文件参数的方法。作者开发了一个浏览器插件,通过正则表达式匹配9种不同的代码场景,从JS文件中提取参数名,包括对象属性名、解构变量、函数参数、API请求参数等。文章还介绍了智能分类机制、参数过滤机制和Fuzz-Payload构造等功能,帮助安全研究人员快速找到未授权接口的参数,提高漏洞挖掘效率。作者表示该插件将在内部测试后发布到GitHub上。
综合评分: 91
文章分类: WEB安全,渗透测试,漏洞分析,安全工具,安全开发
未授权接口构造思路拓展 | JavaScript中的参数提取实现与插件开发
原创
庆尘
Daylight庆尘
2025年10月26日 21:09
重庆
01
一、引言
对于未授权访问漏洞的测试来说,最常遇到的问题就是找不到这个接口的参数和找不到这个参数的值,那找参数的值就不用说。比较依靠爆破技巧以及对业务参数的熟悉程度。例如经常挖某一家厂商,那大概率就知道这个参数的实际意义,以及应该去哪里寻找。但参数名的寻找,却是一个比较难解决的问题
先来看看构造接口后出现的几种情况
第一种就是明确的缺参数回显,这种自然很简单,直接根据提示来构造参数即可
还有第二种,会特殊一点,也是明确的缺参数回显,但回显的是中文参数名,这个会稍微难一点点,需要结合业务,结合系统参数名命名规律和Js对应代码块写法来构造传参。例如
HTTP/2 200 OKDate: Sun, 26 Oct 2025 09:16:25 GMTVary: Access-Control-Request-Headers
{"result":null,"returnMsg":"客户服务号不能为空"}
第三种就比较复杂,仅给你说参数错误,但不会有任何明确提示,如下
这种时候比较常见的处理思路是
常见处理思路
1、Js查看接口对应代码块位置,是否写明参数
2、收集历史数据包参数对该接口的参数名进行Fuzz
3、根据接口名猜测,例如queryInfobypid,那么参数大概率会跟pid有关
4、猜测常见参数,例如List接口的pageNo,pageSize等
但很多情况下,Js对应代码块位置是不会携带参数的,并且由于我们是进行的未授权访问漏洞挖掘,并没有太多正常的业务数据包,也无法从历史数据包中提取Fuzz字典,当这时候通过接口名也无法猜测参数时,我们还能有什么办法呢?
这时候我的想法是,既然Js文件中接口对应代码块位置没有写明参数,那会不会在Js文件的某个位置是写了这个参数名的呢,仔细一想,其实这是非常有可能的。所以针对上面的第三种情况,我们现在多了一个处理方法,那就是提取整个Js文件的参数
02
二、Js文件参数提取
既然要提取整个Js文件的参数,这个工程量肯定比较大,所以我首选编写浏览器插件,通过正则实现常见代码块场景覆盖。那现在我们的问题就是让匹配规则尽可能多的覆盖Js文件中携带参数的代码块
为此,我将js文件中所带参数的常见代码块形式进行了分类,并进行分别处理,如下
1、对象属性名提取
用于匹配较为常见的对象属性名场景
// 场景1.1: 普通对象字面量const user = { userId: 123, // ✅ 提取: userId userName: "john", // ✅ 提取: userName email: "[email protected]" // ✅ 提取: email};
// 场景1.2: 字符串键对象const config = { "apiKey": "abc123", // ✅ 提取: apiKey 'secret': "xyz789", // ✅ 提取: secret "maxRetries": 3 // ✅ 提取: maxRetries};
// 场景1.3: 嵌套对象const appConfig = { apiUrl: "https://api.example.com", // ✅ 提取: apiUrl timeout: 5000, // ✅ 提取: timeout settings: { // ✅ 提取: settings theme: "dark", language: "en" }};
插件实践效果如下,成功提取到测试用例中14个完整参数
2、解构变量提取
这个主要是用于对一系列结构场景进行处理,例如重命名,默认值等,测试用例如下
// 场景2.1: 简单解构const { userId, userName, profile } = user;// ✅ 提取: userId, userName, profile
// 场景2.2: 重命名解构const { apiKey: key, secret, maxRetries } = config;// ✅ 提取: key, secret, maxRetries
// 场景2.3: 默认值解构const { category = "default", status = "active" } = options;// ✅ 提取: category, status
这个的关键点在于要能识别 key: alias 格式,并且一次性提取解构中的所有变量和别名
插件实现效果如下,成功提取测试用例中8个参数名
3、嵌套解构提取
这种场景主要是为了匹配深层嵌套或者混合嵌套,代码示例如下
// 场景3.1: 单层嵌套解构const { settings: { theme, language } } = userConfig;
// ✅ 提取: theme, language, settings// 场景3.2: 多层嵌套解构const { profile: { personalInfo: { firstName, lastName } }} = complexUser;// ✅ 提取: firstName, lastName, profile,personalInfo
// 场景3.3: 混合嵌套解构const { settings: { theme, language }, preferences: { notifications } } = userConfig;// ✅ 提取: theme, language, notifications,preferences
这里要使用多个捕获组处理多个嵌套块,共11个参数,去重之后为9个参数,来看看插件效果
可以看到完美进行了匹配,结果确实是9个参数
4、函数参数提取
这种场景就非常常见了,直接去匹配Js中的函数参数,示例代码如下
// 场景4.1: 普通函数参数function getUser(userId, userName, includeProfile = false) { // ✅ 提取: userId, userName, includeProfile}// 场景4.2: 箭头函数参数const updateUser = (id, data, options = {}) => { // ✅ 提取: id, data, options, updateUser};// 场景4.3: 参数解构function createUser({ name, email, age = 18, preferences = {} }) { // ✅ 提取: name, email, age, preferences}// 场景4.4: 嵌套参数解构const processOrder = ({ orderId, items, shipping}) => { // ✅ 提取: orderId, items, shipping, processOrder};
插件效果如下,成功完整提取15个目标参数
5、变量赋值提取
这个就是用来匹配Js中的多种赋值场景,例如
// 场景5.1: 变量声明const authToken = "abc123"; // ✅ 提取: authTokenlet pageSize = 20; // ✅ 提取: pageSizevar maxRetries = 5; // ✅ 提取: maxRetriesconst searchQuery = "javascript"; // ✅ 提取: searchQuery
// 场景5.2: 赋值语句currentPage = 1; // ✅ 提取: currentPagetotalItems = 100; // ✅ 提取: totalItemsfilterValue = "active"; // ✅ 提取: filterValue
// 场景5.3: const config = { key: "value" }; // ✅ 提取: key,config
插件实践效果如下,成功完全覆盖测试用例中9个目标参数
6、API请求参数提取
API请求的场景,相对来说在实战中遇到的会比较多,师傅们看到应该也会比较熟悉,就是下面这种
// 场景6.1: Fetch APIfetch('/api/users', { method: 'POST', // ✅ 提取: method headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token // ✅ 提取: Authorization }, body: JSON.stringify({ // ✅ 提取: body name: "John", // ✅ 提取: name age: 25, // ✅ 提取: age email: "[email protected]" // ✅ 提取: email })});// 场景6.2: Axiosaxios.post('/api/login', { username: "admin", // ✅ 提取: username password: "123456", // ✅ 提取: password rememberMe: true // ✅ 提取: rememberMe});
插件匹配效果如下
7、URL参数提取
这种也是非常常见的场景,特别是对于很多习惯用分段式JS(即baseurl+接口)的厂商来说,这上面能提取的参数信息是非常多的
// 场景7.1: URL查询字符串const url1 = '/api/users?page=1&limit=10&search=keyword';// ✅ 提取: url1,page, limit, search
// 场景7.2: URLSearchParamsconst params = new URLSearchParams(); // ✅ 提取: paramsparams.set('category', 'books'); // ✅ 提取: categoryparams.append('sort', 'price'); // ✅ 提取: sortparams.append('order', 'asc'); // ✅ 提取: order
// 场景7.3: 模板字符串URLconst apiUrl = `/api/search?ql=${query}&page=${pageNumber}&sort=${sortBy}`;// ✅ 提取: apiUrl, ql, pageNumber, sortBy// 场景7.4: 动态URL构建url.searchParams.append('minPrice', '0'); // ✅ 提取: minPriceurl.searchParams.append('maxPrice', '100'); // ✅ 提取: maxPrice
在实现该匹配的时候,要精确匹配 ? 和 & 后的参数名,同时也要支持支持 URLSearchParams 的 set/append 方法以及模版字符串中的动态参数
插件实现效果:完美匹配到测试用例中12个参数名
8、配置对象提取
该功能主要用于匹配Js配置代码中的参数
// 场景8.1: 配置对象const appConfig = { // ✅ 提取: appConfig apiUrl: "https://api.example.com", // ✅ 提取: apiUrl timeout: 5000, // ✅ 提取: timeout retryCount: 3, // ✅ 提取: retryCount cacheEnabled: true // ✅ 提取: cacheEnabled};// 场景8.2: 请求配置const requestOptions = { // ✅ 提取: requestOptions headers: { 'Authorization': 'Bearer token123', // ✅ 提取: Authorization 'APIKey': 'key456' // ✅ 提取: APIKey }, query: { // ✅ 提取: query include: 'profile,settings', // ✅ 提取: include fields: 'name,email,avatar' // ✅ 提取: fields }};// 场景8.3: 方法选项user.find({ where: { // ✅ 提取: where status: 'active', // ✅ 提取: status role: 'user' // ✅ 提取: role }, limit: 50, // ✅ 提取: limit offset: 0 // ✅ 提取: offset});
插件实现效果如下
9、路由参数提取
这种路由参数场景在我们的路由测试中是非常常见的,这也是fd结果筛选中需要进行处理的路径,主要适配了几个常见的前端框架,如下
// 场景9.1: Express.js 路由app.get('/api/users/:userId', (req, res) => {});// ✅ 提取: userIdapp.put('/api/products/:productId/reviews/:reviewId', (req, res) => {});// ✅ 提取: productId, reviewId// 场景9.2: React Routerconst routes = [ { path: '/user/:userId', // ✅ 提取: userId element: <UserProfile /> }, { path: '/products/:category/:productId', // ✅ 提取: category, productId element: <ProductDetail /> }];// 场景9.3: Vue Routerconst routes = [ { path: '/user/:userId/profile', // ✅ 提取: userId component: UserProfile }];// 场景9.4: Next.js 动态路由// pages/user/[userId].js // ✅ 提取: userId// pages/blog/[slug]/comments/[commentId].js // ✅ 提取: slug, commentId// 场景9.5: 其他框架const routes = { '/user/{userId}': UserPage, // ✅ 提取: userId '/api/v1/orders/{orderId}/items/{itemId}': OrderItemsAPI // ✅ 提取: orderId, itemId};
插件效果如下,效果依旧ok
现在我们实现了对Js文件中参数名的大致提取,当前的问题是如何把提高提取的准确率,并把参数作为利用到后续的未授权测试流程的参数fuzz中
03
三、智能分类机制
考虑到很多时候我们找参数其实是有针对性的,比如找分页参数,找id参数等等,所以对参数提取结果添加分类和评分机制,方便用户快速查找指定类别代码(仅通过参数名判断)
现有的大致特殊用途分类为认证参数,ID参数,状态参数,时间参数和分页参数
例如某个接口出现大量数据,此时用户想寻找分页参数,就可以进行快速筛选。插件效果实现如下
04
四、参数过滤机制
由于Js中提取的结果异常庞大,通常一个大型Js文件,提取的参数结果会达到2000个左右,其中不可避免会出现误报或垃圾数据,所以我们得对提取的结果进行一系列限制,防止匹配到大量的脏数据
即进行长度限制,黑名单匹配,标识符规则匹配等等一系列措施(注意:此处我过滤了带有下划线的参数,并将其认定为不是合法参数,但实际有的站点是存在这种参数的,只是概率较小,但匹配之后会带来大量的误报,所以我依然选择了不匹配)所以遇到参数带有下划线的站点时谨慎使用
代码实现如下
最后进行单字黑名单判段和结果去重,进一步优化输出结果
05
五、Fuzz-Payload构造
该插件的主要目的是帮助用户寻找接口的参数,所以需要对结果进行自定义处理,主要就是提供构造键值对传参和Json传参的选项,例如匹配结果为
categorycomponentelementitemIdorderIdpathproductIdresreviewIdroutesuserId
则键值对构造结果如下
category=1&itemId=1&orderId=1&productId=1&reviewId=1&userId=1&component=1&element=1&path=1&res=1&routes=1
JSON体构造结果如下
{ "category": "1", "component": "1", "element": "1", "itemId": 1, "orderId": 1, "path": "1", "productId": 1, "res": "1", "reviewId": 1, "routes": "1", "userId": 1}
特别是JSON,传递不正确的参数并不会导致报错,这样用户就能快速判断匹配结果中是否包含对应接口的所需参数
06
六、GET-payload优化
那现在新的问题又来了,上面也说了,大型Js文件,提取的参数一般在2000个左右,这样构造为POST-JSON的请求其实是没有问题的,因为post请求理论上是没有长度限制的,所以并不会影响效果,如下
可以看到两千多行的请求体,接口仍然正常接受参数并执行逻辑,不会产生任何回显
但此处的问题是get传参,当参数过多时就会出现问题,例如
可以看到,出现了413错误,即长度过长
对于这个问题,首先想到的是提供给用户分批构造的选项,但仔细想了下,分批构造还不如用户复制全部之后,自己到txt多分几组自己测试。
所以我这里的解决方案是,引入参数分类时的参数评分机制,形成一个高价值参数列表,用户在构造GET时,可以选择构造所有(如果太长的话,智能自己拿到txt里多分几段),也可以选择仅构造高价值参数列表,插件设计UI如下
构造所有:
仅构造高优先级参数:
高优先级通常只有一两百个参数,这样是不会出现413错误的,如下,接口仍正常回显
07
七、文末总结
至此,我们针对JS文件中参数名提取的参数开发已经完成的差不多了,我自己初步使用下来效果是没问题的,能找到一些之前自己不可能找到的接口参数,但注意一个问题——从JS文件中提取参数只是找参数的其中一个方法,并不是接口写在这个JS文件中,接口的参数就一定也在这个JS文件中,不过很多时候是可以找到的
接下来会优先进行团队内部测试,看看内部的师傅们在使用时有没有什么问题和建议,针对性优化一下Bug或功能,过一段时间后会放到Github上供有需要的师傅们下载使用,也希望能让师傅们挖到更多的洞
总之在我看来,JS文件是Web测试中最大的宝藏资源。特别是对于未授权访问来说,可以从里面提取的信息太多太多。而我们要做的就是不断剖析JS文件,想方设法从中提取所有对我们测试有用的信息。最后,欢迎有问题或建议的师傅们一起交流
END
混口饭打个广:
本人亲带SRC课程,想咨询课程的师傅可以来联系我哈,支持随时插班
别让”入门慢”拖慢你的脚步|庆尘Src三期课程来袭——聚焦独家漏洞挖掘技巧
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:Daylight庆尘 庆尘《未授权接口构造思路拓展 | JavaScript中的参数提取实现与插件开发》