如何在Web服务器拦截可执行文件上传并检测伪装恶意文件
可执行/恶意脚本文件识别规则
仅靠后缀名、单匹配<?php标签的检测方式漏报极多,不同类型禁止上传文件的固定识别特征如下:
- Windows PE可执行文件(exe、dll、sys等):文件起始2字节固定为
MZ(十六进制值0x4D 0x5A),文件偏移0x3C位置会指向PE头标记PE\0\0(十六进制值0x50 0x45 0x00 0x00),只要匹配该特征,无论改什么后缀都是PE格式可执行文件。 - Linux ELF格式文件(.so动态库、无后缀可执行程序):文件起始4字节固定为
\x7fELF(十六进制值0x7F 0x45 0x4C 0x46),匹配即可直接判定为可执行类文件。 - Shell脚本(.sh、.bash等):核心特征是shebang标记,即文件开头(忽略前置空白、BOM头)前2字节为
#!,后续紧跟解释器路径,常见匹配串包括#!/bin/sh、#!/bin/bash、#!/usr/bin/env sh、#!/usr/bin/env bash。 - Python脚本(.py、.pyc):源码类脚本优先匹配shebang指向Python解释器的特征,比如
#!/usr/bin/python、#!/usr/bin/env python,辅助匹配import、__main__、def等Python专属语法标记;编译后的pyc文件前4字节为对应版本的固定魔数,比如Python3.8及以上版本常见魔数开头为\x55\x0d\x0d\x0a。 - Perl脚本(.pl、.pm):优先匹配shebang行
#!/usr/bin/perl、#!/usr/bin/env perl,辅助匹配use strict;、sub等Perl专属语法特征。 - PHP类脚本:你当前用的
<?php匹配存在漏报,需要补充匹配<?=短标签、<script language="php">旧版标签、后跟PHP关键字的<?短开标签(注意和XML声明做区分,避免误判),同时补充匹配eval(、system(、exec(等高危函数特征,防止攻击者用编码方式绕过标签检测。
伪装成图片/文本后缀的恶意文件检测方案
仅校验文件头无法识别插入到正常文件内部的恶意代码(也就是常说的图片马),需要按三层规则做检测:
- 第一层:白名单格式文件头强校验
所有允许上传的文件格式,必须匹配对应格式的标准文件头,不匹配直接拦截,常见允许格式的文件头特征:- png:前8字节固定为
\x89PNG\r\n\x1a\n(十六进制值89 50 4E 47 0D 0A 1A 0A) - jpg/jpeg:前2字节为
\xFF\xD8,文件末尾2字节为\xFF\xD9 - gif:前6字节为
GIF87a或GIF89a - txt:无固定文件头,但内容必须全部为可打印字符+常规换行、制表符,不可存在不可见控制字符、脚本标签、shebang标记
- mp4:文件偏移4-8字节位置为
ftyp - avi:前4字节为
RIFF,偏移8字节位置为AVI
- png:前8字节固定为
- 第二层:全文件内容特征扫描
不要只检测文件开头,要遍历整个文件内容做特征匹配,拦截以下内容:- 所有脚本类开标签:
<?、<%、<script、#! - 可执行文件特征串:
MZ、\x7fELF(如果是允许上传的二进制媒体文件触发该匹配,要走第三层结构校验排除偶然字节碰撞) - 恶意代码特征:
eval(、system(、exec(、passthru(、shell_exec(、base64_decode(等高危函数调用,以及cmd /c、/bin/bash -c等命令执行特征串
- 所有脚本类开标签:
- 第三层:文件结构合法性校验
用对应格式的官方标准解析库尝试解析上传文件:比如图片用成熟图像处理库打开,验证是否能正常读取宽高、通道信息;视频用媒体解析库验证是否能正常读取时长、编码信息。解析失败直接判定为伪装文件拦截——这是识别伪装文件最有效的手段,正常的图片、视频、文本文件一定能被标准库正常解析,而插入恶意代码的伪装文件大概率会出现解析报错、参数异常的问题。
实操提示:不要自己手写二进制解析、特征匹配逻辑,直接用各语言生态成熟的MIME检测、媒体处理库做校验,比如Python端用python-magic、Pillow,Java端用Apache Tika,避免因规则考虑不全被大小写混淆、插入垃圾字符、编码等方式绕过。另外上传后的文件要重命名为随机文件名,存储到Web服务无执行权限的目录,不要给上传目录开放脚本解析权限,做多层防御。
内容的提问来源于stack exchange,提问作者Praan
相关产品推荐
相关产品推荐

