ASP.NET MVC XSS protection - asp.net-mvc

According to OWASP XSS page, one needs to use different XSS protection techniques for different contexts. However, in ASP.NET MVC Razor views, we only have the # sign to escape data in the context of HTML element inner content. What about HTML attributes, CSS, javascript contexts and others?
HTML element content
This is safe and will work as expected:
<div>#data</data>
HTML element attribute
This is not safe and can be exploited:
<div style="background: #color"></div>
JavaScript
While this is not safe:
<script>
var value = #value;
</script>
Safe solution is:
<script>
var value = #Json.Encode(value);
</script>
CSS
This is not safe and can be exploited:
<style>
.box { background : #color; }
</style>

A great thing about razor is that it does all the HTML encoding by default. Unless you use #Html.Raw(), it is pretty difficult to make your page vulnerable. You generally have to explicitly make variables render as html.
You also have Html.Encode() if you need it. There is also HttpUtility.JavaScriptStringEncode()
Regarding the updated vulnerable code:
#{var js = "alert(1);";}
<script>var value = #js</script>
I think you would be violating rule 0 with this code. You are inserting arbitrary strings into a script tag, and expecting it not to be executed. I actually get a syntax error (warning) with your example, but it will still run. If you wrapped it in quotes, you would be safe.
#{var js = "\"alert(1);";}
<script>var value = "#js"; alert(value);</script>
output:
"alert(1);
Notice that the quote that I put in the string gets escaped to ", making me unable to break out of the string, so I cannot inject js.
I'd be interested to see if someone has a way of sanitizing this without putting it in quotes, but I am skeptical.
update 2:
Dealing with CSS
The examples you give are not about escaping strings, it is more about inserting untrusted CSS into your page. To do that, you will need something that can parse CSS. For example, it is not that you want the value to be encoded, you just want it not to include the dangerous stuff like url(javascript:), behavior, binding, etc. You'll need a CSS filtering tool for that.
HTML attributes
you are safe if you do this:
<div data-color="#color"></div>
Since razor encodes quotes, you won't be able to terminate the string early. That's as simple as it is to prevent XSS (barring some unknown vulnerability in razor). Your Json.Encode() uses the same idea.
BUT, you are doing somehting risky if you do this:
<div #attribute></div>
Again, it's not that you need an escaped string here, you want something that filters your attributes on any dangerous content. The fact is, that doing things this way is really messy, and I would advise against it. It is bad design because it is screwing up your separation of concerns and making it hard to secure your app from XSS. What you should do instead is add CSS classes if you want to change the style. If you need to set an attribute based on a variable in razor, use something else rather than injecting it into your HTML and hoping to filter it.
ex:
#{
var disabled = isDivDisabled ? "disabled" : "";
}
<div #disabled><div>

Related

In Rails, which is a better defender against XSS attacks, strip_tags or sanitize?

Assuming no tags are allowed in the user input and we want to sanitize user input before storing it in the database, in Rails, we have the options of using sanitize (whitelist an empty set of tags) and strip_tags.
Which is better against XSS attacks? If something else is even better, what is that? And why is it better?
As of Rails 3 and the fatty beatdown the Rails core dev team took when they made Rails unsafe by default, all strings are now tagged as either safe or unsafe with "unsafe" strings being the default. You only need to think about explicitly managing the "safeness" of strings in Rails when you're writing helpers that output HTML into your template.
Escaping vs Sanitizing:
In this context, escaping means replacing some of the string characters with an HTML escape sequence that will remove the special meaning from the text and cause it render as regular text. Sanitizing on the other hand, means validating the HTML content to ensure only good HTML tags and attributes are used. Note that sanitizing is inherently less secure than escaping because of this and should only be used where rendered content must contain HTML markup. An example would be a WYSIWYG HTML editor on a textarea that manages code that is later rendered on a page.
Sanitize encodes all tags and strips all attributes (not specifically allowed which is all in your case) from the html string passed to it. It also strips href and src tags with invalid protocols to prevent any abuse of js attributes. Strip_tags on the other hand will strip all supplied tags including comments which sounds like exactly what you want. As long as you're whitelisting params and adding them to your DB properly escaped such as:
Title.where(author = ?, author_id)
and not blindly inserting user input into your db I would be comfortable with how you're setup.

Prevent AngularJS interpolation in certain DOM hierarchies

I use AngularJS and have some parts of HTML that I don't wish to interpolate because it contains user inputted data. So potentially the data may have {{asdf}} in there that I don't want AngularJS to parse. This is because if the user inputs {{{}, {}} this may break the compilation process and prevent any Angular code from running.
Is there a way around this by specifying to Angular not to compile this part of the DOM tree?
The Non Bindable directive I believe is what your looking for.
So at any element you can do:
<div ng-non-bindable> Some {{1+2}} expressions</div>
That will display:
Some {{1+2}} expressions

MVC HTML helper wrapper for jqPlot

I wish to create an MVC wrapper around jqPlot.
I want to have a helper object to render the required html container element and the required java scripts to draw the chart.
Something that will look like this:
#Html.jqPlot()
.ChartType(eChartTypes.PieChart)
.ChartData(someData)
.RenderChart();
Now I'm only at the initial design phase and I know what the jqPlot object should look like to achieve that, the problem I'm having is with the java script that suppose to be emitted to draw the actual chart using jqPlot.
Suppose I will render the following script in my .RenderChart() method
public string RenderChart()
{
string chartCode = string.format(#"
<script type="text/javascript" src="../src/plugins/jqplot.canvasTextRenderer.min.js"></script>
<script type="text/javascript" src="../src/plugins/jqplot.canvasAxisLabelRenderer.min.js"></script>
$(document).ready(function(){
var plot1 = $.jqplot ('{0}', [{1}]);
});
",this.ChartGuid, this.ChartData);
return chartCode;
}
The above is not actual code but just a general representation of the idea.
So the problem is that i don't want the Helper to emit the JS code into the body of the Html document, furthermore i cannot let it do that becuse some of the required scripts may be at the bottom of the html (as the best practice states).
Any suggestions ?
What would be the best way to emit JS code using an HTML helper if the situation requires it (like this one) ?
I think, listening to an even will be a possible solution, in this case the even of outputting or finishing the rendering of the footer. so maybe your code will give as an option to listen to an event and render at that moment, but this is of course platform dependent. I also worked on a php wrapper you can fork it here: https://github.com/oumsofiane1/jqplotPHPwrapper.git
and just implemented a helper, but of course you can extend that :-)
Hope this helps

I use AntiXSS but I still can hack page

I don't know if I am doing this right. I first time build something to prevent attack on page.
I will start from the bottom:
I have property:
public string Description {get;set;}
User can set it's value through tinyMCE
tinyMCE.init({
mode: "textareas",
theme: "advanced",
encoding : "xml"...
In controller before I save this in database I do:
model.Description = HttpUtility.HtmlDecode(model.Description);
In database I have a value like:
<p>bla bla bla</p>
I added AntiXSS library to my project:
public class AntiXssEncoder : HttpEncoder
{
public AntiXssEncoder() { }
protected override void HtmlEncode(string value, TextWriter output)
{
output.Write(Encoder.HtmlEncode(value)); // on breakpoint code always get in here
}
...
When I display data from database I use:
#Html.Raw(Model.Place.Description)
And it works fine I see only text. No Html tags. Breaklines work fine. I can style text with bold, italic etc.
But If I enter:
<script>alert(open to attack);</script>
I got alert window. I don't understand do I need to do something more to prevent this?
I added AntiXSS library to my project
And where are you using it?
Make sure that you have not only added AntiXSS but you actually used it:
#Html.Raw(Microsoft.Security.Application.Sanitizer.GetSafeHtmlFragment(Model.Place.Description))
But remember that the new version of the AntiXSS library is a bit too restrictive and will strip tags like <strong> and <br> out which might not be desired.
As an alternative to the AntiXSS library you could use HTML Agility Pack to do this job. Rick Strahl blogged about a sample implementation.
First off you are displaying RAW Html- not encoded in any manner.
If you want to display Html you should ideally be doing several things.
Sanitize it with the antixss Sanitizer class using GetSafeHtmlFragment.
Note that this wont protect you completely.
Do this before saving to the DB.
Implement the not yet fully supported headers to prevent other script from running. This is limited to only some of the modern browsers.
Or... Dont allow html or don't allow any HTML outside of known character tags. Ie a whitelist approach so you allow <strong> and nothing outside of other alphanumeric chars is allowed.

How to render single quote in safe way

I saw in a tutorial video that we should use Html.Encode in our views to prevent malicious injections. However, when the text that I'm encoding contains the ' character (for example Dog's) the output in the browser is Dog#39;s. I would have thought every potentially dangerous character would be remaped to some safe code that the browser would render correctly. Is this not the case? How can I get ' to show up in the browser but in an HTML safe way?
The # in Razor automatically encodes for you, meaning that you probably did a double encode.
Example:
#Html.Encode("This is \"safe\"")
is more or less the same as
#{Response.Write(Html.Encode(Html.Encode("This is \"safe\"")));}
Dunno if that last one works in Razor though.
If you are using ASP.NET MVC 2 <%: %> is already encoding the value for you
In Razor (MVC 3) # encodes the values for you so you do not need to wrap the output in Html.Encode
Make sure that you are not double encoding

Resources