A custom ActionResult for a multi-part http response? - asp.net-mvc

I'd like to respond to an http request with both a txt file and an html page. This way the client can save the file and see a summary of that file's contents via an html page.
Since the file is generated on the fly, I have to use state management on the server to generate the summary on the second request. I'd like to avoid this and wrap this up in a single response.
What would the custom ActionResult look like?

This was also discussed here on SO.
i answered it like this:
Nope, multipart attachments for
download (like as in email) aren't
supported for security reasons. It's
called a "drive-by download."
Note that Gmail handles this by
dynamically zipping up the files. You
should too.
http://forums.asp.net/t/1240811.aspx
I don't believe any modern browser supports multipart/mixed.

You could send XML with reference to an XSLT stylesheet. The browser can do the transformation and display a resulting HTML output.
And the user may simple do "File->Save as ..." to store the XML file.

Why not render the summary as normal HTML View and provide a link under that summary that points to a separate ActionResult that returns binary data...
public ActionResult SendFile(int id)
{
File file = FileRepository.GetFile(id);
byte[] fileData = file.FileData.ToArray();
return File(fileData, file.FileMimeType, file.FileName);
}

I did some search on this topic and to my surprise, this seems people did this already. I found a description here, but it does not provide a public test URI, so I couldn't test browser behaviour on this. It also mentiones the solution to send an archive file to the client. But I assume that's not what you're looking for, right?
Here is another article showing an example with multipart responses. Sadly, the demo URI seems not to be working any more.
So the situation is this: HTTP multipart responses can be done. There are client (few) libraries to handle those in application code. Browser behaviour is to be tested (Here's a voice). Using this feature seems experimental and may be recommended only you can control both ends of the communication to eliminate interoperability issues.

Related

Swagger-UI how much modification can be done

I have some questions regarding swagger-ui. I have downloaded the swagger-ui from here and have played around with the index.html and tried modifying it. From what I understand the UI is dynamically generated based on the open api specification doc either in a yaml or json file format. My questions are as follows
How much modification can be done to the UI that is being generated by the Swagger?
Can "Try Out" functionality be modified to have more control? What I want to do is have few input fields which are not generated by swagger and use them as input for an api call, make UI more dynamic in nature.
Does the Swagger-UI depend on any sort of API gateway to make calls to api endpoints?
Thanks,
Salil
How much modification can be done to the UI that is being generated by the Swagger?
Swagger UI can be tweaked in very different ways mainly via JS or CSS.
You can have a look to https://swagger.io/docs/open-source-tools/swagger-ui/customization/overview/
Can "Try Out" functionality be modified to have more control? What I want to do is have few input fields which are not generated by swagger and use them as input for an api call, make UI more dynamic in nature.
You should have a look to the link I shared above but not sure this is doable like this.
If I had to do such kind of thing I would rather look at how to complete the original OpenAPI definition (the yaml/JSON file) before passing it to Swagger UI.
Note that there is also a "interceptor" feature in Swagger UI that allow to modify requests before sending them for instance. This might interest you.
Does the Swagger-UI depend on any sort of API gateway to make calls to api endpoints?
Not at all. Swagger UI just uses your browser to call the API at the URL documented by the OpenAPI file.
Stack Overflow doesn't work well when there are multiple questions as part of one "Question". Having said that, I'll answer what I know.
As far as I can tell, you can modify the yaml or JSON source as much as you like. You can write an entire file from scratch, or import it from any editor.
For this sort of testing, I think you might want to look for a more in-depth testing tool such as Postman. That's not something I have any experience with, but from what I hear it could help with "what if I send this request?" sceanrios.

Prevent XSS attacks and still use Html.Raw

I have CMS system where I am using CK Editor to enter data. Now if user types in <script>alert('This is a bad script, data');</script> then CKEditor does the fair job and encodes it correctly and passes <script>alert('This is a bad script, data')</script> to server.
But if user goes into browser developer tools (using Inspect element) and adds this inside it as shown in the below screen shot then this is when all the trouble starts. Now after retrieving back from DB when this is displayed in Browser it presents alert box.
So far I have tried many different things one them is
Encode the contents using AntiXssEncoder [HttpUtility.HtmlEncode(Contents)] and then store it in database and when displaying back in browser decode it and display it using MvcHtmlString.Create [MvcHtmlString.Create(HttpUtility.HtmlDecode(Contents))] or Html.Raw [Html.Raw(Contents)] as you may expect both of them displays JavaScript alert.
I don't want to replace the <script> manually thru code as it is not comprehensive solution (search for "And the encoded state:").
So far I have referred many articles (sorry not listing them all here but just adding few as proof to show I have put sincere efforts before writing this question) but none of them have code which shows the answer. May be there is some easy answer and I am not looking in right direction or may be it is not that simple at all and I may need to use something like Content Security Policy.
ASP.Net MVC Html.Raw with AntiXSS protection
Is there a risk in using #Html.Raw?
http://blog.simontimms.com/2013/01/21/content-security-policy-for-asp-net-mvc/
http://blog.michaelckennedy.net/2012/10/15/understanding-text-encoding-in-asp-net-mvc/
To reproduce what I am saying go to *this url and in the text box type <script>alert('This is a bad script, data');</script> and click the button.
*This link is from Michael Kennedy's blog
It isn't easy and you probably don't want to do this. May I suggest you use a simpler language than HTML for end user formatted input? What about Markdown which (I believe) is used by Stackoverflow. Or one of the existing Wiki or other lightweight markup languages?
If you do allow Html, I would suggest the following:
only support a fixed subset of Html
after the user submits content, parse the Html and filter it against a whitelist of allowed tags and attributes.
be ruthless in filtering and eliminating anything that you aren't sure about.
There are existing tools and libraries that do this. I haven't used it, but I did stumble on http://htmlpurifier.org/. I assume there are many others. Rick Strahl has posted one example for .NET, but I'm not sure if it is complete.
About ten years ago I attempted to write my own whitelist filter. It parsed and normalized the entered Html. Then it removed any elements or attributes that were not on the allowed whitelist. It worked pretty well, but you never know what vulnerabilities you've missed. That project is long dead, but if I had to do it over I would have used an existing simpler markup language rather than Html.
There are so many ways for users to inject nasty stuff into your pages, you have to be fierce to prevent this. Even CSS can be used to inject executable expressions into your page, like:
<STYLE type="text/css">BODY{background:url("javascript:alert('XSS')")}</STYLE>
Here is a page with a list of known attacks that will keep you up at night. If you can't filter and prevent all of these, you aren't ready for untrusted users to post formatted content viewable by the public.
Right around the time I was working on my own filter, MySpace (wow I'm old) was hit by an XSS Worm known as Samy. Samy used Style attributes with embedded background Url that had a javascript payload. It is all explained by the author.
Note that your example page says:
This page is meant to accept and display raw HTML by trusted
editors.
The key issue here is trust. If all of your users are trusted (say employees of a web site), then the risk here is lower. However, if you are building a forum or social network or dating site or anything that allows untrusted users to enter formatted content that will be viewable by others, you have a difficult job to sanitize Html.
I managed to resolve this issue using the HtmlSanitizer in NuGet:
https://github.com/mganss/HtmlSanitizer
as recommended by the OWASP Foundation (as good a recommendation as I need):
https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.236_-_Sanitize_HTML_Markup_with_a_Library_Designed_for_the_Job
First, add the NuGet Package:
> Install-Package HtmlSanitizer
Then I created an extension method to simplify things:
using Ganss.XSS;
...
public static string RemoveHtmlXss(this string htmlIn, string baseUrl = null)
{
if (htmlIn == null) return null;
var sanitizer = new HtmlSanitizer();
return sanitizer.Sanitize(htmlIn, baseUrl);
}
I then validate within the controller when the HTML is posted:
var cleanHtml = model.DodgyHtml.RemoveHtmlXss();
AND for completeness, sanitise whenever you present it to the page, especially when using Html.Raw():
<div>#Html.Raw(Model.NotSoSureHtml.RemoveHtmlXss())</div>

Forcing a page to POST

This may be a very unusual question, but basically there's a page on another domain (that I can view, but can't edit/change) that has a button. When that button is clicked it generates some unique keys.
I need to pull those unique keys with my web service (using ASP .NET MVC3) I can get the initial HTML of the page, but how can I force the page to "click" the button so that I can get the values after the POST?
Normally, I'd reuse the code to generate keys myself, but I don't have access to the logic.
I hope this makes sense.
Use e.g. firebug to see what POST parameters are sent with form and then make the same POST from your code.
For this you can use WebRequest or WebClient.
See this SO questions that will help you how to do it:
HTTP request with post
Send POST request in C# like a web page does?
How to simulate browser HTTP POST request and capture result in C#
Then just parse the response with technology of your choice (I would use regular expressions - Regex, or LinqToXml if the response is well formed XML).
Note: Keep in mind that your code will be dependent on some service you are not maintaining. So you can get in problems when the service is unavailable, discontinued or if the format of POSTed form or response will be changed.
This really depends on the technology on the targeted site.
If the page is a simple HTML form then you can easily send a POST. You will need to send the expected data to the POST. Then you can parse the data.
If its not so straight forward you will need to look into ways to automate the click. Check Selenium. Also you might need to employ scrapping if the results page is a mess.

Deleting an Azure Blob in MVC 3

I'm trying to delete blobs in an mvc 3 application that uses azure storage.
I'm trying to pass the Uri of the blob which will be deleted to the controller, however an error is thrown:
A potentially dangerous Request.Path value was detected from the client (:)
I think this is from the https: part of the Uri and I need to parse it out, however I'm not sure how to do that. I'm wondering how to fix this error.
Is there a more graceful way to delete a blob from storage?
You must properly URL encode your urls. Here's an example of a badly encoded url:
http://foo.com/controller/action?param=http://bar.com
Here's how it should look like:
http://foo.com/controller/action?param=http%3A%2F%2Fbar.com
Or maybe you are having an url of the form:
http://foo.com/controller/action/https://bar.com
which is even worse. If you want to use special characters in the Path portion of an URL you might find the following blog post useful.
If you want unsecure content to get through then you can add [ValidateInput(false)] to your action - however, this is opening up something that is there for your security - so only do this if you are sure you're code is secure - see first answer in A potentially dangerous Request.Form value was detected from the client
I was able to fix it and I want to summarize the solution, since it requires bit from the other two answers and bits mostly from the Scott Hanselman Blog post.
You need to do a few things to make this work:
Put the [ValidateInput(false)] on your action method.
Make sure your Url is properly encoded (an example is given in the above post) which is done when you use the blobVariableName.Uri.AbsoluteUri as the string to pass from your view to your controller, so you shouldn't have to do anything there.
Make your query string looks like
http://site/controller/action?blobid=http%3A%2F%2F... and NOT http://site/controller/action/http%3A%2F%2F... the latter won't work!
On a side note, since I started, our functional requirements changed and now were storing information about each blob in the database, which allows me to pass parameters other than the blob's uri, which seems like a much safer way to play it.
A great deal of the community appears to be in agreement that it is a bad idea to pass uri's and to open up your application as to allow you to do so.

How to get ContentType for file in ASP.NET MVC when using File Action Method

Attempting to use asp.net mvc's Action Result of File.
So it would seem that I have to specify a ContentType for the file to be sent to the browser. Currently there is no real limit to what types of files may be sent to the browser in my application, so I can't always assume it will be a "text/pdf", for example.
What's the best way of working out the ContentType of a file, or is there a way where this can be set to something 'generic'?
The simpler the better!
Thanks,
You either user the local machine's database of MIME types (from the registery):
http://www.codeproject.com/KB/dotnet/ContentType.aspx
or find an alternate dictionary. Like this duplicate SO question.

Resources