Fortify Cross-site scripting: Persistent issue in Response.Binarywrite - asp.net

In an existing Asp.Net application, we are using Response.BinaryWrite to render image on an aspx page. This is the required functionality, and below is the C# code-
1. byte[] img = getImage();
2. Response.BinaryWrite(img);
The getImage function reads the image from a folder on server and returns byte array. Fortify scan shows cross-site vulnerability on 2nd line.
I did following validations, but fortify still reports it as cross-site issue -
Validated bytearray to check if the file is of correct format (jpeg or bmp), used this link - Determine file type of an image
Response.BinaryWrite(ValidateFileType(img));
Validated the domain in the file path to check if the file is originating from correct domain.
Is there any specific way to pass the fortify cross-site issue with byte array or can i consider it as false positive?

Had to use a workaround to resolve this, below is the old and new code -
Old Code -
1. byte[] byteImage = getImage();
2. Response.BinaryWrite(byteImage);
New Code (Replaced 2nd line in old code with below block) -
byte[] byteImage = getImage();
var msIn = new MemoryStream(byteImage);
System.Drawing.Image img = System.Drawing.Image.FromStream(msIn);
var msOut = new MemoryStream();
img.Save(msOut, img.RawFormat);
Response.BinaryWrite(msOut.ToArray());
msIn.Dispose();
msOut.Dispose();
Response.Flush();
So, basically converting the byteArray to an Image object, and then writing the image object back to the Response.BinaryWrite stream resolved this, and it passed through Fortify scan.
If anyone is looking for a solution, this might help.

Related

Extracting Windows File Properties with http link

I am working on this problem and the proposed solution works for me.
However, now I need to make this work in my actual application which is an AWS Beanstalk .NET web application. My beanstalk application knows the url source of the picture. Knowing the url, I can get a stream and process the file (by creating a byte array and even a Bitmap object).
However, it seems that to get the file properties as mentioned above (such as the camera type or painting application that created the file), I really need a local file because that is the expected input argument.
This is a problem for me. I know the http link, I know the bytes but I have no such thing as a file path.
How can I solve this? I need the windows file properties.
If I understood you correctly, you want to read image metadata from a URL without saving it to a file first, i.e. directly from the Internet.
Here is one way that works for me:
string demoImageUrl = "https://raw.githubusercontent.com/ianare/exif-samples/master/jpg/Canon_40D.jpg";
byte[] imgData = null;
using (var wc = new WebClient())
{
imgData = wc.DownloadData(demoImageUrl);
}
using (var sr = new MemoryStream(imgData, false))
{
BitmapSource image = BitmapFrame.Create(sr);
BitmapMetadata md = (BitmapMetadata)image.Metadata;
string comment = md.Comment;
string title = md.Title;
string dateTaken = md.DateTaken;
}
You need to add references to PresentationCore and WindowsBase assemblies and also include the following namespace:
using System.Windows.Media.Imaging;

FileResult not returning proper file type and file name

I have an ASP.NET MVC application with an ActionResult called GenerateReport. I'm trying to return a byte array to save an Excel file. Here are snippets:
var contentType = "application/vnd.ms-excel";
var fileName = "Statistics.xlsx";
...
var fileBytes = package.GetAsByteArray();
return File(fileBytes, contentType, fileName);
When I'm prompted to save the file, it sometimes (but not always) asks what I want to do with "GenerateReport". It's naming the file the same as the ActionResult and it's not giving it a file type. I will request to save it and it will say that it failed to save. I will select Retry and it will save fine. Then, if I rename it to an .xlsx, all of the data is there and correct. I'm using IE9 and Chrome and I haven't noticed it happen in Chrome. Unfortunately, it needs to work in IE9.
Does anyone know why it's not getting my content type and file name sometimes?
Check the response for Content-Encoding. It might be the same issue like here PHP File Serving Script: Unreliable Downloads?

The process cannot access the file because it is being used by another process at SharePoint 2010 C# code

I am creating custom timer job service in SharePoint 2010 using asp.net 3.5 and c#.In this service, business logic is that i have to create zip file containing list of applications as excel report for each client.for this, i am using Ionic.zip third party dll and ZipFile class for creating zip file and storing this zip file on hard disk having some path.here scenario is that my code contains two foreach loops, upper for list of clients and inner for list of applications.each client may have no. of applications.I am adding these applications to zip file, storing it on hard disk and attaching this file to mail for sending to clients, but my problem is that I am trying to delete zip file before gone to next client, so that there should not be any files on hard disk, but I am getting error as "The process cannot access the file because it is being used by another process".also I have tried to attach output stream for excel report as mail attachment but I am getting zero bytes in attachment. how should i overcome this error.
I am giving simple code below
foreach(list of clients)////may have no. of clients
{
string zipFileDownloadPath = String.Empty;
foreach(list of applications)//may have no. of applications
{
HttpWebResponse resp = (HttpWebResponse)httpReq.GetResponse();
Stream excelReport = resp.GetResponseStream();
zipFile.AddEntry(appName, excelReport);
}
zipFileDownloadPath = clientFolder + #"\" + client["client_name"] + "_" + reportDate + ".zip";
zipFile.Save(zipFileDownloadPath);
mail.Attachments.Add(new Attachment(zipFileDownloadPath));
smtp.Send(mail);//mail have body, subject etc.
//here I am deleting files
if (Directory.Exists(clientFolder))
{
Directory.Delete(clientFolder, true);//here I am getting error
}
}
I the above code I have also tried so save zipfile to output stream so that there should not be any need for storing files on hard disk and attach this stream to mail attachment, but problem is that, i am getting proper bytes in output stream but when mail is sent, i am getting zero byes in attachment.
//here is code for attaching output stream to mail
foreach(list of clients)////may have no. of clients
{
foreach(list of applications)//may have no. of applications
{
HttpWebResponse resp = (HttpWebResponse)httpReq.GetResponse();
Stream excelReport = resp.GetResponseStream();
zipFile.AddEntry(appName, excelReport);
}
Stream outputStream = new MemoryStream();
zipFile.Save(outputStream);
mail.Attachments.Add(new Attachment(outputStream,"ZipFileName" MediaTypeNames.Application.Zip);));
smtp.Send(mail);//mail have body, subject etc.
}
Try moving the position of the stream to it's begiining before sending it to the attachement:
outputStream .Seek(0, SeekOrigin.Begin);
Also before deleting your file make sure you dispose the zipFile object:
zipFile.Dispose()
Or alternately (better) wrap it in a using statement.
Also unless I am missing something if you are using streams, why do you need to save the files to the harddrive? just use the streams, something along the lines of:
var ms = new new MemoryStream();
zipFile.Save(ms);
ms.Seek(0, SeekOrigin.Begin);
mail.Attachments.Add(new Attachment(ms,"ZipFileName" MediaTypeNames.Application.Zip));
zipFile.Dispose()
Special thanks to Luis.Luis has solved my problem.
Hi Everyone Finally I have solved my problem. problem was that I was saving the zip file on output stream so stream was reading exact bytes and reaching at it's last position and I was attaching same stream to attachment that's why i was getting zero bytes in mail attachment.so solution for this is that seek the position of output stream to begin after saving to zip file and before attaching to it to mail. please refer following code for reference.
Stream outputStream = new MemoryStream();
zipFile.Save(outputStream);
outputStream .Seek(0, SeekOrigin.Begin);
mail.Attachments.Add(new Attachment(outputStream,"ZipFileName" MediaTypeNames.Application.Zip);));

ASP.NET MVC3: Cant find/access file

String DocLocation = System.AppDomain.CurrentDomain.BaseDirectory + "Files/test.pdf";
// or
String DocLocation = Url.Content("~/Files/test.pdf");
var document = new FileStream(DocLocation, FileMode.Open);
var mimeType = "application/pdf";
var fileDownloadName = "download.pdf";
return File(document, mimeType, fileDownloadName);
The first method is UnauthorizedAccessException.
The second method cant find the file.
I am trying to send a file for download. Using full desktop path seems to work.
Also, how would I display PDF in the browser instead (note, still need download option as not all are pdf)?
Try Server.MapPath("~/Files/test.pdf")
File() takes a physical path on disk.
Therefore, you can't use Url.Content, since that returns a relative URL for the browser.
Instead, you need Server.MapPath, which converts an application relative path into a full path on the local disk.

How can I create an image object from an FileUpload control in asp.net?

I have a FileUpload control. I am trying to save the file that is uploaded (an image) and also save several thumbnail copies of the file.
When I try something like this:
System.Drawing.Image imgOriginal = System.Drawing.Image.FromStream(PhotoUpload.PostedFile.InputStream);
I get an "System.ArgumentException: Parameter is not valid."
I also tried using the PhotoUpload.FileBytes to create the image from the file bytes instead of the InputStream, but the same error occurs.
The uploaded file is a jpg. I know it's a valid jpg since it saves the original ok.
Edit: This code actually does work. The Parameter is not valid was due to the PhotoUpload.PostedFile.InputStream being empty... which seems to be an entirely different issue. It looks like after I save the original the fileupload stream goes away.
Edit: Found out that the InputStream of a FileUpload can only be read/consumed one time and then it is gone.
To get around that I saved the fileupload filebytes into a byte array and used the byte array to create copies of the image.
Code:
// Copy the FileBytes into a byte array
byte[] imageData = PhotoUpload.FileBytes;
// Create a stream from the byte array if you want to save it somewhere:
System.IO.Stream myStream = new System.IO.MemoryStream(imageData);
// Or create an image from the stream as many times as needed:
System.Drawing.Image imgOriginal = System.Drawing.Image.FromStream(myStream);
Have a look at this link
ASP Net - How to pass a postedfile to a system.drawing.image
Here's my function call:
uploadAndSizeImage(System.Drawing.Image.FromStream
(uploadedFileMD.PostedFile.InputStream))
I'm getting this error:
Exception Details:
System.ArgumentException: Invalid
parameter used.
Google isn't turning up much though I
did find a reference to it possibly
being caused by the stream reader
being at the end of the stream and me
needing to reset it to position one.
But that was kind of vague and not
really sure if it applies here.
Does this help?
EDIT:
Also, have you tried manually reading the file using something like
System.IO.FileStream fs = System.IO.File.OpenRead(#"Image.JPG");
byte[] data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
System.IO.MemoryStream ms = new System.IO.MemoryStream(data);
System.Drawing.Image image = Image.FromStream(ms);
Or saving a temp copy from the FileUpload and loading the image from file?

Resources