16

I'm creating an ASP.Net form with a fileupload control which will then email the details of the form and the file to another admin. I want to ensure this secure (for the server and the recipient). The attachment should be a CV so I will restrict it to typical text documents.

From what I can tell the best bet is to check that the file extension or MIME Type is of that kind and check it against the "magic numbers" to verify that the extension hasn't been changed. I'm not too concerned about how to go about doing that but want to know if that really is enough.

I'd also be happy to use a third party product that takes care of this and I've looked at a couple:

blueimp jQuery file upload http://blueimp.github.io/jQuery-File-Upload/

and cutesoft ajaxuploader http://ajaxuploader.com/Demo/

But blueimp one still seems to require custom server validation (i guess just being jQuery it just handles client-side validation) and the .net one checks the MIME-type matches the extension but I thought the MIME type followed the extension anyway.

So,

Do I need to worry about server security when the file is added as an attachment but not saved? Is there a plugin or control that takes care of this well? If I need to implement something for server validation myself is matching the MIME-type to the "magic numbers" good enough?

I'm sure nothing is 100% bulletproof but file upload is pretty common stuff and I assume most implementations are "safe enough" - but how!?

If it's relevant, here is my basic code so far

<p>Please attach your CV here</p>
<asp:FileUpload ID="fileUploader" runat="server" />

and on submit

MailMessage message = new MailMessage();
if (fileUploader.HasFile)
{
    try
    {
        if (fileUploader.PostedFile.ContentType == "text")
        {
            // check magic numbers indicate same content type... if(){}

            if (fileUploader.PostedFile.ContentLength < 102400)
            {
                string fileName = System.IO.Path.GetFileName(fileUploader.PostedFile.FileName);
                message.Attachments.Add(new Attachment(fileUploader.PostedFile.InputStream, fileName));
            }
            else
            {
                // show a message saying the file is too large
            }
        }
        else
        { 
           // show a message saying the file is not a text based document
        }
    }
    catch (Exception ex)
    {
        // display ex.Message;
    }
}
wunth
  • 634
  • 4
  • 13
  • _"Do I need to worry about server security when the file is added as an attachment but not saved?"_ Not sure what you mean? What is "saved"? "secure" as to which portion of the process? Are you trying to remove the file object from `` `.files` property if the conditions are not met? – guest271314 Oct 17 '17 at 02:17
  • @guest271314 the user is uploading the file and it's added as an attachment to an email which is then sent. As far as I know this doesn't result in the file being saved on the server, I guess it ends up on a mail server. The recipient may well save it but I meant it's not saved on the server. – wunth Oct 17 '17 at 02:20
  • _"The recipient may well save it but I meant it's not saved on the server."_ What concerns do you have given the described procedure? – guest271314 Oct 17 '17 at 02:21
  • @guest271314 My concerns are a) that I can't say for sure whether the file isn't "read" on the server and therefore embedded malicious code can run b) The recipient may end up the victim of a malicious file – wunth Oct 17 '17 at 02:24
  • If you are in control of the server you should know if the file is read at server. How would the file "run"? – guest271314 Oct 17 '17 at 02:26
  • @guest271314 I don't know the mechanisms behind how ASP.Net transfers a file from an upload to a mail server. Malicious code in files seems to be a genuine threat and concern from what I've read but I don't know how to deal with it properly. I don't know how it runs, I only want to ensure it doesn't – wunth Oct 17 '17 at 02:33
  • _"Malicious code in files seems to be a genuine threat and concern from what I've read"_ Can you include link what you have read at Question relevant to an uploaded file being capable of running malicious code? – guest271314 Oct 17 '17 at 02:35
  • @guest271314 if I google "how to secure file upload" I get a bunch of results showing me upload vulnerabilities. Our organisation recently suffered an attack which came in via email (executed via a vb script in a word doc I think) and I really don't want to be the one responsible to open a door to this sort of thing. I might be making a mountain out of a molehill - hopefully, but I want to be sure... – wunth Oct 17 '17 at 02:46
  • 1
    @guest271314 while I am wary of someone scaremongering to sell something: https://www.acunetix.com/websitesecurity/upload-forms-threat/ – wunth Oct 17 '17 at 02:50
  • What type of file is expected to be uploaded? – guest271314 Oct 17 '17 at 02:58
  • @guest271314 The file type is mentioned in the question - I want to accept CVs so can reasonably limit that to doc or docx or whatever mac users create etc. – wunth Oct 17 '17 at 03:06
  • What is CV? It is possible to suggest a file type which users can upload using `accepts` attribute at `` element, though the user can select a different file type. Given the linked page, you could parse the entire file as text at server to determine if code is included within file. – guest271314 Oct 17 '17 at 03:09
  • Yes the 'accepts' attribute is part of this but as w3 says: "Do not use this attribute as a validation tool. File uploads should be validated on the server". And the issue is also that file extensions can be changed. To answer your request for a link - this is what initially alerted me to the possibility of malicious code running on the server: https://forums.asp.net/t/1930613.aspx?File+Upload+Security . At this point I really feel that this thread is about me trying to inform you rather than the other way around – wunth Oct 17 '17 at 03:16
  • Have not tried `asp.net`. Is the server using `php`, `C#` or `C++` to process the file? The key would be what the expected input is. All content outside of the expected input can be excluded. This could probably be achieved client side using `FileReader` and other means. – guest271314 Oct 17 '17 at 03:19
  • Why don't you zip them? In this way you will still have the data but not in any executable form. – GramThanos Oct 23 '17 at 10:44
  • 1
    @GramThanos I really liked that idea at first but I don't think it solves the issue of embedded code or macros etc. - The file would just be interacted with more on the server in order to zip it and also the recipient will still get the same file after they unzip it. To be honest, I think my problem is a terrible mixture of ignorance and paranoia! My solution has been to take a pragmatic approach with a few reasonable measures and understanding that our infrastructure has measures to protect itself further upstream - I'll write up more detail on it soon. Smart suggestion though, thanks! – wunth Oct 24 '17 at 01:41
  • @wunth my thoughts were too big for a comment, so I posted some helpful actions as an answer. – GramThanos Oct 24 '17 at 03:14

1 Answers1

5

A server can never be 100% secure, but we should do our best to minimize the risk on an incident. I should say at this point that I am not an expert, I am just a computer science student. So, here is an approach that I would follow in such a case. Please, comment any additional tip you can give.


Generally speaking, to have a secure form, all client inputs must be checked and validated. Any information that does not origin from our system is not trusted.

Inputs from the client in our case:

  • file's name
    • name
    • extension
  • file's content

Extension

We don't really care about the minetype, this is info for a web server. We care about the file extension, because this is the indicator for the OS on how to run/read/open a file. We have to support only specific file extensions (what ever your admin's pc can handle) there is no point supporting unknown file types.

Name (without the extension)

The name of the file is not always a valuable info. When I deal with file uploading I usually rename it (set it) to an id (a username, a time-stamp, hashes etc). If the name is important, always check/trim it, if you only expect letters or numbers delete all other chars (I avoid to leave "/", "\", "." because they can be used to inject paths).

So now we suppose that the generated file name is safe.

Content

When you support no structured files, you just can not validate the file's content. Thus, let an expert program do this for you... scan them with an antivirus. Call the antivirus from the console (carefully, use mechanics that avoid injections). Many antivirus can scan zips contents too (a malicious file, in a folder on your server is not a good idea). Always keep the scan program updated.


On the comments I suggested zipping the file, in order to avoid any automatic execution on the admin's machine and on the sever. The admin's machine's antivirus can then handle it before unzip.

Some more tips, don't give more information's to the client than he needs... don't let the client know where the files are saved, don't let the web-server access them for distribution if there no need to. Keep a log with weird actions (slashes in filenames, too big files, too long names, warning extensions like "sh" "exe" "bat") and report the admins with an email if anything weird happen (it is good to know if your protections work).

All these creates server work load (more system holes), so you may should count the number of files that are scanned/checked at the moment before accepting a new file upload request (that is where I would launch a DDoS attack).

With a quick google search Avast! For Linux - Command Line Guide, I do not promote Avast, I am just showing it as an existing example.

Lastly but not least, you are not paranoid, I manage a custom translation system that I coded... spams and hack attacks have occurred more than once.


Some more thoughts, JavaScript running on a web-page is only secure for the client's computer (thanks to the browser's security). We can use it to prevent invalid posts to the server but this does not ensures that such requests will not be done as JavaScript can be bypassed/edited.

So, all JavaScript solutions are only for a first validation (usually just to help the user correct mistakes) and to correctly set the form data.

GramThanos
  • 3,572
  • 1
  • 22
  • 34