【前端安全】跨站脚本攻击(XSS)nodejs案例

327 阅读2分钟

跨站脚本攻击(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攻击。

image.png

防御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, "&amp;")
		.replace(/</g, "&lt;")
		.replace(/>/g, "&gt;")
		.replace(/"/g, "&quot;")
		.replace(/'/g, "&#x27;")
		.replace(/\//g, "&#x2F;");
}

当输入

<script>alert('XSS attack!');</script>

会被转译成

&lt;script&gt;alert(&#x27;XSS attack!&#x27;);&lt;&#x2F;script&gt;

注意

实际开发的时候,不要直接使用以上代码,直接用第三方库会更高效,安全。出了问题,概不负责。