手动排查html漏洞需三步:定位高危结构、验证执行上下文、确认渲染结果是否被绕过;重点检查display:none的可交互元素、innerhtml注入风险、浏览器自动补全导致的dom变异及模板条件块未闭合问题。

手动排查 HTML 代码漏洞不是靠“看一遍就完事”,而是有明确路径:先定位高危结构,再验证执行上下文,最后确认渲染结果是否被绕过。没有自动化扫描器兜底时,这三步缺一不可。
怎么快速揪出 display:none 的隐藏可交互元素?
这类元素是前端逻辑漏洞的温床,尤其在权限控制或调试功能残留场景下。浏览器原生开发者工具效率低,得用控制台一行命令筛出来:
-
document.querySelectorAll('button, a, input[type="button"], input[type="submit"], [onclick], [href^="javascript:"]')先捞出所有潜在可交互节点 - 再加过滤:
.filter(el => getComputedStyle(el).display === 'none' || getComputedStyle(el).visibility === 'hidden') - 注意:
getComputedStyle不反映hidden属性或父级display: none的继承效果,所以必须递归检查el.offsetParent === null才算真正不可见 - 别漏掉注释里的标签——
<!-- <button onclick="adminDelete()"> -->这种写法在 DOM 解析后不会生成节点,但源码里存在,得用document.documentElement.innerHTML配合正则扫
为什么 innerHTML 直接插入用户数据就是漏洞?
不是“用了 innerHTML 就一定不安全”,而是它绕过了所有 HTML 解析层的转义逻辑,把字符串当原始 DOM 片段执行。常见误判:
- 以为做了
String.replace(/, ' 就安全——漏了 <code>、<code> 等编码变体,更漏了 <code><img src="https://img.php.cn/?x-oss-process=image/resize,p_40" alt="网站HTML代码漏洞手动排查技巧">这类无闭合标签的执行 - 以为只插纯文本就没事——只要输入里含
<script></script>或<img onload="...">,innerHTML会立刻解析并执行 - 用
textContent替代是安全的,但若业务真要渲染富文本,必须用 DOMPurify 等库做白名单过滤,且禁用ALLOWED_TAGS中的script、onerror等危险项
未闭合标签导致 DOM 结构错乱,怎么验证影响范围?
浏览器容错机制会让页面“看起来正常”,但实际 DOM 树已变形,JavaScript 操作可能失效或误匹配。不能只看渲染结果:
- 打开开发者工具的 Elements 面板,右键任意节点选
Break on > subtree modifications,再触发 JS 操作——如果断点频繁命中非预期节点,大概率是父容器因标签未闭合被浏览器自动补全,改变了真实层级 - 用
document.body.innerHTML和原始 HTML 字符串对比,找差异位置。浏览器补的会出现在不该出现的地方 - 重点查
table内部:未闭合的tr或td会导致整个表格被拆成多个孤立tbody,用document.querySelectorAll('table tbody')能快速暴露异常数量 - 服务端模板(如 Jinja、Django)中混用
{% if %}和<div> 时,条件块未闭合比纯 HTML 更难发现,必须结合模板编译后的输出源码看<p>最麻烦的不是找到漏洞,而是确认它是否真能被利用——比如一个 <code>display:none的按钮,得手动删掉该样式再点一下,看请求是否发出去、参数是否可控、后端有没有二次校验。手动排查的终点,永远是“能不能走通这条攻击链”,而不是“代码看起来有没有问题”。











