XSS的原理
XSS(跨站脚本攻击)原理
1. 核心机制
XSS攻击的本质是恶意脚本在用户浏览器中执行。攻击者通过向网页注入恶意代码,当其他用户访问该页面时,浏览器会执行这些代码(没有对用户的输入进行过滤导致用户输入的恶意JS代码输入到页面中产生漏洞的),导致:
- 会话劫持(窃取Cookie)
- 页面篡改
- 敏感数据窃取
- 恶意重定向
2. 攻击流程
graph LR
A[攻击者构造恶意脚本] --> B[注入目标网站]
B --> C[用户访问被篡改页面]
C --> D[浏览器执行恶意脚本]
D --> E[攻击达成]
3. 三种主要类型
(1) 反射型XSS
- 攻击方式:恶意脚本通过URL参数传递
- 触发条件:服务器未过滤输入,直接返回参数内容
- 示例:
服务器返回页面包含:http://example.com/search?keyword=<script>stealCookie()</script>
<p>您搜索了: <script>stealCookie()</script></p>
(2) 存储型XSS(危害最大)
- 攻击方式:恶意脚本存储到数据库
- 触发条件:用户访问包含恶意内容的页面(如评论区)
- 危害性:长期存在,影响所有访问者
- 攻击链: $$ \text{攻击者提交} \rightarrow \text{服务器存储} \rightarrow \text{用户加载} \rightarrow \text{脚本执行} $$
(3) DOM型XSS
- 特点:完全在客户端发生,不经过服务器
- 原理:前端JavaScript不安全地操作DOM
- 示例漏洞代码:
攻击URL:document.getElementById("output").innerHTML = "欢迎, " + location.hash.substring(1); // 从URL#后取值
http://example.com#<img src=x onerror=alert(1)>
4. 关键漏洞点
- 输入未过滤:用户输入直接拼接到HTML/JS中
- 输出未转义:特殊字符如
< > " '
未转换为实体字符 - 不安全API使用:如
innerHTML
、eval()
、document.write()
5. 数学表达攻击场景
设合法输入为 $A$,恶意载荷为 $M$,漏洞函数为 $f$,则攻击成功条件: $$ f(A + M) \neq f(A) + f(M) $$ 当过滤函数 $f$ 非幂等或不完备时,存在: $$ \exists M \text{ 使得 } f(M) = M \quad \text{(绕过过滤)} $$
6. 防御原则
- 输入过滤:删除或编码
< > & " '
等危险字符 - 输出转义:根据上下文使用不同编码规则
- HTML上下文:
< → <
- JavaScript上下文:
" → \u0022
- HTML上下文:
- 内容安全策略(CSP):通过HTTP头限制脚本来源
Content-Security-Policy: script-src 'self'
总结:XSS本质是信任链断裂——浏览器信任服务器返回的内容,而服务器未充分验证用户输入。防御关键在于严格实施数据与代码分离原则。
编码
地址栏urlcode
英文数字一般不会进行编码,一般对特殊字符进行编码
ASCII转16进制就是urlcode编码规范
JS unicode
\u开始的
先转ASCLL,再转16进制---》\u00
html实体编码
有三种形式:
十进制编码:直接转ASCII,如果是16进制编码,再转一个16进制就行了
<---->不要忘记分号
解析顺序
html实体编码---》urlcode----》js unicode
XSS-Lab 靶场过关
level 1 无任何过滤
http://127.0.0.1/xss-labs-master/level1.php?name=t1
<?php
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
?>
get传参,这里可以看到这关并没有做任何的过滤,导致我name=什么就会输出什么,直接将name=的结果输出到页面上来,但是我们要了解到到底什么样的标签可以嵌套解析,不然我们没办法解析我的恶意代码
payload:
http://127.0.0.1/xss-labs-master/level1.php?name=%3Cimg%20src=1%20onerror=alert(1)%3E
http://127.0.0.1/xss-labs-master/level1.php?name=%3Cscript%3Ealert(1)%3C/script%3E
说明<h>这个标签是可以嵌套解析标签和script代码的,那具体我们有那些可以,那些不行呢?
level 2 input表单
<?php
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level2.php method=GET>
<input name=keyword value="'.$str.'">
<input type=submit name=submit value="搜索"/>
</form>
</center>';
?>
.htmlspecialchars函数
详解:https://www.php.net/manual/zh/function.htmlspecialchars.php
可以看到这个函数当我们再像前面那关那样输入js代码,发现它并不能解析,这是因为此过滤函数进行了html的实体编码,将<>转换成了如下实体编码,这样就会认为解析过后的<>是普通字符而无法解析
字符 | 替换后 |
---|---|
& (& 符号) |
& |
" (双引号) |
" ,除非设置了 ENT_NOQUOTES |
' (单引号) |
设置了 ENT_QUOTES 后, ' (如果是 ENT_HTML401 ) ,或者 ' (如果是 ENT_XML1 、 ENT_XHTML 或 ENT_HTML5 )。 |
< (小于) |
< |
> (大于) |
> |
绕过标签和属性value:
分析源码可以看出它并没有对input进行过滤,只对get传参进行了过滤,那我们就需要绕过input
1 绕过value
“”闭合
aaaa" οnclick="alert(1)
2 闭合input标签
aaa"> <script>alert(1)</script>
XSS cookie
1 进入登录页面,查看登录的cookie
2 删除页面的cookie
3 进入服务器的后台复制cookie,修改后台的index.php
4 成功进入