跨站脚本攻击(XSS)是一种常见的Web安全漏洞,它允许攻击者将恶意脚本注入到网页中,这些脚本可以在其他用户的浏览器中执行,从而窃取用户信息、会话令牌或其他敏感数据。
本教程代码未使用第三方库,纯手写实现,请不要生产环境使用。
可受攻击的案例
下面是一个简单的Node.js案例,展示如何XSS攻击:
const http = require("http");
const url = require("url");
const querystring = require("querystring");
const server = http.createServer((req, res) => {
const { pathname, query } = url.parse(req.url, true);
if (pathname === "/") {
// 读取 HTML 文件并返回给客户端
res.writeHead(200, { "Content-Type": "text/html" });
res.end(`<html>
<head>
<title>XSS Test</title>
</head>
<body>
<h1>XSS Test Page</h1>
<form action="/submit" method="post">
<input type="text" name="userInput" placeholder="Enter your input">
<button type="submit">Submit</button>
</form>
</body>
</html>`);
} else if (pathname === "/submit" && req.method === "POST") {
let body = "";
// 接收 POST 请求的数据
req.on("data", (chunk) => {
body += chunk;
});
req.on("end", () => {
// 解析 POST 请求的数据
const formData = querystring.parse(body);
const userInput = formData.userInput;
// 将用户输入中的特殊字符转义
// const escapedInput = escapeHtml(userInput);
// 返回转义后的结果给客户端
res.writeHead(200, { "Content-Type": "text/html" });
res.end(`<h2>Your input: ${userInput}</h2>`);
});
} else {
// 处理未知路由
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("404 Not Found");
}
});
const port = 3000;
server.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
在上述代码中,用户输入直接插入到响应的HTML中,没有进行任何过滤或转义。这意味着,如果攻击者提交一个包含JavaScript代码字符串,如:
<script>alert('XSS attack!');</script>
这段代码将被浏览器执行,导致XSS攻击。
防御XSS攻击
为了防御XSS攻击,我们需要对用户输入进行转义,转义HTML特殊字符。
req.on("end", () => {
// 解析 POST 请求的数据
const formData = querystring.parse(body);
const userInput = formData.userInput;
// 将用户输入中的特殊字符转义
const escapedInput = escapeHtml(userInput);
// 返回转义后的结果给客户端
res.writeHead(200, { "Content-Type": "text/html" });
res.end(`<h2>Your input: ${escapedInput}</h2>`);
});
新增函数
// 转义 HTML 特殊字符的函数
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'")
.replace(/\//g, "/");
}
当输入
<script>alert('XSS attack!');</script>
会被转译成
<script>alert('XSS attack!');</script>
注意
实际开发的时候,不要直接使用以上代码,直接用第三方库会更高效,安全。出了问题,概不负责。