- html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Documenttitle>
- head>
- <body>
- <form id=x>
- <input id=attributes>
- <input id=attributes>
- form>
- body>
- <script>
- console.info(x.attributes);
- const data = decodeURIComponent(location.hash.substr(1));
- const root = document.createElement('div');
- root.innerHTML = data;
-
- //这里模拟了XSS过滤的过程,方法是移除所有属性
- for (let el of root.querySelectorAll('*')) {
- for (let attr of el.attributes) {
- el.removeAttribute(attr.name);
- }
- }
- document.body.appendChild(root);
- script>
const data = decodeURIComponent(location.hash.substr(1)); #截取#号后面的值
const root = document.createElement('div'); #创建一个div
root.innerHTML = data; #然后将#号后面的值赋值给div
for (let el of root.querySelectorAll('*')) { #选中div下面的所有子元素
for (let attr of el.attributes) { #获取子元素的所有属性
el.removeAttribute(attr.name); #删除获取到的所有属性
我们传递了

但是却发现src=1的属性被删除了,οnerrοr=alert(1)属性却还保留着,这是为什么呢?我们先了解一下这里的删除顺序。我们使用断点调试测试它的顺序

我们先一步步调试查看值的情况,通过断点调试,我们发现src作为第一个属性进入后被删除了,剩下的属性onerror仅一位,但是循环次数大于字符串个数时就不能删除了属性了。
我们使用一个python代码测试删除元素的顺序:

我们发现在a数组下,我们仅取出来了3个值,在预期中我们应该取出6个值,这就是应该边循环边删除的原因造成的。
这就有很大的问题,因为删除元素时因为索引问题我们不清楚到底删除了哪些元素,所以我们仅需要进行多次尝试就可以绕过一次循环:

- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Documenttitle>
- head>
- <body>
-
- body>
- <script>
- const data = decodeURIComponent(location.hash.substr(1));;
- const root = document.createElement('div');
- root.innerHTML = data;
-
- // 这里模拟了XSS过滤的过程,方法是移除所有属性,sanitizer
- for (let el of root.querySelectorAll('*')) {
- let attrs = [];
- for (let attr of el.attributes) {
- attrs.push(attr.name);
- }
- for (let name of attrs) {
- el.removeAttribute(name);
- }
- }
- document.body.appendChild(root);
- script>
- html>
两次循环的题是将属性先放入一个数组里面再进行删除,这个时候就不存在一次循环的问题。
所以我们使用两种方法进行绕过。
将进入循环的东西不放入我们需要的代码,这样即使删除了也没有关系
那我们如果让没有用到的属性进入循环,需要的又没有进入循环呢?
tabindex:全局属性,指示其元素是否可以聚焦,以及它是否在何处参与顺序键盘导航。使用Tab键获取焦点。

这样就是将