Unescapping client data in C# to prevent XSS or other attack - javascript

To prevent web application input from XSS or any other attack, we would like to decode all the input coming from the client (browser).
To bypass the standard validation, bad guys encode the data. Example:
<IMG SRC=javascript:alert('XSS')>
That gets translated to
<IMG SRC=javascript:alert('XSS')>
In C#, we can use HttpUtility.HtmlDecode & HttpUtility.UrlDecode to decode the client input. But, it does not cover all the type of encoding. For example, following encoded values are not getting translated using above methods. However, all the browser decode and execute them properly. One can verify them at https://mothereff.in/html-entities as well.
<img src=x onerror="&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041">
It gets decoded to <img src=x onerror="javascript:alert('XSS')">
There are some more encoded text that does not get decoded using HtmlDecode method. In Java, https://github.com/unbescape/unbescape handles all such varieties.
Do we have a similar library in .Net or how do handle such scenarios?

Generally, you should not allow users to enter code into a text box.
Client side
Judging from the comments on your post, I'd simply add some client-side validation to prevent users from adding any sort of malicious inputs (such as verifying email fields contain emails) and then add the same validation techniques to your server.
Server side
As soon as you read a user's input in a model, you should validate and sanitise it before you do any further processing. Have a generic AntiXSS() class that can remove any malicious characters such as the <> symbols by checking myString.Contains("<") or myString.Contains(">") for example. If it does, remove that character. Validate your types. If you're checking the userEmail field, make sure it conforms to email syntax.
The general idea is that you can pass data to the client, but never trust any of the data that comes back from the client without first sanitising and cleansing everything.

I found the solution. HtmlUtility.HtmlDecode decodes the chars between ampersand '&' and semicolon ';'. However, the browsers do not bother about the suffixed ';'.
In my case, semicolon ';' was missing. I have written simple code to insert a semicolon before calling HtmlDecode method. Now, it's decoding properly as expected.

Related

How can I properly sanitize the comments posted by users in PHP? [duplicate]

I have a html form that accepts user entered text of size about 1000, and is submitted to a php page where it will be stored in mysql database. I use PDO with prepared statements to prevent sql injection. But to sanitize the text entered by user, what are the best efforts needed to do ?
I want to prevent any script injection, xss attacks, etc.
Security is an interesting concept and attracts a lot of people to it. Unfortunately it's a complex subject and even the professionals get it wrong. I've found security holes in Google (CSRF), Facebook (more CSRF), several major online retailers (mainly SQL injection / XSS), as well as thousands of smaller sites both corporate and personal.
These are my recommendations:
1) Use parameterised queries
Parameterised queries force the values passed to the query to be treated as separate data, so that the input values cannot be parsed as SQL code by the DBMS. A lot of people will recommend that you escape your strings using mysql_real_escape_string(), but contrary to popular belief it is not a catch-all solution to SQL injection. Take this query for example:
SELECT * FROM users WHERE userID = $_GET['userid']
If $_GET['userid'] is set to 1 OR 1=1, there are no special characters and it will not be filtered. This results in all rows being returned. Or, even worse, what if it's set to 1 OR is_admin = 1?
Parameterised queries prevent this kind of injection from occuring.
2) Validate your inputs
Parameterised queries are great, but sometimes unexpected values might cause problems with your code. Make sure that you're validating that they're within range and that they won't allow the current user to alter something they shouldn't be able to.
For example, you might have a password change form that sends a POST request to a script that changes their password. If you place their user ID as a hidden variable in the form, they could change it. Sending id=123 instead of id=321 might mean they change someone else's password. Make sure that EVERYTHING is validated correctly, in terms of type, range and access.
3) Use htmlspecialchars to escape displayed user-input
Let's say your user enters their "about me" as something like this:
</div><script>document.alert('hello!');</script><div>
The problem with this is that your output will contain markup that the user entered. Trying to filter this yourself with blacklists is just a bad idea. Use htmlspecialchars to filter out the strings so that HTML tags are converted to HTML entities.
4) Don't use $_REQUEST
Cross-site request forgery (CSRF) attacks work by getting the user to click a link or visit a URL that represents a script that perfoms an action on a site for which they are logged in. The $_REQUEST variable is a combination of $_GET, $_POST and $_COOKIE, which means that you can't tell the difference between a variable that was sent in a POST request (i.e. through an input tag in your form) or a variable that was set in your URL as part of a GET (e.g. page.php?id=1).
Let's say the user wants to send a private message to someone. They might send a POST request to sendmessage.php, with to, subject and message as parameters. Now let's imagine someone sends a GET request instead:
sendmessage.php?to=someone&subject=SPAM&message=VIAGRA!
If you're using $_POST, you won't see any of those parameters, as they are set in $_GET instead. Your code won't see the $_POST['to'] or any of the other variables, so it won't send the message. However, if you're using $_REQUEST, the $_GET and $_POST get stuck together, so an attacker can set those parameters as part of the URL. When the user visits that URL, they inadvertantly send the message. The really worrysome part is that the user doesn't have to do anything. If the attacker creates a malicious page, it could contain an iframe that points to the URL. Example:
<iframe src="http://yoursite.com/sendmessage.php?to=someone&subject=SPAM&message=VIAGRA!">
</iframe>
This results in the user sending messages to people without ever realising they did anything. For this reason, you should avoid $_REQUEST and use $_POST and $_GET instead.
5) Treat everything you're given as suspicious (or even malicious)
You have no idea what the user is sending you. It could be legitimate. It could be an attack. Never trust anything a user has sent you. Convert to correct types, validate the inputs, use whitelists to filter where necessary (avoid blacklists). This includes anything sent via $_GET, $_POST, $_COOKIE and $_FILES.
If you follow these guidelines, you're at a reasonable standing in terms of security.
You need to distinguish between two types of attacks: SQL injection and XSS. SQL injection can be avoided by using prepared statements or the quote functions of your DB library. You use the quoting function this before inserting into the database.
XSS can be avoided by quoting all special chars with htmlspecialchars. It is considered good style to escape the output after you read it from the database and store the original input in the database. This way, when you use the input in other contexts where HTML escaping is not needed (text email, JSON encoded string) you still have the original input form the user.
Also see this answer to a similar question.
There are two simple things you need to do to be safe:
Use prepared statements or escape the data correctly.
When outputting to HTML, always escape using htmlspecialchars( ).

Is my method completely secure for xss

I have a chatting website and I wanna know if it is XSS secure. Let me explain what is my method.
I use this JQuery code to add new messages to screen that are incoming from ajax request:
$("#message").prepend(req.msg);
I know this is vulnerable but messages on DB are encoded. So when I send that payload message:
<text>TEST</test>
It stored on database as encoded:
<text>TEST</test>
I know a scenario that is bypassing .htmlentities() function in this answer. Shortly:
<input value=<%= HtmlEncode(somevar) %> id=textbox>
If we send a onclick=alert(document.cookie) input to this html code, it will become:
<input value=a onclick=alert(document.cookie) id=textbox>
So in this scenario, encoding < > ; & characters can't save us. But I didn't write my code like this so I think I'm secure from that vulnerabilty. My server responds a JSON like this:
..."msg" : "<tr><td><b>user:<\b> <text>TEST</test><\td><\tr>",...
And I directly .prepend() the "msg" data into page. I think this is fully secure. Hacker must use < > ; & characters to XSS. I am also encoding \ as \\. But maybe I am missing something. Is that fully secure ?
No. It's not. The way the data is transported makes it possible for someone to input unescaped HTML tags. Say that someone posted this payload:
\u003cscript\u003ealert(1)\u003c/script\u003e
This would be entered into the database as-is, because there is nothing for htmlencode to escape. However, when it's put in the JSON, and said JSON is parsed, it becomes this:
<script>alert(1)</script>
And executes the malicious code. A better solution would be to encode the raw data for JSON, and then use an HTML escapement mechanism client-side.
With the server-side escaping \ in the JSON, I think that is fully secure.

Input special character in search string when handled at server side

I'm testing a project I'm working on. Here I've put a filter on server side(Java) to redirect the page to Error page whenever I encounter any HTML tag like regex(URL Encoded is also checked) in query string. As per my skill set, it's working fine. But I'm very much sure it's not the end. There must be a way to still enter the vector to execute XSS script.
Examples : <hello> redirects to error page
%3Chello%3E converts to <hello> and redirected to error page
%253Chello%253E converts to %3Chello%3E & page works fine as no HTML tag is found.
The approach you're trying is black-list approach which is to search for bad characters (IE <, >) and redirect to an error page and\or encode it. This is the wrong approach.
You should use a white list of permitted characters and redirect to an error page if the input contains any non-permitted characters. One way to enforce this approach is regular expressions: ^[a-zA-Z0-9]*$ or ^[\s\w]*$. Adding both client validation and server validation would keep you safe and error-free (unless a hacker tries to bypass the client validation in which in this case the server validation would stop him).
If you try to guess the attacker's method you are destined to fail.
The right way to encode user originated input to prevent XSS is HTML Encoding, not URL encoding (not %3Chello%3E, but >hello<).
If you encode the user input you don't have to redirect the user to an error page as the examples you gave and the ones that I gave are harmless
Having said that, here is an example of XSS without < and >:
Let's say a page receives a picture file name and displays it, and does not encode the quote character:
https://contoso.com/displaypic?source=111.jpg
<img src="111.jpg"></img>
If you access this URL, you have yourself XSS:
https://contoso.com/displaypic?source=a"+onerror="alert('XSS')
<img src="a" onerror="alert('XSS')"></img>

A potentially dangerous Request.QueryString -- How to prevent without turning off safety features

I am getting this message when I perform a post with some data encoded in the query string. I have browsed the web on this and all the solutions are about turning off the validation -- which seems backward to me. What I want to do is modify the query string so that it doesn't trigger the validation in the first place.
The query string is urlEncoded with this javascript:
var qs = 'i=' + id+ '&c=' + encodeURIComponent(c) + '&' + 'p=' + encodeURIComponent(p);
'Id' is just an integer, so the c and p parameters are the only ones likely to cause this, and they are both URIencoded.
What causes this error, and what, beyond uri encoding can I do to prevent the complaint?
I don't like turning off safety features. It is smart to wear a safety belt when you are driving.
This is a safety belt only for people that haven't passed their driving test. If output is correctly encoded, the "potentially dangerous" query string value is no longer dangerous.
For example, if the character " is output to HTML this should be encoded as ", or if the character ' is output to JavaScript then it should be encoded as \x27.
ASP.NET Request Validation only protects your code if you are not correctly encoding for output, and furthermore it only protects values that have been input via a website with Request Validation enabled. Anything input from any other sources (e.g. a shared database, another application or an external API) will not be validated by request validation. This is why I would code your application to handle correct output encoding instead. If stackoverflow.com blocked potentially dangerous input then it would not be possible for people to write code like this in their posts: <script>alert('example');</script>, but with proper output encoding, as you can see this is safe.
Check out my post on ASP.NET Security (A3-Cross-Site Scripting (XSS) section).
Also see the OWASP XSS Prevention Cheat Sheet.
You're right, most "fixes" for this tell you to turn off validation so it was kind of difficult to find something other than that. I think you're going to have to turn it off just for that request and then manually validate it. According to microsoft, you can disable it for a request like this:
Request.Unvalidated("userInput"); // Validation bypassed
Request.Unvalidated().Form["userInput"]; // Validation bypassed
If you disable request validation, you must manually check the unvalidated user input for potentially dangerous input
See this article: http://msdn.microsoft.com/en-us/library/hh882339(v=vs.110).aspx
Good Luck!
The ASP.NET team doesn't want you rely on 'RequestValidation' so it is ok to turn it off (it's a crutch that gives a false sense of security because it isn't always up to speed).
For info on why this ok and what you should do instead, watch this video starting at 11:10. I would actually recommend watching the whole video.

JavaScript and JQuery - Encoding HTML

I have a web page that has a textarea defined on it like so:
<textarea id="myTextArea" rows="6" cols="75"></textarea>
There is a chance that a user may enter single and double quotes in this field. For instance, I have been testing with the following string:
Just testin' using single and double "quotes". I'm hoping the end of this task is comin'.
Additionally, the user may enter HTML code, which I would prefer to prevent. Regardless, I am passing the contents of this textarea onto web service. I must encode the contents of the textarea in JavaScript before I can send it on. Currently, I'm trying the following:
var contents $('<div/>').text($("#myTextArea").val()).html();
alert(contents);
I was expecting contents to display
Just testin' using single and double "quotes". I'm hoping the end of this task is comin'.
Instead, the original string is printed out. Beyond just double-and-single quotes, there are a variety of entities to consider. Because of this, I was assuming there would be a way to encode HTML before passing it on. Can someone please tell me how to do this?
Thank you,
If you're sending to a web service, you'll presumably be URL-encoding these (as part of a POST, for instance, either via form submission of Ajax). That will handle any necessary escaping at your end. The service at the other end is responsible for interpreting the input string correctly. If the service doesn't accept HTML tags, it's the service's job to do the necessary entity encoding (or whatever other kind of encoding it wants).
If the service doesn't take responsibility for this, it's open to errors in the client and attacks by people with nefarious intent. So it's really the other end's problem.
By using:
var contents = $("<div/>").text($("#myTextArea").val()).text();
alert(contents);
You display the textual contents instead of the contents in html.

Categories

Resources