1. 项目概述:从“知道”到“会防”的必经之路
在Web开发这条路上,安全从来不是选修课,而是决定项目生死存亡的必修课。我见过太多团队,功能做得飞快,UI炫得耀眼,但一上线就被各种自动化扫描工具揪出一堆漏洞,轻则数据泄露,重则服务瘫痪,甚至背上法律责任。很多人对“Web漏洞”的认知,还停留在“听说过SQL注入、XSS”这个层面,但具体到代码里长什么样、攻击者怎么利用、我们又该如何精准防御,往往就语焉不详了。这就是理论和实战之间那道巨大的鸿沟。
“常见Web漏洞及其代码实战”这个主题,目的就是填平这道鸿沟。它不是一个简单的漏洞列表罗列,而是一次从攻击者视角出发,深入代码肌理的防御实战演练。我们会聚焦那些在渗透测试报告和漏洞赏金平台上最高频出现的漏洞类型,比如注入、跨站脚本、越权访问、文件上传、逻辑缺陷等。但更重要的是,我们将用真实的、可运行的代码片段(涵盖前端Vue.js和后端Node.js/Python等常见技术栈),来还原漏洞产生的完整场景,并一步步演示如何通过代码层面的修改,将其彻底修复。
无论你是刚入门的前端工程师,觉得安全是后端的事;还是经验丰富的全栈开发者,想系统性地加固自己的知识体系;亦或是项目负责人,希望建立团队的安全编码规范,这篇内容都将提供直接的、可落地的参考。我们将避开枯燥的理论说教,直接进入代码战场,在“攻”与“防”的对抗中,真正理解每一个安全原则背后的原因。毕竟,只有亲手写过有漏洞的代码,并亲手把它修好,你对安全的认知才会从“概念”变成“肌肉记忆”。
2. 核心漏洞类型与攻击原理深度拆解
在动手写代码之前,我们必须先成为“攻击者”,理解他们的武器库和攻击路径。Web漏洞虽然名目繁多,但核心的攻击思想往往围绕几个关键点: 信任边界 的突破、 输入数据 的污染、 权限控制 的缺失以及 业务逻辑 的误用。下面我们就拆解几种最常见、也最危险的漏洞类型,看看它们是如何在代码中生根发芽的。
2.1 注入类漏洞:当数据变成指令
注入漏洞的本质,是程序没有清晰地区分“数据”和“代码”。攻击者将恶意构造的“数据”输入系统,系统却将其当作“代码”的一部分执行。这就像你本想让访客在留言簿上写句话,他却写了一段能操控留言簿本身的指令,并且系统还乖乖照做了。
SQL注入 是最经典的例子。假设一段后端查询用户信息的代码是这样的(以Node.js为例):
// 漏洞代码:直接拼接用户输入
const username = req.query.username; // 用户输入:admin' OR '1'='1
const sql = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;
db.query(sql, (err, results) => { ... });
当攻击者输入 admin' OR '1'='1 时,最终的SQL语句变成了:
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'xxx'
由于 '1'='1' 恒为真,这条语句很可能绕过了密码验证,直接返回所有用户信息。攻击者甚至可以利用 UNION 、 SELECT 等语句查询其他表,或者通过 ; 执行多条语句进行更严重的破坏。
命令注入 则更为直接,常出现在需要调用系统命令的功能中,比如服务器通过用户输入来拼接一个系统命令:
// 漏洞代码:拼接用户输入执行系统命令
const host = req.body.host; // 用户输入:8.8.8.8 && rm -rf /
const cmd = `ping -c 4 ${host}`;
child_process.exec(cmd, (error, stdout) => { ... });
如果不对输入进行严格过滤,攻击者就可以用 && 、 | 、 ; 等Shell操作符注入任意命令,后果不堪设想。
注意 :注入漏洞的修复核心是“分离数据和指令”。对于SQL,必须使用参数化查询(预编译语句);对于系统命令,应避免拼接,使用安全的API并严格限定参数白名单。
2.2 跨站脚本攻击:来自客户端的“特洛伊木马”
XSS让攻击者能够将恶意脚本注入到其他用户浏览的页面中。它利用了浏览器对服务器返回内容的信任。根据脚本注入和执行的持久性位置,主要分为三类:
反射型XSS :恶意脚本来自当前HTTP请求。常见于搜索框、错误信息提示等,脚本不会存储到服务器。
// 漏洞代码:直接将用户输入插入到HTML响应中
app.get('/search', (req, res) => {
const query = req.query.q; // 用户输入:<script>alert(document.cookie)</script>
res.send(`<p>您搜索的关键词是: ${query}</p>`); // 脚本被直接执行!
});
存储型XSS :恶意脚本被保存到服务器(如数据库),并在其他用户访问相关页面时执行。常见于论坛帖子、用户评论、昵称等。
// 漏洞代码:未过滤存储和展示的用户内容
// 后端存储
const comment = req.body.comment; // 用户提交了恶意脚本
db.saveComment(comment);
// 前端展示(Vue 2 示例,错误做法)
<template>
<div v-html="userComment"></div> <!-- 直接渲染未转义的HTML,风险极高! -->
</template>
DOM型XSS :漏洞出在客户端JavaScript代码本身,恶意脚本通过修改页面的DOM树来执行。
// 漏洞代码:使用innerHTML或类似方法直接插入未经验证的内容
const hash = window.location.hash.substring(1);
document.getElementById('content').innerHTML = `欢迎,${hash}`;
// 如果URL是 https://example.com/#<img src=x onerror=alert(1)>
// 那么脚本就会被执行。
XSS的危害远不止弹个警告框。它可以盗取用户的会话Cookie、发起伪造请求(CSRF)、篡改页面内容、进行键盘记录,甚至结合其他漏洞控制用户浏览器。
2.3. 越权访问漏洞:混乱的权限边界
越权漏洞的核心是“系统验证了你是谁,但没有检查你是否有权做这件事”。它通常分为两类:
水平越权 :用户A可以访问或操作用户B的数据。例如,通过修改URL中的用户ID参数,看到他人的订单、个人信息等。
// 正常请求:GET /api/orders/123 (查看自己ID为123的订单)
// 攻击尝试:GET /api/orders/456 (尝试查看他人ID为456的订单)
// 漏洞后端代码:
app.get('/api/orders/:orderId', (req, res) => {
const order = db.getOrder(req.params.orderId); // 直接查询,未检查订单所有者
res.json(order);
});
垂直越权 :普通用户能够执行需要更高权限(如管理员)才能执行的操作。例如,普通用户通过直接调用管理员API接口,或者在前端隐藏的管理功能元素上操作。
// 前端(Vue)

1128

被折叠的 条评论
为什么被折叠?



