7

I am allowing uploading of files to my C# MVC website, I am restricting those types based on extension at the moment, but also feel I need a server side check to confirm they haven't just renamed it.

Is there a technique that I can use to check all the types I need or a library I can use that will help here?

I have seen people checking the first few bytes of the file, but I am scared I will miss something?

Thanks for your help.

Edit:

There are a lot of suggestions here. I will investigate some of these as a solution.

2
  • 1
    If all you got is a bunch of bytes, then I'm afraid it's going to be a bit difficult. If you're only dealing with images, you can always check for specific headers. Commented Sep 2, 2012 at 5:47
  • it will be image types as well as other mime types such as doc, xls, pdfs etc. Commented Sep 2, 2012 at 5:48

7 Answers 7

4

If you are reading the file as an HttpPostedFile you can get the content type which is equal to the mime type.

So then you can do the following:

if (myFile.ContentType == "video/mpeg") { // Do your thing } else{ // error } 
Sign up to request clarification or add additional context in comments.

1 Comment

1

Try this solution: Using .NET, how can you find the mime type of a file based on the file signature not the extension

It will do file content sniffing for you.

Comments

0

I ended up mixing some solutions from here, because I am not using the HttpFileBase and only have the file stream, I had to read the first few bytes of the stream to determine the mime type.

Note: I don't use the registry technique because I don't know what will or wont be installed on the servers.

Comments

0

You can obtain the MIME type in the following way:

var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"'); mimeType = file.ContentType; 

Once MIME type is obtained, it can be compared with string comparison (as shown by @ffffff01 )

Comments

0

For more safety you can also check both mimeType with the ContentType property as ffffff01 said, and file extension with Path.GetExtension method.

Comments

0

Client side

<asp:FileUpload runat="server" ID="fileUploader" accept=".pdf,.docx"/> <asp:RegularExpressionValidator ID="fileUploaderV" runat="server" ControlToValidate="fileUploader" ErrorMessage="Only .pdf, .docx formats are allowed" ValidationExpression="(.+\.([Pp][Dd][Ff])|.+\.([Dd][Oo][Cc][Xx]))" Display="Dynamic" ForeColor="Red"></asp:RegularExpressionValidator> 

Server side

using System.Runtime.InteropServices; [DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)] static extern int FindMimeFromData (IntPtr pBC, [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeParamIndex = 3)] byte[] pBuffer, int cbSize, [MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed, int dwMimeFlags, out IntPtr ppwzMimeOut, int dwReserved); public static string getMimeFromFile(HttpPostedFile file) { IntPtr mimeout; int MaxContent = (int)file.ContentLength; if (MaxContent > 4096) MaxContent = 4096; byte[] buf = new byte[MaxContent]; file.InputStream.Read(buf, 0, MaxContent); int result = FindMimeFromData(IntPtr.Zero, file.FileName, buf, MaxContent, null, 0, out mimeout, 0); if (result != 0) { Marshal.FreeCoTaskMem(mimeout); return ""; } string mime = Marshal.PtrToStringUni(mimeout); Marshal.FreeCoTaskMem(mimeout); return mime.ToLower(); } } 

Comments

0

I personally used the FileSignatures for file content inspection in the past.

/// <summary> /// Provider for /// <a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods">extension methods</a> /// on <see cref="Stream">streams</see>. /// </summary> public static class StreamExtensions { private static readonly ImmutableArray<string> _mimeTypeKeys = ["application/pdf", "image/jpg", "image/jpeg", "image/png"]; private static readonly ImmutableArray<string> _extensionKeys = ["pdf", "jpg", "jpeg", "png"]; /// <summary>Checks if the stream contains a valid file.</summary> /// <param name="inputStream"><inheritdoc cref="Stream" path="/summary"/></param> /// <param name="extension">Out: The actual extension of the file provided through the <paramref name="inputStream"/>.</param> /// <param name="mimeType">Out: The actual mime-type of the file provided through the <paramref name="inputStream"/>.</param> /// <returns><see langword="true"/> if the stream is a valid file, otherwise <see langword="false"/>.</returns> public static bool IsValidFile( this Stream inputStream, out string extension, out string mimeType) { mimeType = null; extension = null; if (inputStream is null) return false; var fileStreamInspector = new FileFormatInspector(); var fileHeader = fileStreamInspector.DetermineFileFormat(inputStream); mimeType = fileHeader.MediaType; extension = fileHeader.Extension; return _mimeTypeKeys.Contains(mimeType) && _extensionKeys.Contains(extension); } } 

How to use:

var isValid = inputFile.IsValidFile( extension: out var extension, mimeType: out var mimeType); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.