Can I test the validity of an image file before uploading it in ASP.NET? - asp.net

I have an ASP.NET web application that allows the user to upload a file from his PC to a SQL Server database (which is later used to generate an image for an tag). Is there an "easy" way to test the image within .NET to validate that it does not contain anything malicious before saving it?
Right now, I use this:
MemoryStream F = new MemoryStream();
Bitmap TestBitmap = new Bitmap(Filename);
TestBitmap.Save(F, System.Drawing.Imaging.ImageFormat.Png);
int PhotoSize = (int)F.Length;
Photo = new byte[PhotoSize];
F.Seek(0, SeekOrigin.Begin);
int BytesRead = F.Read(Photo, 0, PhotoSize);
F.Close();
Creating TestBitmap fails if it is not an image (e.g. if Filename is the name of a text file), but apparently this doesn't stop a file that is an image with malicious code appended to it from loading as an image, so saving it as a MemoryStream and then writing the stream to a byte array (which is later saved in the database) supposedly fixes this.

To avoid people pass programs and other information's using the ability to upload photos to your site you can do two main steps.
Read and save again the image with your code to remove anything elst.
Limit the size of each image to a logical number.
To avoid some one upload bad code and run it on your server you keep an isolate folder with out permission to run anything. More information's about that on:
I've been hacked. Evil aspx file uploaded called AspxSpy. They're still trying. Help me trap them‼
And a general topic on the same subject: Preparing an ASP.Net website for penetration testing

Related

Generating Excel Documents with ASP.NET Website

I have an ASP.NET application that helps the user create a Gridview with certain data in it. Once this table is generated I want the user to push a button and be able to save the table as an Excel document.There are two different methods I know of:
Using HtmlTextWriter with ContentType "application/vnd.ms-excel" to send the file as an HttpResponse. I use GridView1.RenderControl(htmlTextWriter) to render the gridview. This almost works, but the excel file always shows a warning when the file opens because the content doesn't match the extension. I have tried various content types to no avail. This makes sense I guess, because I'm using an HtmlWriter. It also doesn't seem a good practice.
The second thing I've tried is generating the Excel file using Office Automation. But for the file to be generated, I need to save it to disk and then read it again. From what I have read, this is the only way, because the Excel object only becomes a real Excel file once you save it. I found that the .saveas method from the Excel class would throw an exception because of write permissions, even if I tried to save in the App_Data folder. So I did some research and found that apparently Office Automation is discouraged for web services: https://support.microsoft.com/en-us/kb/257757
Microsoft does not currently recommend, and does not support,
Automation of Microsoft Office applications from any unattended,
non-interactive client application or component (including ASP,
ASP.NET, DCOM, and NT Services), because Office may exhibit unstable
behavior and/or deadlock when Office is run in this environment.
There surely must be a save way to have a website generate an Excel file and offer it to the user!? I can't imagine that this problem is unsolved or so rare that nobody cares about it, but yet I can't find any good solution to this.
the easiest (and best) way to create an excel file is by using epplus
Epplus sample for webapplication
using (ExcelPackage pck = new ExcelPackage())
{
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Demo");
//Load the datatable into the sheet, starting from cell A1. Print the column names on row 1
ws.Cells["A1"].LoadFromDataTable(tbl, true);
//Format the header for column 1-3
using (ExcelRange rng = ws.Cells["A1:C1"])
{
rng.Style.Font.Bold = true;
rng.Style.Fill.PatternType = ExcelFillStyle.Solid; //Set Pattern for the background to Solid
rng.Style.Fill.BackgroundColor.SetColor(Color.FromArgb(79, 129, 189)); //Set color to dark blue
rng.Style.Font.Color.SetColor(Color.White);
}
//Example how to Format Column 1 as numeric
using (ExcelRange col = ws.Cells[2, 1, 2 + tbl.Rows.Count, 1])
{
col.Style.Numberformat.Format = "#,##0.00";
col.Style.HorizontalAlignment = ExcelHorizontalAlignment.Right;
}
//Write it back to the client
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=ExcelDemo.xlsx");
Response.BinaryWrite(pck.GetAsByteArray());
}

SQLFileStream with a chunked file

I'm a little stuck in trying to upload files into our SQL DB using FileStream. I've followed this example http://www.codeproject.com/Articles/128657/How-Do-I-Use-SQL-File-Stream but the difference is we upload the file in 10mb chunks.
On the first chunk a record is created in the DB with empty content (so that a file is created) and then OnUploadChunk is called for each chunk.
The file is uploading ok but when I check, a new file has been created for each chunk, so for a 20mb file for example I have one which is 0kb, another which is 10mb and the final one which is 20mb. I'm expecting one file of 20mb.
I'm guessing this is perhaps to do with getting the transaction context or incorrectly using TransactionScope which I dont quite fully grasp yet. I presume this may be different for each chunk with it going to and from client to server.
Here is the method which is called every time a chunk is sent from the client (using PlupLoad if of any relevance).
protected override bool OnUploadChunk(Stream chunkStream, string DocID)
{
BinaryReader b = new BinaryReader(chunkStream);
byte[] binData = b.ReadBytes(chunkStream.Length);
using (TransactionScope transactionScope = new TransactionScope())
{
string FilePath = GetFilePath(DocID); (Folder path the file is sitting in)
//Gets size of file that has been uploaded so far
long currentFileSize = GetCurrentFileSize(DocID)
//Essentially this is just Select GET_FILESTREAM_TRANSACTION_CONTEXT()
byte[] transactionContext = GetTransactionContext();
SqlFileStream filestream = new SqlFileStream(FilePath, transactionContext, FileAccess.ReadWrite);
filestream.Seek(currentFileSize, SeekOrigin.Begin);
filestream.Write(binData, 0, (int)chunkStream.Length);
filestream.Close();
transactionScope.Complete();
}
}
UPDATE:
I've done a little research and I believe the issue is around this:
FILESTREAM does not currently support in-place updates. Therefore an update to a column with the FILESTREAM attribute is implemented by creating a new zero-byte file, which then has the entire new data value written to it. When the update is committed, the file pointer is then changed to point to the new file, leaving the old file to be deleted at garbage collection time. This happens at a checkpoint for simple recovery, and at a backup or log backup.
So have I just got to wait for the garbage collector to remove the chunked files? Or should I perhaps be uploading the file somewhere on the file system first and then copying it across?
Yes, you will have to wait for Sql to clean up the files for you.
Unless you have other system constraints you should be able stream the entire file all at once. This will give you a single file on the sql side

Retrieve image stored in in db and save to a file

I have a customer that is asking to be able to retrieve an image from a Sql Server Db and turn around and save it to a directory on his computer. He wants to be able to do this via a asp.net web page. I am able to retrieve the image from the image as a byte array but have no idea how to take that image and save it to the directory as a file. Anyone have any ideas on how to do this? Thanks.
You can try with Save Method
MemoryStream memoryStream = new MemoryStream((byte[])YourDataTable.Rows[0]["ImageData"]);
Picturebox picturebox = new Picturebox();
picturebox.Image = Image.FromStream(memoryStream);
picturebox.Image.Save("...YourPath", System.Drawing.Imaging.ImageFormat.Jpeg)

asp.net image jpeg not saving correctly

I am trying to save a jpeg image in an uploads folder which has correct permissions setup. When I test the file is being saved (eg: images/uploads/Winter.jpg) but if I try to view the image in my browser or if I attempt to open the image using anything else the image does not display.
I think that the file is not being encoded correctly before saving it to disk but am not very experienced dealing with the saving of files, encoding. Does the below code look ok or do I need to encode the file being uploaded somehow before saving it to disk?
String imgPath = "newsletter\\images\\uploads\\";
String filename = System.IO.Path.GetFileName(upload.PostedFile.FileName);
filepath = imgPath + filename;
filepath = Request.PhysicalApplicationPath + filepath;
upload.PostedFile.SaveAs(filepath);
The file saves to the correct folder but is only 150bytes in size. If I try to browse to the file and view it with an image viewer it does not display correctly.
Encoding shouldn't be a problem - the raw data isn't changing. However, it's possible the browser isn't sending all the data, or that the upload control is deleting the data before you're saving it.
Make sure that you call .SaveAs() before the page begins unloading, and before any additional postbacks. I think we'll need to see more surrounding code to help further.
Another note - by allowing the existing file extension to be used, you're allowing users to upload .aspx files, which could subsequently be executed through a request. Safe filenames are GUIDs and whitelisted file extensions. Using un-sanitized uploaded path information is very dangerous. If you re-use filenames, sanitize them to alphanumerics.

storing the files in a web application in asp.net

I have set of components that i wish to let the users download from my web application.
Now the question is where should i place the files in app_data or create a separate folder in asp.net web application as shown here or is there any other optimal solution for this ?
What i mean by components is you can take a look at this ! So what is the best way to do store the components ?
Right now what i'm doing is: i'm storing the files in a external folder outside the application more specifically in documents folder of my c drive, and i'm storing the path to a component as a data element of the table, when ever user clicks on a particular row's button (in the grid view) i'm getting the title of that particular clicked row and querying the database table for the filepath of that component title using these lines of code:
String filePath = dr1[0].ToString(); //GETS THE FILEPATH FROM DATABASE
HttpContext.Current.Response.ContentType = "APPLICATION/OCTET-STREAM";
String disHeader = "Attachment; Filename=\"" + filePath + "\"";
HttpContext.Current.Response.AppendHeader("Content-Disposition", disHeader);
System.IO.FileInfo fileToDownload = new System.IO.FileInfo(filePath);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.WriteFile(fileToDownload.FullName);
Am i doing it properly ? Is there a better/optimal way to do it ?
A user simply needs read access to download a file, so you can simply create a directory claled "Downloads" and place them in there.
You can ensure that people can't "browse" that directory by disabling Directory Browsing and not placing any default docs in there (index.html, default.aspx for example)
What you are currently doing looks like a fairly standard way for providing downloads off your site.
I can't think of something more "optimal".

Resources