同源策略(Same-Origin Policy)是浏览器实施的一项核心安全机制,它限制了一个源(origin)的文档或脚本如何与另一个源的资源进行交互。所谓"同源"指的是协议、域名和端口号完全相同。
同源策略主要影响以下操作:
- AJAX请求
- Cookie、LocalStorage和IndexedDB访问
- DOM访问(iframe间通信)
常见的同源策略绕过技术
1. JSONP (JSON with Padding)
JSONP是一种利用<script>
标签不受同源策略限制的特性实现的跨域通信方法。
javascript
function handleResponse(data) {
console.log('Received data:', data);
}
const script = document.createElement('script');
script.src = 'https://example.com/api?callback=handleResponse';
document.body.appendChild(script);
安全问题:JSONP完全信任第三方服务器返回的内容,容易遭受XSS攻击。
2. CORS (跨源资源共享)
虽然CORS本身是解决跨域问题的标准方法,但配置不当会成为安全漏洞:
javascript
// 不安全的CORS配置示例
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*'); // 允许所有域
res.header('Access-Control-Allow-Methods', '*');
res.header('Access-Control-Allow-Headers', '*');
next();
});
3. postMessage通信
window.postMessage
允许不同源的窗口间安全通信,但使用不当会导致安全问题:
javascript
// 父窗口
childWindow.postMessage('敏感数据', '*'); // 目标origin设为*不安全
// 子窗口
window.addEventListener('message', (event) => {
// 未验证event.origin可能导致数据泄露
console.log(event.data);
});
4. 服务端代理
通过同源服务器转发请求绕过浏览器限制:
javascript
// 前端代码
fetch('/proxy?url=https://external-api.com/data')
.then(response => response.json())
.then(data => console.log(data));
风险:代理服务器可能成为攻击目标或被滥用。
防护措施与最佳实践
1. 安全的CORS配置
javascript
// 安全的CORS配置
app.use((req, res, next) => {
const allowedOrigins = ['https://trusted-site.com', 'https://another-trusted.com'];
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.header('Access-Control-Allow-Origin', origin);
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Credentials', 'true');
}
if (req.method === 'OPTIONS') return res.sendStatus(200);
next();
});
2. 安全的postMessage实现
javascript
// 发送方
const targetWindow = document.getElementById('iframe').contentWindow;
targetWindow.postMessage('敏感数据', 'https://trusted-recipient.com');
// 接收方
window.addEventListener('message', (event) => {
if (event.origin !== 'https://trusted-sender.com') return;
// 处理消息
console.log('安全的消息:', event.data);
});
3. 内容安全策略(CSP)
通过CSP限制可以加载的外部资源:
html
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self' https://trusted-cdn.com;
connect-src 'self' https://api.trusted-domain.com;
frame-ancestors 'none';
">
4. 安全的Cookie设置
javascript
// 服务器设置Cookie时
Set-Cookie: sessionId=abc123; Secure; HttpOnly; SameSite=Strict; Path=/; Domain=example.com
5. 输入验证与输出编码
对所有用户输入进行严格验证,并对输出进行适当编码:
javascript
// 使用DOMPurify清理HTML
const clean = DOMPurify.sanitize(userInput);
// 文本内容编码
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
高级防护技术
1. 子资源完整性(SRI)
确保加载的外部资源未被篡改:
html
<script src="https://example.com/script.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>
2. 沙箱iframe
html
<iframe src="https://untrusted.com"
sandbox="allow-scripts allow-same-origin"
allow="geolocation 'src'">
</iframe>
3. COEP/COOP头
使用新的安全头增强隔离:
javascript
res.header('Cross-Origin-Embedder-Policy', 'require-corp');
res.header('Cross-Origin-Opener-Policy', 'same-origin');
总结
同源策略是Web安全的重要基石,但开发者必须了解其局限性和潜在的绕过方式。通过合理配置CORS、正确使用postMessage、实施严格的内容安全策略以及遵循其他安全最佳实践,可以显著降低跨域安全风险。
安全是一个持续的过程,随着新的Web技术和攻击手段的出现,开发者需要不断更新知识并调整防护策略。始终遵循最小权限原则,只授予必要的访问权限,是保障Web应用安全的关键。