How to prevent script injection that was pasted to input - javascript

Recently I've met the XSS problem. I've searched and read a lot of related questions and articles. I've noticed that all answers are focused on how to prevent untrusted data to be passed to server. And in front-end, escape special codes seems the only way to prevent scripts execute.
But what if a user just input a piece of code(such as <script>alert("hi");</script>) to an input, when will this code executes? And is there a way to prevent it?
I've listened the keydown keyup event, but this can only prevent normal input, it has no effort when user copy and paste directly into input, it'll show my warning message when user input a piece of script, but the script still executed!
$("input").on("keyup", function (e) {
var value = $(this).val() || "";
var regex = /<(\/?\w+[^\n>]*\/?)>/ig;
if(regex.test(value)){
layer.msg("Invalid characters!");
$(this).val(value.replace(regex, "<$1>"));
e.preventDefault();
return false;
}
});
I don't understand why the script in an input's value is executed by browser, and when it is executed ? Is there any articles that can explain this mechanism or is related ? Did I have something unnoticed ?
If there any articles that you think will help, please let me know.
Thanks.
Thanks for all the answers and comments. Maybe I didn't describe it clear. I've test that when I copied <script>alert("hi");</script> and paste it into an input, the browser did prompt an alert window and showed the "hi".
I've also just use $("input").val('<script>alert("hi");</script>'), it won't prompt alert window, but if I trigger the input's focus and blur event, it will prompt the alert window too.
So, why the codes are executed ?

Say my user name was <script>alert('You got pranked!')</script> and your app isn't protected against XSS.
When registering, the app will save my user name as is, and there's nothing wrong with that.
But, when I go to my profile page (or any page that will display my name), the HTML rendered by the server will look like that
<h1>Profile page</h1>
<p>User name: <script>alert('You got pranked!')</script></p>
The client browser will see a <script> tag and will execute what is inside.
The easiest solution to counter that is to escape any HTML-special characters. No matter what tech stack you have, there are lots of tools that will do that for you.
But the way all these tools work, is that when displaying my user name, it will be shown as <script>alert('You got pranked!')</script>, thus preventing the browser from seeing a <script> tag when displaying my user name.

The value or contents of form fields are not executed by browsers, nor are they parsed as HTML unless you treat them as HTML.
You can paste anything you like into an input field, and submit it to a server. Pasting <script>alert("hi");</script> into an input is fine, and that text will be used as the value of the input field when the form data is submitted to the server.
The problem of XSS comes when a site uses previously submitted data and squirts it into the HTML of a response (as described in RichouHunter's answer)
An example of treating the input field as HTML without going to the server:
// Assuming jQuery:
$('div').html($('input').val());

Related

How do I create a hyperlink inside an input text field in html?

I have an input text field in which the user can enter the name of a website. Is it possible for it to be hyperlinked so that once the field is saved, if the user clicks on it, it redirects to the website?
I use Django for the backend and Javascript and html for the front end.
An input field's value is stored as plain text, therefore you cannot include HTML (i.e. a link) and expect the HTML to be parsed and functioning.
You could simulate this behavior with JavaScript, however I would recommend against it. (You would add a click listener, your function would pull the value of the field, see if it is a valid URL, and then open up the location.)
I'm not going to write the code for this because it would be a terrible user experience. The standard behavior for an input field is that you click on it to edit the text. This is an assumption your users have, and they would therefore (a) not think to click on it because they don't expect it to be a link, and (b) click in it if they wanted to edit the text, only to be redirected and unable to edit the text.
Alternatively, you could add a small button next to the input, i.e. 'Open' or 'Test' or an external link icon.
Simply, if you are printing the URL for the user on their profile page, sure you can just print it as follows:
<a href='$url'>$url</a>
That's PHP but of course you can do this in any language. I'm not sure if this answers your question since you ask if it can be printed "inside" the field which isn't possible/doesn't make sense.
HOWEVER, think about security. Remember the user can enter any malicious URL into this field, so you need to be aware of who you are potentially linking this to on your website/application.
Useful resources:
URL HTML field:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/url
Validate URL format with Django (does not check if malicious or not though):
How can I check if a URL exists with Django’s validators?

Input value isn't getting carried forward when form is submitted

I am feeling really guilty for asking this question. However, I tried everything and nothing worked...forcing me to ask here. If suggested, I will delete this question.
On chrome console of website: https://search.cisco.com/search?tab=Cisco&locale=enUS,
I performed following:
document.getElementById("searchT").value = "Hello World!" //works fine
document.getElementById("searchform").submit() ;
Line 1 works fine and fills the input with "Hello World!". Line 2 submits the form and page reloads but somehow the "Hello World!" isnt getting carried forward when the page loads. It would be great if someone could explain why is it happening?
You are populating value to the input field and then submitting the form.
Form action is equal to dot so its realoding the page.
The input field you set value does not have any name atrtibute so its missing in the query field in the url address and it looks like nothing were submitted.
When you type search term from keyboard other scripts perform (maybe ajax) requests and present you the results without page reload.
EDITED
When you hit enter on the keyboard scripts are reloading the page with ?query=searc-term parameter. And query is not the name of the text input you are populating the value
Step one put Hello World! in the search field. Step two submitted the search form. It should have brought back the search results for Hello World!, but it didn't.
What happened?
I took a look at the code for the form and this is what I saw:
It has normal html form properties like id, class and action.
It also has an extra property on it: ng-submit.
A quick google search for ng-submit led me to discover this:
ngSubmit
directive in module ng
Enables binding angular expressions to onsubmit events.
Additionally it prevents the default action (which for form means sending the request to the server and reloading the current page), but only if the form does not contain action, data-action, or x-action attributes.
source: https://docs.angularjs.org/api/ng/directive/ngSubmit
From this, we can determine two things:
Cisco using Angular's ng-submit to collect the query and return the search results.
The search feature was not designed to work without Angular's ng-submit.
You did everything correctly; unfortunately the search feature isn't designed to work by normally submitting a form; it needs to be Angular's ng-submit.

IE 8 iFrame causes JavaScript errors on first load only

I use an iframe on my page, which consists of a form with input elements.
Every input element has an onblur() event, which validates the input.
When I open the page in IE 8 with a freshly cleared cache it produces a javascript error like this.
document.getElementById(...)' is Null or not an Object
However, when I inspect the form it is loaded completely and the I'm trying to access is rendered.
Furthermore when i reload the whole page I don't get any errors anymore.
Also when I load the content of the iframe on its own I also don't get errors.
Firefox and Chrome dont throw errors at all.
In short, the Javascript errors I get only occur in IE and only when I use an iframe to display the form (which is mandatory) and only when the page is loaded for the first time.
Any ideas on how I can fix this?
I hope its not too confusing to read.
Edit:
document.getElementById("vHint_"+fieldName).innerHTML=data;
FieldName is the id of the input field. Data is the return value of the validation.
In this case data is an image tag.
After every input field is a span Tag with the id "vHint_"+fieldName.
The event is attached like this:
<input id="Jahr" class="input" type="text" onblur="validDate(this,'Jahr','_beginn')" maxlength="4" style="width:32px" value="" name="Jahr">
First of all thank you for your effort.
The example user13500 provided worked like a charm.
And it made me dig deeper.
And i found the solution.
All input fields are created with a self made ASP Framework, which puts them all in the Session.
The onblur() event of the input field within the iframe triggers an AJAX Request to an ASP file passing the name of the input field as a request parameter. The ASP file now tries to find the field in the Session and retrieve its value to validate the input.
After that the result is posted back to the javascript file, which then uses document.getElementById("vHint_"+fieldName).innerHTML=data; to post the result back in the page.
This normally works without erros.
But, since the application is run in an iframe and the domains of the surrounding page and the application in the iframe are different, IE rejects the Session of the iframe. Thus the result of the ASP validation is empty, because it couldn't find the field in the Session.
Having figured that out the only thing that has to be done is to add this line of code in the application:
Response.AddHeader "P3P", "CP=""CAO PSA OUR"""
This way IE doesn't reject the Session of the application anymore.
Maybe this can be useful for others too.

Read only textfield editable via inserted javascript?

I have a form with a read only field for display/submit to the next page purposes.
However, I noticed using developer tools in Chrome, I was able to add an id to an element, use the javascript console to select that element, and change its value. I submitted the form and what do you know - the next page acted on it as if it was the original value.
Now, there shouldn't be any problem with the people using the site I'm building, but it seems like a huge security flaw to me. Isn't the point of read-only to remain constant? If a savvy user to change it around, doesn't that pose a big problem? In fact, I didn't even think you could add and change attributes in chrome.
Please post your thoughts below, and let me know if there's a solution ("disabled" textfield, but setting the disabled property doesn't send the data to the next page).
NEVER trust input from a web form.
The user could, just as easily, remove the readonly attribute and edit the value. The readonly attribute is only something to help the user when filling out the form, so they don't edit a value expecting it to change, when your server actually won't let it be changed. So, always remember to code the behavior on your server first, and have the HTML form be a helpful guide for users to make the form easier to fill out (without having to submit the form several times to get relevant error messages).
To overcome this, if something is readonly and you do not want it edited, you could store the value in your database. Also, values provided by users should always be checked (and sanitized) as no amount of JavaScript, HTML, or CSS is going to prevent someone who knows what they're doing from adding new or changing/removing existing values.

How do I determine whether data on a form has been input by the user or the browser?

I have a checkout form that will display a pop-up survey to ask why they haven't started filling out the form after 5 seconds. However, I need to be able to check whether the user has actually entered data as opposed to data entered by the browser's auto-fill feature (any pre-populated data set in the markup I specifically ignore in the javascript or jQuery).
Right now my solution is to have the setTimeout run a function which checks a variable (true or false) that is set to false on a jQuery .focus or .change event on the input types (input, select, textarea). However, since the javascript may load after the user is able to use the form elements, I have to check whether the user has entered data before the survey pops up.
Is it possible to differentiate between user-inputted data and browser-inputted data if the javascript loads after the user has done anything to the form fields?
If you really want to tell browser not to autofill it at all, you could use autocomplete attribute, but this is unfortunately an invalid attribute and thus will not validate. If you really need your HTML to validate, you can use jQuery to do just that for you:
$(your_form_selector).attr('autocomplete', 'off');
More discussion about autocomplete here
What about .keyup event for form?
var isFilledByUser = false;
$("#input").keyup(function(){
var isFilledByUser = true;
});
ok... this was mildly entertaining, but I definitely agree... this feature would be so annoying XD
http://jsfiddle.net/NTvrN/1/
but there you go... now type, foo!

Categories

Resources