Transfer possibly unsafe user input from hidden input field to DOM - javascript

The following is a simplified example of a page a user has created at a site (they created it by filling out a form and then they get a URL for the page; the below is the HTML for the page they created).
In the example, I'm taking the value of a hidden input field and then putting it into the DOM as is. That results in an alert, simulating an XSS attack.
What's the best way to prevent things like this? The value of #sourceinput was previously input by the same or a different user who's viewing the page below, and the user's input wasn't filtered to remove tags. (The actual case involves the jquery.tooltip.js plugin and it's bodyHandler callback; on mouseover a bodyHandler callback would get the hidden input and display it to the user.)
One way to deal with this would be to strip tags on input; I control what goes in the hidden textfield so that would seem to solve it.
Another way would be to strip tags in Javascript, but some of these don't seem to be 100% effective:
Strip HTML from Text JavaScript
Is there some sort of best practice that I'm missing, or are those two the best ways?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<head>
<title></title>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>google.load("jquery", "1.7.1");</script>
<script>
$(document).ready(function() {
var badHTML = $('#sourceinput').val();
$('#destinationdiv').html( badHTML );
//$('#destinationdiv').text( badHTML );
});
</script>
</head>
<body>
<input type="hidden" id="sourceinput" value="<script>alert('hi');</script>" />
<div id="destinationdiv" style="width:10px;height:10px;background-color:red;"></div>
</body>
</html>
UPDATE: The solution I'm going with for now has three parts:
When the page the user has created is saved, I run PHP's strip_tags() on their input. These are just short text strings like titles and blurbs, so few users will expect they can enter HTML. That might not be appropriate for other situations.
When the page the user created is displayed, instead of putting what the user had entered in an input value attribute, I put their input inside a div.
I take the value out of that div using .text() (not .html() ). I then run that through the underscore function (see below).
Testing this out - including simulating skipping the first step - seems to work. At least I'm hoping there isn't something I missed.

Here's the escape function used by Underscore.js, if you don't want to use the entire Underscore library of functions:
var escape = function(string) {
return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
};
Used like
var safe_html = escape("<b>Potentially unsafe text</b>"); // "<b>hello</b>"
$("#destination").html(safe_html);
It's written well and is known to work, so I'd advise against rolling your own.

I would say what you commented out (using text() from jquery is the better option). That will make sure the text stays text which is what you want. Filtering or stripping may have unwanted side effects like removing a mathematical expression in the input (" x is < 5").

Do Nothing.
You are trying to protect the user from himself. There is no way the user A can harm user B. And for all you care, user A might as well type javascript:alert('hi') on the address bar and xss himself. And no matter what javascript escape function you create, a savvy user can always bypass it. All in all, its a pointless pursuit.
Now, if you start saving what the user entered on the server side, then you should definitely filter things. Don't build anything on your own. Depending on your server side language, there are several options. OWASP's AntiSammy is one such solution.
If you do choose to save user entered html on the server side, make sure to run it by antisammy or a similar library before saving it to the database. On the way out, you should simply dump the HTML without escaping, because you know whatever is in the database is sanitized.

Related

Is there any way to edit a URL to embed a form entry?

I know it is possible to embed form values into the URL as parameters if the form has an ID assigned to it. But what if it does not have an ID?
For example the "Search" field in this page:
http://au.autodesk.com/speaker-resource-center/call-for-proposals/voting
<input type="text" placeholder="Search " class="form-control ng-valid ng-dirty search-box" ng-model="search.$" ng-change="updateButtons()">
I know it is possible to embed form values into the URL as parameters if the form has an ID assigned to it.
That is not true.
Server-side (and occasionally client-side) code on a page may read the query string as a means to set default values for form controls (typically so that a form can be corrected and resubmitted if there were errors in the previous attempt).
In these cases, the name attributes will usually map onto the query string (because the form will generate the query string from the name attributes). Often an input will be given an id that is the same as its name.
It is entirely under the control of the site's authors.
There is no way to set values of inputs on another site without the other side providing a mechanism to allow you to do that.
There's a few different ways to do that. Looking at that HTML, it's the first text-type input inside the div, so the first method that comes to mind is this:
You could pull out the div (using the class "search-area") and then target the first text input box within that div. I don't know whether you're using jQuery or native JS or exactly what language/library/framework you're using.
JQuery would be something like:
var inputElement = $(".search-area")[0].first()
This SO answer may help:
jQuery: how to find first visible input/select/textarea excluding buttons?
Edited to add: Answer is targetting the input element. As the answer from someone else mentions.. You can't actually do what you're wanting to do with the URL.
Edited again. Misread the question. I'll leave this here in case someone else needs to know how to target an input field that doesn't have an ID. Alternatively, I have no problems if someone wants to delete this answer.

Hiding Password field content from users

I'd like to know if its possible for me to do something from the following :
1) Replace the source code visible in view source , with an image , or nothing at all.
2) Hide the value attribute of <inpt type="password" ....> tag , so that the password entered by the user is not visible to anyone .
Thanks in advance.
You can minify your HTML to make it slightly unreadable, but it's trivial to unminify it. You can't do anything further to "remove" or "hide" it.
You mean to hide the value attribute after the user types something in, or to hide the value sent from the server? If the former, you could use JavaScript to extract the value as it's typed into some variable and replace the value with gibberish. If the latter, then the obvious answer is to not send that value.
View source is a representation of static HTML, so if you create any element dynamically, it will not be displayed in view source.
Note: These fields will still be accessible using dev tools.
Following is a sample code:
JSFiddle
function submit() {
var uName = document.getElementById("txtUserName").value;
var uPass = document.getElementById("txtUserPass").value;
console.log(uName, uPass);
}
function addPasswordField() {
var passInput = "<input type='password' id='txtUserPass' />";
document.getElementById("content").innerHTML += passInput;
}
(function() {
addPasswordField();
})()
<div id="content">
<input type="text" id="txtUserName">
</div>
<button onclick="submit()">submit</button>
There is no way to hide source code in a browser since that is how these things are built. The web is an open platform and developers working with the web need to have the view source functionality while working on their project(s). May I ask why you feel the need to hide the source code and the password?
To answer the first question: No. This is how browsers are designed and there are lots of other ways to request the page to see the source. For example, you could use Fiddler to see the traffic passing between the server and the browser.
As for the second question...why are you trying to hide the password?
Using the password input type will prevent anyone from seeing the password on the screen. so I assume this is to stop the data being viewed in transit?
If you want to secure your connection between the client and the server, you should consider using a secure (https) connection. Thanks to LetsEncrypt this is free, so it is no longer a costly option.

Writing a javascript function that just prints details of a form to another html page when a button is clicked.

So I'm trying to take information from a form, one is a number that can be changed by the user and the other is a constant floating point number. When the user inputs a number, they then press submit, which is when I want the output to be printed to my confirmation webpage. I've not seen much online on this so if anyone has some advice or just a pointer to some online material for me that would be greatly appreciated. Also should mention that I'm not allowed to use any javascript libraries to do this just in case. Thanks
Ach, I'm feeling sympathetic. I assume you're doing this on the same page (if not, you're probably in the wrong place & want PHP I guess).
If it is, here's something extremely crude to get you started, with some comments.
Note that there is a truly vast amount of information on JS and the DOM, given it's essentially the primary purpose of the language. Which suggests you didn't really look very hard, but I get it's difficult to know what you're looking for at first. MDN is generally excellent for specifics - look up the methods used here, they'll all have better examples than mine.
// Listen for a 'click' on the element with an ID of 'submit',
// and run the 'printSomeCrap' function:
document.querySelector('#submit').addEventListener('click', printSomeCrap, false)
function printSomeCrap() {
// Grab the constant from the element with the id 'constant'
var constant = document.querySelector('#constant').textContent
// Grab whatever was typed in from the element with the id 'input'
var input = document.querySelector('#input').value
// Then find the element with the ID of 'output', and print out
// what was just grabbed as a string:
document.querySelector('#output').innerHTML = `Constant: ${constant}, Input: ${input}`
}
<input id="input" type="text" placeholder="Just type something">
<p id="constant">0.123456789</p>
<button id="submit">Then press this button</button>
<div id="output"></div>

Disable html/javascripts commands in text fields

How do I prevent input in texts fields from containing HTML and JavaScript code?
Example: I have an input text field. If the user enters javascript instructions, then they get executed.
How can I modify
<script>alert('aces')</script>
so that it will show up as normal text in my field and not as a alert when i try to list it?
Have you looked into libraries like underscore.js (used by Backbone.js)?
It comes with escape functions that prevents user entered javascript to run.
http://underscorejs.org/#escape and http://underscorejs.org/#unescape
so you would write:
alert(_.escape(USERINPUT));
this becomes even more important when you add user input to your DOM, for security reasons you need to escape inputs (or allow only a selection of harmless tags like < strong >).

jquery, replace html on submit

I have a form which is using a select list to jump around my site. This is currently using onclick window.location so user selects the page and presses go and it goes to that page.
I now need to add a small text box for the user to type in a code (say 123456) and then when they click go, it should go to the url selected, but with the [CODE] being the number entered in the box. I discovered jquery replaceAll so it gave me the idea to have this in the select html:
http ://jumptothispage.com/parts/p[CODE]/edit
http ://jumptothispage.com/jobs/j[CODE]/edit
When you press go, it would replace all [CODE] in that html with the code entered and then jump to that page selected, e.g.
http ://jumptothispage.com/parts/p123456/edit
http ://jumptothispage.com/jobs/j123456/edit
I am already using jquery on my site so makes sense to try and utilize that again. I'd appreciate a pointer and or other suggestions instead.
Thanks,
Paul.
A workaround: Store the code in a cookie, so at least it's not visible to every person who looks at the URL bar. Then in every onclick, fit it into the URL to send the user to the "right" page.
Or, have your select option's value literally read CODE, which your onclick interprets to mean "The user hasn't set the code yet." When the user types in the code, store it in a variable (in the example below, realcode), and you can then do this:
$('select#navigation option').each(function(idx, el) {
$(el).attr('value', $(el).attr('value').replace(/CODE/, realcode));
});

Categories