业务侧限制上传大小是成本最低、见效最快的溢出攻击防线之一,多数溢出类攻击在超大请求体进入业务逻辑前就被直接拒绝。
上传文件大小限制多少合适?先看攻击者怎么打
很多研发问过同一个问题:上传文件大小限制多少合适?答案不复杂,跟着业务需求走,但必须留出一条硬边界。
溢出类攻击有一个共同点,攻击者喜欢把异常大的数据塞进小接口,比如一个头像上传接口,正常用户最多传 2MB 左右的图片,攻击者传一个 500MB 甚至 2GB 的文件过去,服务端如果没限制,接收、写临时文件、交给图片解析库处理,每一步都可能触发问题。
- 缓冲区溢出:旧版图片解析库对长度字段信任过度,超长数据直接覆盖相邻内存。
- 整数溢出:文件头里声明了很大的宽高,服务端计算内存分配时数值溢出,实际只分配小块内存。
- 内存耗尽:多部分表单解析器把整个请求体读进内存,大文件直接把堆内存打满。
- 磁盘耗尽:上传文件先写临时目录,多个并发大文件上传快速占满磁盘。
业务侧限制上传大小,等于在入口处把这些攻击面一起收窄,行业共识认为,上传大小限制应当以“业务够用”为原则,而不是越大越好。
具体到不同业务,可以参考以下范围:
| 业务场景 | 常见文件类型 | 建议上传大小上限 |
|---|---|---|
| 用户头像、评论图片 | JPG、PNG、WebP | 2M~5M |
| 合同、简历、文档 | PDF、DOCX | 10M~20M |
| 论坛附件、小型压缩包 | ZIP、RAR | 20M~50M |
| 短视频、音频 | MP4、MP3 | 100M~500M |
| 大型网盘、设计源文件 | PSD、CAD、大分片 | 走分片上传接口 |
视频和设计文件不要直接开超大整包上传,应当改用分片上传,每个分片控制在 1M~10M,服务端逐片校验,既能恢复中断,也能避免单次请求体过大。
上传大小不设限,溢出攻击有多容易触发
拿一个常见的图片上传接口举例,后端用 Spring Boot 默认配置,没有显式设置 multipart 上限,攻击者用 curl 构造一个 800MB 的 multipart 请求:
curl -X POST
-H "Content-Type: multipart/form-data"
-F "file=@/tmp/bigfile.jpg"
http://your-api/upload
这个请求进入应用后,Servlet 容器会先解析 multipart,默认情况下,Spring Boot 1.x 的 max-file-size 是 1MB,但很多项目为了图省事改成 -1,也就是不限制,一旦放开,800MB 文件先被接收,再写入临时目录,再交给 ImageIO 或 Thumbnailator 解析,解析阶段如果触发整型溢出,服务进程可能直接崩溃。
Nginx 日志里可以看到大量 413 状态码,这是限制生效后最直接的信号:
tail -f /var/log/nginx/access.log | grep 413
如果日志里没有 413,而有大量超时或 500,说明请求可能已经透传到后端,业务侧限制缺失。
业务侧限制上传大小有用吗?从三个真实场景看
有些人觉得限制上传大小是“产品体验问题”,跟安全关系不大,业务侧限制上传大小有用吗?放到下面三个场景里看,结论很直接。
电商商品图上传接口
正常卖家上传商品主图,一般在 1M~5M,攻击者抓包构造一个 300MB 的伪 JPEG,服务端没有限制时,文件进入图片压缩服务,压缩服务为了生成缩略图,先把整个文件读进内存,300MB 文件加上解码后的位图数据,内存占用轻松超过 1GB,单次攻击未必打挂服务,但并发 10 个请求,内存会迅速耗尽。
在业务侧加上 5MB 限制后,超大请求直接在框架层被拒绝,压缩服务根本收不到文件,限制越靠近业务入口,攻击者越难触达深层解析组件。
文档转换服务的整数溢出
在线 PDF 转 Word 或 Office 预览服务,通常允许上传文档,攻击者构造一个只有 2MB 的恶意 PDF,但在内部对象里声明了超长数组,解析库计算内存大小时发生整数溢出,只分配小块缓冲区,随后写入超长数据,导致远程代码执行。
业务侧限制上传大小不能完全挡住这类逻辑漏洞,但它能减少攻击者控制文件复杂度的空间,很多溢出 payload 必须依赖大体积数据块,限制在 20M 内能过滤掉相当一部分攻击样本。
企业网盘附件同步
企业网盘允许上传单个大文件,但不能不做任何限制,某员工误传一个 50GB 的虚拟机镜像,或者攻击者借一个测试账号上传超大分片,都会拖垮存储节点。
这时应该启用分片上传,每个分片限制 10M,同时限制总文件大小,服务端每收到一个分片就校验大小和哈希,超大分片直接拒绝,业务侧限制在这里不仅是安全控制,也是资源治理手段。
服务器上传大文件溢出攻击怎么防?分层配置实操
服务器上传大文件溢出攻击怎么防?单靠一处配置不够,需要分层设卡,每层配置都能独立拒绝超大请求。
第一层:反向代理直接拒绝超大请求
Nginx 在 http、server 或 location 块中配置:
client_max_body_size 2m;
超过限制时,Nginx 直接返回 413 Request Entity Too Large,请求不会转发到后端。
Apache 使用:
LimitRequestBody 2097152
放在 Directory 或 .htaccess 中,单位是字节。
Tomcat 在 server.xml 的 Connector 中配置:
maxPostSize="2097152"
反向代理层限制的好处是开销极低,请求体还没读完就被断开,后端完全无感知。
第二层:应用框架限制与异常处理
内部服务如果绕过 Nginx 直连应用端口,代理层限制就失效了,所以应用框架必须有自己的限制。
Java Spring Boot 在 application.yml 中:
spring:
servlet:
multipart:
max-file-size: 2MB
max-request-size: 4MB
PHP 在 php.ini 中:
upload_max_filesize = 2M
post_max_size = 4M
Python Django 在 settings.py 中:
DATA_UPLOAD_MAX_MEMORY_SIZE = 2097152
FILE_UPLOAD_MAX_MEMORY_SIZE = 2097152
Node.js 使用 multer 中间件:
const upload = multer({
limits: { fileSize: 2097152 }
});
应用框架拒绝时通常会抛异常,需要捕获异常并返回统一错误响应,不能把堆栈信息带回客户端,Spring Boot 可以捕获 MaxUploadSizeExceededException,返回 413 或自定义 JSON 错误。
第三层:解析前检查文件头与真实大小
大小限制通过后,文件不一定安全,还需要在真正解析前做两件事:
- 校验文件魔数,确认扩展名和真实类型一致。
- 读取图片头部的宽高信息,拒绝超大像素图片。
例如用 ImageMagick 的 identify 命令:
identify -format "%w %h" upload.jpg
宽高乘积超过业务预期,比如头像图超过 10000 x 10000,直接拒绝,这样可以防止解压式炸弹或像素炸弹拖垮内存。
WAF拦截与业务侧上传大小限制哪个更可靠
不少安全负责人会纠结:WAF 拦截与业务侧上传大小限制哪个更可靠?答案不是二选一,而是先业务侧限制,再 WAF 补充。
| 对比维度 | 业务侧上传大小限制 | WAF 拦截 |
|---|---|---|
| 执行位置 | 入口网关或应用框架 | 旁路或串联安全设备 |
| 对未知溢出攻击 | 有较大拦截概率 | 依赖规则库,可能有延迟 |
| 误报率 | 极低,只要上限合理 | 可能误拦正常复杂文件 |
| 绕过难度 | 低,不依赖内容识别 | 分块传输、编码变形可绕过 |
| 维护成本 | 配置一次长期有效 | 需要更新规则和策略 |
| 对业务影响 | 可能限制大文件场景 | 可能误判正常上传 |
WAF 的价值在于识别恶意内容,比如带漏洞利用 payload 的 PDF,但攻击者常用分块传输和分段编码绕过 WAF 的大小检测,业务侧 Nginx 的 client_max_body_size 不关心内容,只看 Content-Length 和实际传输字节,绕过难度低得多。
在北京等保测评上传大小限制要求中,业务系统通常需要给出明确的文件大小上限和拒绝策略,只部署 WAF 不设置应用层限制,往往会被判定为访问控制不完整,先做好基础限制,再叠加 WAF,才能同时满足合规和实战。
业务侧上传大小限制配置清单与验证
落地时不要只改一个配置文件,要按链路逐步验证。
配置清单
- Nginx:
client_max_body_size 10m; - Apache:
LimitRequestBody 10485760 - Tomcat:
maxPostSize="10485760" - Spring Boot:
spring.servlet.multipart.max-file-size=10MB - PHP:
upload_max_filesize = 10M和post_max_size = 12M - Django:
DATA_UPLOAD_MAX_MEMORY_SIZE = 10485760 - Node.js multer:
limits: { fileSize: 10485760 }
改完配置后重启服务,别只 reload 不重启,有些框架参数需要进程重启才生效。
验证方法
先造一个超过限制的测试文件:
dd if=/dev/zero of=/tmp/test_15mb.jpg bs=1M count=15
然后用 curl 模拟上传:
curl -X POST
-H "Content-Type: multipart/form-data"
-F "file=@/tmp/test_15mb.jpg"
http://your-api/upload
预期返回 413 或自定义拒绝信息,而不是 500,同时观察后端应用日志,不应出现解析异常或内存溢出堆栈。
再验证边界内正常文件能否上传:
dd if=/dev/zero of=/tmp/test_8mb.jpg bs=1M count=8
curl -F "file=@/tmp/test_8mb.jpg" http://your-api/upload
正常返回成功,说明限制值设置合理,未误伤正常业务。
监控侧可以定期检查临时目录大小,防止异常写入:
df -h /tmp
du -sh /tmp/upload
如果临时目录频繁接近磁盘上限,说明上传链路中仍有绕过点,需要回头查代理层和应用层配置是否全部生效。
业务侧限制上传大小常见问题
上传大小限制设置多少才算安全?
没有固定数值,要看业务场景,头像、评论图 2M~5M,文档 10M~20M,视频和设计文件走分片上传,核心原则是够用即可,不要为了兼容极端大文件而放开限制。
只靠 WAF 限制上传大小够吗?
不够,WAF 规则可以被分块传输、编码变形绕过,而且部分场景下 WAF 不解析经过加密隧道的内网流量,业务侧限制更靠近应用,执行更稳定。
Nginx 限制上传大小后还需要应用层限制吗?
需要,因为内部服务可能绕过 Nginx 直连应用端口,比如运维调试、内网调用、k8s Pod 直连,应用层限制可以在代理层失效或直连时继续兜底。
做好业务侧上传大小限制,不等于解决所有上传安全问题,但它能把相当一部分溢出类攻击挡在处理链路的入口之外,先定好大小边界,再谈内容检测和沙箱解析,攻击面会小得多。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/652130.html





