攻击者是如何从JavaScript文件中窃取敏感信息的
字数 1162 2025-08-27 12:33:31
JavaScript文件中敏感信息的安全风险与防护措施
1. 问题概述
在JavaScript文件中存储敏感信息(如API密钥、用户凭证等)是一种极其危险的做法,主要原因包括:
- JavaScript文件是公开可访问的
- 全局作用域中的变量可被任何包含该脚本的网站访问
- 攻击者可以通过多种方式窃取这些信息
2. 常见错误示例
2.1 全局变量存储敏感信息
var api_key = '1391f6bd2f6fe8dcafb847e0615e5b29';
var profileInfo = apiCall('getProfile', api_key, 'all');
这种写法将API密钥暴露在全局作用域中,任何包含此脚本的页面都能访问api_key变量。
3. 作用域与变量声明
3.1 作用域类型
- 全局作用域:变量成为window对象的属性
- 函数作用域:使用
var在函数内声明的变量 - 块级作用域:ES6引入的
let和const
3.2 变量声明方式
| 关键字 | 作用域 | 可重新赋值 | 提升 |
|---|---|---|---|
| var | 函数作用域 | 是 | 是 |
| let | 块级作用域 | 是 | 否 |
| const | 块级作用域 | 否 | 否 |
3.3 严格模式
使用"use strict"可以防止意外创建全局变量:
"use strict";
var test1 = 'arka'; // 正常工作
test2 = 'kapı'; // 抛出ReferenceError
4. 保护变量的尝试与局限
4.1 立即调用函数表达式(IIFE)
(function() {
"use strict";
var privateVar = 'Secret value';
})();
console.log(privateVar); // ReferenceError
虽然IIFE可以避免污染全局命名空间,但不能真正保护敏感数据。
5. 攻击者窃取敏感信息的方法
5.1 覆盖原生函数
window.fetch = (url, options) => {
console.log(`URL: ${url}, data: ${options.body}`);
};
(function() {
"use strict";
var api_key = "1391f6bd2f6fe8dcafb847e0615e5b29";
fetch('/api/v1/getusers', {
method: "POST",
body: "api_key=" + api_key
});
})();
攻击者可以覆盖fetch函数来拦截包含敏感数据的请求。
5.2 定义Setter和Getter
Object.prototype.__defineSetter__('api_key', function(value) {
console.log(value);
return this._api_key = value;
});
Object.prototype.__defineGetter__('api_key', function() {
return this._api_key;
});
(function() {
"use strict";
let options = {};
options.api_key = "1391f6bd2f6fe8dcafb847e0615e5b29";
anotherAPICall(options);
})();
通过定义全局setter,可以记录所有赋值给特定属性名的值。
5.3 自定义迭代器
Array.prototype[Symbol.iterator] = function() {
let arr = this;
let index = 0;
console.log(arr);
return {
next: function() {
return {
value: arr[index++],
done: index > arr.length
}
}
}
};
(function() {
let secretArray = ["this", "contains", "an", "API", "key"];
for(let element of secretArray) {
doSomething(element);
}
})();
通过自定义数组迭代器,可以访问数组中的所有元素。
6. 最佳实践建议
- 永远不要将敏感数据硬编码在JavaScript文件中
- 从服务器动态获取敏感数据:
- 使用安全的API端点
- 实现适当的身份验证和授权机制
- 使用短期有效的令牌而非长期有效的密钥
- 使用服务器端会话管理而非客户端存储敏感信息
- 实施CSP(内容安全策略)限制脚本来源
- 使用HTTP-only、Secure标志的Cookie存储会话标识符
7. 替代方案
当确实需要将某些配置信息传递给客户端时:
- 使用服务器生成的临时令牌而非永久密钥
- 通过meta标签传递非敏感配置:
<meta name="app-config" content="some-non-sensitive-config"> - 使用加密的Web存储(但仍需谨慎)
8. 总结
在客户端JavaScript中保护敏感数据本质上是不安全的,因为:
- 浏览器环境是完全开放的
- 任何包含脚本的上下文都可以被操纵
- 有多种技术可以绕过看似安全的封装
唯一可靠的安全策略是完全不将敏感数据暴露给客户端,所有敏感操作都应通过安全的服务器端API进行。