同源策略的绕过与防护

同源策略(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应用安全的关键。