[The code for this post is available on GitHub]
This article covers the various ways in which you might handle text encoding in ASP.NET MVC. For example, if you were writing a forum web app, you should absolutely be paranoid about what your users are typing into your site. You need to be very careful about how you redisplay their input. For example, a friendly forum user might write something like:
Nice post, thanks for sharing!
On the other hand, they may write:
If you turn around and show this “post” to your other uses, maybe they’ll get hacked. At a minimum, the evil-doers could be a nuisance to your real users.
On the other hand, if you’re building a CMS or utility helper method, you do not want to filter out the HTML a user might type. They probably need to enter some HTML which you’ll want to show to all the other users. Same thing goes for code your app might generate.
There are at least three ways which MVC manages and encodes (or does not encode) text data. Knowing which scenario you’re targeting allows you to choose the right option. We’ll look at four examples in this post:
- A forum app which can be hacked
- A forum app which is safe from XSS injection
- A CMS app with rich text editing
- Generating HTML in code for use in MVC Razor views
Protecting Against Unwanted HTML Inputs
First, the good news. MVC protects you in several ways against any sort of HTML / JS injection issues. When you write out string contents such as below, it HTML encodes it by default when using @.
If we assume commentText = “<script src=’evil.js’></script>”, then the output would simply be:
That is <script src=’evil.js’></script> in view source, which is perfectly safe.
Next, it is unlikely that this input ever makes it to your site. By default, if you have an action method taking this input, it will just error out with the following message:
Error on submit:
A potentially dangerous Request.Form value was detected from the client…
Of course, we could disable this with a ValidateInput attribute:
In this case, you must be VERY careful when you write out the commentText values later.
So far we have seen that by default razor outputs text in a safe way using @value. Also, POST requests are blocked if they have dangerous content unless you let it in.
In order to demonstrate these concepts, I created a working sample app here:
View the safe forum and unsafe forum sections to see what happens. You can download the code from the sample as well.
Allowing Direct HTML Inputs
But what if you trust the input and need MVC out of the way so you can write true HTML content to the browser? One such example might be a CMS you’re writing. There are two cases you would treat differently here. Is your HTML coming from data given to your view or from code called by your view?
Let’s assume it’s handed to you as a string in a variable called cmsSectionData (i.e. data). Then we can use the helper method:
rather than @cmsSectionData. This will make the contents of cmsSectionData part of your HTML in the view. You will also need to disable validation on any edit pages using [ValidateInput(false)] as shown above.
Check out the CMS section of the demo to see it in action.
Finally, if you are writing little helper methods to make your views cleaner (a good idea!), you’ll do something totally different. For example, suppose we frequently need to wrap images in links in our views. We could write it out in HTML each time, or we could write a method on a class we make called OurHtmlHelper called LinkWithImage. Here is an example implementation:
You might think we could write code like this:
But MVC’s encoding for @ would block it for sure. You could wrap it in an @Html.Raw() but there is a better way.
Introducing the MvcHtmlString class
The purpose of this class is to inform MVC to get out of the way and NOT encode the contents. So simply changing the return type of LinkWithImage to MvcHtmlString fixes it.
Check out the Helpers section of the demo to see this in action.
There you have it. Three ways to encode or avoid encoding HTML data in ASP.NET MVC applications.
Reblogged this on My Web Anecdotes.
alert(‘Hello world!!! :)’);
LOL, that made me laugh, thanks! Luckily WordPress also does HTML encode.
So, are you basically left to either HTML encode everything you display or, if you want to display raw HTML, to “trust the input”?
What if you both want to be protected against evil input AND output raw HTML?
Yes, to a degree that is what MVC / ASP.NET provide. What I’ve done on recent projects that require untrusted but formatted input is to use Markdown.
There is a cool editor and server-side library called MarkDownDeep which has worked the best for me.
That allows some formatted input but there are no script issues provided you disallow that type of input (easy enough as you’ve already seen).
Reblogged this on Rexhep Kqiku.
Hi Michael- Forgive the intrusion but I work with ESPN in CT/NYC and am actively trying to find them a Sr Application Architect with the latest experience on ASP.NET MVC to join their team for a two year contract. Would you by chance have recommendations on a good place to get the word out for someone with these skills? Thanks so much.
I’m not sure exactly why but this site is loading very slow for me. Is anyone else having this issue or is it a issue on my end? I’ll check
back later and see if the problem still exists.
Seems OK now. :)
LOL, I love it!