Sanitize User Input in C# - Cleanest Way? - c#

There's a gotcha when inserting img's dynamically via scripts.
Take the following code to insert a image for a place:
newPlace.find('.PlaceThumb').append('<img src="' + place.ThumbnailUrl + '" alt="' + place.Name + '" width="50px" style = "padding:2px;"/>');
Someone could name their place: " onload="alert('hi')" and the tag would get rendered as:
<img src="/item.aspx?id=123" alt="" onload="alert('hi')" width="50px" style = "padding:2px;"/>
When the image is loaded, the script will execute.
While only and tags support the onload attribute, this is a good lesson to never trust user input.
What is the "Correct" (nice, elegant, clean, general) way of doing this:
newPlace.find('.PlaceThumb').append('<img src="' + place.ThumbnailUrl + '" alt="' + place.Name.replace('"', '"') + '" width="50px" style = "padding:2px;"/>');
I was thinking maybe with templates you could define an operator on strings that would UUencode them - similar to how a string prefixed with # in C# has special meaning vis a vis backslashes. Is there a way to add this functionality to the standard .net string class?

Maybe you can use new Uri( yourUrlString ). I believe using that (alog with the methods IsWellFormedUriString and IsWellFormedOriginalString) will help you validate the input.

AntiXSS library is one possible solution. Be very carefull with encoding as your code seem to have large number of layers between data and rendered HTML (ASP.Net -> renders HTML template as part of rendered JavaScript -> Browser loads JavaScript -> something executes the scriot that in turn uses JQuery to create HTML based on the temeplate).
Note: Consider separating CSS (width and style attributes) from HTML layout as good HTML practice.

I can't tell if you're using jQuery or not. If you are, then you can do something like this:
newPlace.find('.PlaceThumb').append('<img>');
$('.PlaceThumb img').attr('src', place.ThumbnailUrl).attr('alt', place.Name);
That may not be valid, it's just off the top of my head, but should give you something to look into.

Related

Is C# files, what kind of encoding should be used within a <script> tag in embedded HTML?

I have a C# file with embedded HTML (via new HtmlString(...)) where if I am interpolate strings I use StringObject.EncodeAsHtml(). However I am not sure if I should use the same encoding method when using strings within <script>
new HtmlString(
$"<link rel='manifest' href='{linkToManifest.EncodeAsHtml()}' />" +
$"<script charset='utf-8'>" +
$"if ('serviceWorker' in navigator) {{" +
$"navigator.serviceWorker.register('{linkToServiceWorker.EncodeAsHtml()}\" }})" +
$"}}" +
$"</script>"
);
The first use of .EncodeAsHtml() makes sense, but I am not sure if the second use of it makes as much sense since it is within JavaScript.
Any recommendations?
Don't think you really need to use .EncodeAsHtml() at all in this case.
Also, consider adding type="text/javascript" to the script tag.

Make selenium code with a lot of XPath-s more readable

I've noticed that when I'm using selenium web driver to interact with elements on a web page my code becomes not readable because I use a lot of XPath-s to find this elements. For example:
driver.FindElement(By.XPath("//div[#class='login']//a[#href='#']"), Globals.TIMEOUT).Click();
var loginField = driver.FindElement(By.XPath("//div[#id='login_box']//input[#name='login_name']"));
jdriver.ExecuteScript("arguments[0].setAttribute('value', '" + login + "')", loginField);
var passwordField = driver.FindElement(By.XPath("//div[#id='login_box']//input[#name='login_password']"));
jdriver.ExecuteScript("arguments[0].setAttribute('value', '" + password + "')", passwordField);
driver.FindElement(By.XPath("//div[#id='login_box']//input[#type='submit']")).Click();
driver.FindElement(By.XPath("//div[#class='nameuser']"), Globals.TIMEOUT);
I thought that I can place XPath values into constant strings but it's very helpful to see the actual XPath of the element while reading the code. But on the other hand, when the XPath of some object changes I have to change it at all places it is used.
So what is the best solution for this problem?
Use Selenium Page Object Model using Page factory. Helps to maintain clean code and enhances readability of code.
Create a page object file.
For example, if you are using an xPath like "//div[#id='login_box']//input[#type='submit']" a lot, in the page object file put:
var loginSubmit = "//div[#id='login_box']//input[#type='submit']"
Then in your main file import the page object file:
using myPageObjectFile
driver.FindElement(By.XPath(myPageObjectFile.loginSubmit));
My C# is not great so it might not be like this exactly. But something to that effect should work.
This way when the xPath changes, you only need to adjust it in the page object file.

Verbatim string literal not interpreting html

In my controller action, I am sending a message to a view -
model.Result = ex.Message;
model.Result = model.Result + #" If you would like to create one, please click here ";
So, I want the message to show up like so -
The member doesn't exist. If you would like to create one, please click here.
But what actually shows up is
The member doesn't exist. If you would like to create one, please <a href> click here </a>.
So, I have 2 questions -
1) Why is the verbatim string literal not evaluating the html.
2) Is there a better way of doing this? I don't like having html in my controllers, but I also don't want to over architect things for a line of html.
Razor automatically HTML-encodes strings for security (to prevent script injection). You need to use Html.Raw if you want the actual HTML.
#Html.Raw(Model.ResultMessage)

using a string format with parameters to set onclick

Why doesn't this work?
<input type="button" id="btnAccept" value="Accept" onclick='<%# String.Format("accept('{0}','{1}','{2}','{3}-{4}');", Container.DataItem("PositionID"), Container.DataItem("ApplicantID"), Container.DataItem("FullName"), Container.DataItem("DepartmentName"), Container.DataItem("PositionTitle"))%>' />
The onclick doesn't do anything.
Your best bet is to look at the generated HTML. I think it's a really good habit to check the generated HTML in text format and how it renders on-screen, all the time. Besides errors such as this (which can easily be spotted in the generated HTML), it will help you catch other possible invalid uses of HTML which may render as intended in one browser while rendering terribly in another. HTML rendering engines employ many tricks to try and make invalid HTML look okay.
Anyway, all things aside (such as, assuming accept(...) exists, and all other calls in the tag are correct) I think the issue you are having is as follows:
onclick='<%# String.Format("accept('{0}','{1}','{2}','{3}-{4}');", ... )%>'
This line is probably going to evaluate to look something like this:
onclick='accept('{0}','{1}','{2}','{3}-{4}');'
With all single quotes, all the onclick attribute will see is onclick='accept(' which is not a valid javascript method call. You're going to want to use the "" strings, which you can embed in the format string by escaping them.
String.Format("accept(\"{0}\",\"{1}\",\"{2}\",\"{3}-{4}\");", ... )
Then, you should be able to get the correct combination of ' and " within the attribute:
onclick='accept("{0}","{1}","{2}","{3}-{4}");'

how do you add a NEW LINE character in the string portion of an ActionLink?

I'm building a Ajax.ActionLink in C# which starts:
<%= Ajax.ActionLink("f lastname", ...more stuff
and I'd like there to be a new line character between the words "f" and "lastname". How can I accomplish this? I thought the special character was \n but that doesn't work, and <br> doesn't work either.
You might have to revert to doing something like:
f<br />last
And then wire in the Ajax bits manually.
Try this:
<%= Ajax.ActionLink("f<br />lastname", ...more stuff
You can't use <br /> because the ActionLink method (and indeed I believe all the html and ajax extension methods) encode the string. Thus, the output would be something like
f<br />lastname
What you could try instead would be a formatting:
<%= string.Format(Ajax.ActionLink("f{0}lastname", ...more stuff), "<br />") %>
Did you try the \r\n combination?
How about:
<%= Server.UrlDecode(Ajax.ActionLink(Server.UrlEncode("f<br/>lastname"), ...more stuff
This works for me -
<%= HttpUtility.HtmlDecode(Html.ActionLink("AOT <br/> Claim #", "actionName" ))%>
The \n used to work for me. But now it seems to be depricated. Alternitavely, you may use the NewLine method, for example:
string jay = "This is a" + Environment.NewLine + "multiline" + Environment.NewLine + "statement";
I think Andrew Hare's answer is correct. If you have slightly more complicated requirement, you do have the option to create your own AjaxHelper or HtmlHelper. This will involve creating custom extension methods that work on AjaxHelper and HtmlHelpers, by doing something like:
public static class CustomHtmlHelperExtensions
{
public static MvcHtmlString FormattedActionLink(this HtmlHelper html, ...)
{
var tagBuilder = new TagBuilder("a");
// TODO : Implementation here
// this syntax might not be exact but you get the jist of it!
return MvcHtmlString.Create(tagBuilder.ToString());
}
}
You can use dotPeek or your favorite .NET reflection tool to examine the standard extensions that come with ASP.NET MVC (e.g., ActionLink) etc to find how Microsoft has implemented most of those extension methods. They have some pretty good patterns for writing those. In the past, I have taken this approach to simplify outputting HTML in a readable manner, such as, for Google Maps or Bing Maps integration, for creating options like ActionImage e.g., #Html.ActionImage(...) or to integrate outputting Textile-formatting HTML by enabling syntax such as #Html.Textile("textile formatted string").
If you define this in a separate assembly (like I do), then remember to include this into your project references and then add it to the project's Web.config as well.
Obviously, this approach is overkill for your specific purposes, and for this reason, my vote is for Andrew Hare's approach for your specific case.
It's been several years since the question was asked, but I had trouble with it. I found the answer to be (in MVC):
Text in your ActionLink: ...ActionLink("TextLine1" + Environment.Newline + "TextLine2", ...
In the ActionLink, have a class that points to a css with this line:
whitespace: pre;
That's it. I've seen answers where they put the entire Actionline in < pre > < /pre > tags, but that caused more problems than it solved.

Categories