[上传]关于Asp.Net上传文件后缀判断的那些事
作者:Yoker 日期:2010-06-26
关于上传文件的漏洞,做为从asp时代过来人记忆一定是很深的。搞asp.net开发时间快2年了,说来还真惭愧,没有去认真看过Asp.Net生命中周期的各个环节,今天心血来潮看了下关于文件上传部分的实现,原来.Net Framework给我们做了真不少的事。
首先来看看HttpRequest.Files这个HttpFileCollection,这个集合是用HttpRequest.FillInFilesCollection方法赋值的。让我们来看看具体实现:
程序代码
其中文件数据的获取,在GetMultipartContent中实现的,有兴趣可以进入去看具体的实现过程,今天我们关注的是文件后缀的判断。
在FillInFilesCollection中,注意看this.ValidateString(asPostedFile.FileName, "filename", "Request.Files");进入ValidateString方法可以看到第一步就是去掉文件名中的Null Characters,然后就是CrossSiteScriptingValidation.IsDangerousString方法来判断危险字符串,考虑得可真是周到哈。
仔细看过GetMultipartContent的实现过程知道,Asp.Net上传文件处理中,获取的文件名是根据Multipart Boundary分隔符来实现的。这是完全没有问题的,只是捣乱的人可能上传一个改了后缀的文件,如果是图片,导致我们显示的图片是个大X,要做到判断怎么办了?asp时代是对文件数据流中去取文件头信息来处理的,Asp.Net时代,也有人写出了相应的代码,且看下面代码:
程序代码
具体是否应该是使用这个方法来验证,要看你自己的需求。至此,关于上传文件后缀的那点事就完了,算是又一次深入看了点东西,记录下。另外关于生命周期的可以看看这里:http://msdn.microsoft.com/zh-cn/library/ms178473.aspx
参考:http://www.supesoft.com/ArticleDisp.asp?ID=4843
首先来看看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);
}
}
}
}
}
{
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;
}
}
{
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
文章来自: 本站原创
Tags: c# Asp.Net 上传文件 HttpPostedFile 评论: 0 | 引用: 0 | 查看次数: 59
发表评论
上一篇
下一篇

