[上传]关于Asp.Net上传文件后缀判断的那些事

  关于上传文件的漏洞,做为从asp时代过来人记忆一定是很深的。搞asp.net开发时间快2年了,说来还真惭愧,没有去认真看过Asp.Net生命中周期的各个环节,今天心血来潮看了下关于文件上传部分的实现,原来.Net Framework给我们做了真不少的事。

  首先来看看HttpRequest.Files这个HttpFileCollection,这个集合是用HttpRequest.FillInFilesCollection方法赋值的。让我们来看看具体实现:
程序代码 程序代码
private void FillInFilesCollection()
{
    if ((this._wr != null) && StringStartsWithAnotherIgnoreCase(this.ContentType, "multipart/form-data"))
    {
        MultipartContentElement[] multipartContent = this.GetMultipartContent();
        if (multipartContent != null)
        {
            bool flag = false;
            if (this._flags[64])
            {
                this._flags[64] = false;
                flag = true;
            }
            for (int i = 0; i < multipartContent.Length; i++)
            {
                if (multipartContent[i].IsFile)
                {
                    HttpPostedFile asPostedFile = multipartContent[i].GetAsPostedFile();
                    if (flag)
                    {
                        this.ValidateString(asPostedFile.FileName, "filename", "Request.Files");
                    }
                    this._files.AddFile(multipartContent[i].Name, asPostedFile);
                }
            }
        }
    }
}

  其中文件数据的获取,在GetMultipartContent中实现的,有兴趣可以进入去看具体的实现过程,今天我们关注的是文件后缀的判断。

  在FillInFilesCollection中,注意看this.ValidateString(asPostedFile.FileName, "filename", "Request.Files");进入ValidateString方法可以看到第一步就是去掉文件名中的Null Characters,然后就是CrossSiteScriptingValidation.IsDangerousString方法来判断危险字符串,考虑得可真是周到哈。

  仔细看过GetMultipartContent的实现过程知道,Asp.Net上传文件处理中,获取的文件名是根据Multipart Boundary分隔符来实现的。这是完全没有问题的,只是捣乱的人可能上传一个改了后缀的文件,如果是图片,导致我们显示的图片是个大X,要做到判断怎么办了?asp时代是对文件数据流中去取文件头信息来处理的,Asp.Net时代,也有人写出了相应的代码,且看下面代码:
程序代码 程序代码
public class PostedFileValidation
{
public enum FileExtension
{
    /// <summary>
    /// JPEG图片
    /// </summary>
    JPG = 255216,
    /// <summary>
    /// GIF图片
    /// </summary>
    GIF = 7173,
    /// <summary>
    /// PNG图片
    /// </summary>
    PNG = 13780,
    /// <summary>
    /// SWF文件
    /// </summary>
    SWF = 6787,
    /// <summary>
    /// RAR文件
    /// </summary>
    RAR = 8297,
    /// <summary>
    /// ZIP文件
    /// </summary>
    ZIP = 8075,
    /// <summary>
    /// 7Z文件
    /// </summary>
    _7Z = 55122

    // 255216 jpg
    // 7173 gif
    // 6677 bmp
    // 13780 png
    // 6787 swf
    // 7790 exe dll
    // 8297 rar
    // 8075 zip
    // 55122 7z
    // 6063 xml
    // 6033 html
    // 239187 aspx
    // 117115 cs
    // 119105 js
    // 102100 txt
    // 255254 sql

}
/// <summary>
/// 根据文件头判断文件类型
/// </summary>
/// <param name="file"></param>
/// <param name="fileEx"></param>
/// <returns></returns>
public static bool IsAllowedExtension(HttpPostedFile file, FileExtension[] fileEx)
{
    int fileLen = file.ContentLength;
    byte[] imgArray = new byte[fileLen];
    file.InputStream.Read(imgArray, 0, fileLen);
    MemoryStream ms = new MemoryStream(imgArray);
    BinaryReader br = new BinaryReader(ms);
    string fileclass = "";
    byte buffer;
    try
    {
    buffer = br.ReadByte();
    fileclass = buffer.ToString();
    buffer = br.ReadByte();
    fileclass += buffer.ToString();
    }
    catch
    {
    }
    br.Close();
    ms.Close();
    foreach (FileExtension fe in fileEx)
    {
    if (Int32.Parse(fileclass) == (int)fe)
        return true;
    }
    return false;
}
}

  具体是否应该是使用这个方法来验证,要看你自己的需求。至此,关于上传文件后缀的那点事就完了,算是又一次深入看了点东西,记录下。另外关于生命周期的可以看看这里:http://msdn.microsoft.com/zh-cn/library/ms178473.aspx

参考:http://www.supesoft.com/ArticleDisp.asp?ID=4843

[本日志由 Yoker 于 2010-07-14 11:40 PM 编辑]
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: c# Asp.Net 上传文件 HttpPostedFile
评论: 0 | 引用: 0 | 查看次数: 59
发表评论
昵 称:
密 码: 游客发言不需要密码.
验证码: 验证码
内 容:
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭