Incorrect mime for XLS files

Asked

Viewed 676 times

2

I am doing a migration of a particular system written in ASP.NET (site) and in a certain part of that system there is a place where you upload a file XLS.

There is a check against the mime type of the file to know if it is actually an XLS file.

This worked perfectly on the old server, but after the migration, both on my machine (Windows 7 Ultimate SP1) and on the production server (Windows 2016 Datacenter) the mimes of XLS files are recognized as "application/octet-stream".

Just for the record: I don’t have Microsoft Office installed on my machine or on the server (and I think it would also be a great delay depending on it just to have the right mimes). And I also think it’s unlikely that I should change the code to verify the extension, since it doesn’t bring any kind of benefit to the security of the application.

Is there any way to make this mime be recognized in fact?

The excerpt from the code is below:

string Type = UP_Dados.PostedFile.ContentType;

string[] AllowedTypes = {
    "application/vnd.ms-excel", "application/ms-excel", "application/x-msexcel"
};

if (! System.Linq.Enumerable.Contains(AllowedTypes, Type))
{
    Page.RegisterStartupScript(",", "<script>alert('O arquivo deve ser um XLS')</script>");

    return;
}
  • What is the value that variable Type taking?

1 answer

1

The HttpPostedFile.ContentType doesn’t catch the mime-type of the file while running, it picks up the content-type that the browser reported in payload during the request, or whatever determined this content-type that you see was the browser, ie the content detection occurs before the upload and occurs on the user’s machine.

This I say right away is not such a reliable way, because any HTTP request can be manipulated.

For example in an upload request of a valid file I made, called 2.xls, resulted in this:

POST /upload HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 27329
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryjUAtIb3hLXspUBmo
Host: localhost
Origin: http://localhost
Referer: http://localhost/form
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36 OPR/49.0.2725.47

------WebKitFormBoundaryjUAtIb3hLXspUBmo
Content-Disposition: form-data; name="file"; filename="2.xls"
Content-Type: application/vnd.ms-excel


------WebKitFormBoundaryjUAtIb3hLXspUBmo--

Now this was the result of a xls file invalid, called 3.xls, which is actually just a content text file this just foo bar, the result was (summarized the result to display only the relevant part):

------WebKitFormBoundarySMenF7hr3QNf4T6l
Content-Disposition: form-data; name="file"; filename="3.xls"
Content-Type: application/vnd.ms-excel


------WebKitFormBoundarySMenF7hr3QNf4T6l--

See, he accused it is application/vnd.ms-excel, that is not what is expected.


Upload from Arqivos doc, docx, xls, xlsx, ppt, pptx appear as "application/octet-stream"?

I know that in my example appeared application/vnd.ms-excel, but that’s the point I want to make, I’m not sure of the conditions that the upload was made, but one thing I can tell you, if you’re using an older browser, I’ve noticed that most modern browsers, even IE11, tries to do a good job to detect and pass on the most correct mime-type to a specific file type, but really has no way to guarantee.

I even looked for some package via Nuget: https://www.nuget.org/packages?q=mime+type, only that I only found those guess what by file extension, ie would not be a mime-type detection and rather a map, which would not be anything interesting, because it would install something else for something you could simply validate using something like:

using System.IO;

...

string Nome = UP_Dados.PostedFile.FileName;

if (Path.GetExtension(Nome).ToLower() == ".xls") {
      //Validou
} else {
      //Não validou
}

The most I could find of anything supposedly work for this is the function FindMimeFromData, that is not native to C#, he is part of the urlmon.dll, what I found of attempts of use were:

However when testing 3 files, the 1.xlsx, 2.xls and 3.xls (fake file), I got this result:

resulatdo do urlmon.dll com FindMimeFromData

It is important to note that the urlmon is a part of Internet Explorer that is installed on your server, my IE is the most updated and yet these 3 documents were not recognized, so the solution is not as functional as expected (I tried the two responses linked above)


How to resolve to detect mime-type?

For now there’s no way, at least I have not found any solution that uses for example a copy of the file MAGIC (https://linux.die.net/man/5/magic), then for now the nearest solution would be perhaps to check the ContenType (even if it is something that can be manipulated) and appears application/octet-stream then use a fallback to check the extension, something like this:

using System;
using System.IO;
using System.Linq;

...

string ContentType = UP_Dados.PostedFile.ContentType;
string FileName = UP_Dados.PostedFile.FileName;
bool validate = false;

string[] AllowedTypes = {
    "application/excel",
    "application/x-excel",
    "application/ms-excel",
    "application/x-msexcel",
    "application/vnd.ms-excel",
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
};

//Para o fallback, acaso o navegador enviar a extensão octet-stream ou zip
string[] FallckExtensions = { ".xls", ".xlsx" };
string[] FallbackMimes = {
    "application/zip",
    "application/octet-stream",
    "application/x-zip-compressed"
};

//Se ContentType for um dos FallbackMimes, então checa a extensão
if (FallbackMimes.Contains(ContentType)) {
    string extension = Path.GetExtension(FileName).ToLower();
    validate = FallckExtensions.Contains(extension);
} else {
    //Se o ContentType enviado pelo navegador não for octet-stream ou zip testa o AllowedTypes
    validate = AllowedTypes.Contains(ContentType);
}

Example in ideone

If not working with XLSX then remove from the script:

  • ".xlsx" of AllowedExtensions
  • "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" of AllowedTypes
  • "application/zip" and "application/x-zip-compressed" of FallbackMimes

Note: If I find any better solution I will review the answer

Browser other questions tagged

You are not signed in. Login or sign up in order to post.