改用createElement替代模板字面量能否防范信使应用XSS风险?
解决信使应用的XSS问题:改用createElement可行吗?
你的信使应用当前通过模板字面量结合insertAdjacentHTML渲染对话,导致last_message.text中的恶意HTML/脚本被解析执行,引发XSS风险。应用仅支持纯文本消息,需要彻底阻断富内容渲染。
示例恶意消息
var app = document.querySelector('body'); app.innerHTML = '<img src="x" onerror="alert(1)">';
当前存在风险的渲染代码
renderDialogs: () => { const dialogList = document.getElementById('dialogsList'); dialogList.textContent = ''; const df = document.createDocumentFragment(); dialogs.list.forEach( ({ id, created, modified, username, other_user_id, unread_count, last_message, }) => { const btn = document.createElement('button'); btn.classList = 'list-group-item list-group-item-action list-group-item'; btn.dataset.username = username; btn.dataset.userId = other_user_id; const btnContent = ` <div class="d-flex flex-column gap-1 disable-pointer-events"> <h5 class="mb-0 fs-6">${username}</h5> <p class="mb-0 text-muted preview-text">${last_message.text}</p> <p class="mb-0 dialog-unread"><span class="dialog-unread-count">${unread_count}</span> unread messages</p> </div> `; btn.insertAdjacentHTML('beforeend', btnContent); df.appendChild(btn); }, ); dialogList.appendChild(df); },
回答
改用createElement配合textContent设置文本内容,完全可以解决这个XSS问题。
原因很直接:insertAdjacentHTML会把传入的字符串当作HTML解析,模板字面量插入的恶意内容会被浏览器执行;而createElement创建元素后,通过textContent赋值时,所有内容都会被当作纯文本处理,浏览器不会解析任何HTML标签,自然也不会执行脚本。
以下是修改后的安全渲染代码:
renderDialogs: () => { const dialogList = document.getElementById('dialogsList'); dialogList.textContent = ''; const df = document.createDocumentFragment(); dialogs.list.forEach( ({ username, other_user_id, unread_count, last_message, }) => { const btn = document.createElement('button'); btn.className = 'list-group-item list-group-item-action list-group-item'; btn.dataset.username = username; btn.dataset.userId = other_user_id; // 创建容器div const container = document.createElement('div'); container.className = 'd-flex flex-column gap-1 disable-pointer-events'; // 创建用户名标题 const usernameEl = document.createElement('h5'); usernameEl.className = 'mb-0 fs-6'; usernameEl.textContent = username; container.appendChild(usernameEl); // 创建消息预览文本 const previewTextEl = document.createElement('p'); previewTextEl.className = 'mb-0 text-muted preview-text'; previewTextEl.textContent = last_message.text; container.appendChild(previewTextEl); // 创建未读消息提示 const unreadEl = document.createElement('p'); unreadEl.className = 'mb-0 dialog-unread'; const unreadCountSpan = document.createElement('span'); unreadCountSpan.className = 'dialog-unread-count'; unreadCountSpan.textContent = unread_count; unreadEl.appendChild(unreadCountSpan); unreadEl.append(' unread messages'); // 追加纯文本 container.appendChild(unreadEl); btn.appendChild(container); df.appendChild(btn); }, ); dialogList.appendChild(df); },
这种方式从根源上避免了HTML解析,确保所有用户输入内容都以纯文本形式展示,彻底阻断XSS攻击路径。
内容的提问来源于stack exchange,提问作者Sora
相关产品推荐
相关产品推荐

