Cross Site Scripting cannot be cleared - javascript

In order to prevent malicious html/scripts from being entered in input fields and saved in our application, we are inspecting the user input for html and if found, we don't submit.
We do this using the following function
/**
* Parse for HTML elements to avoid cross-site scripting
* #param str
*/
function isHTML() {
var str = $("#AttributeInstance").val();
var htmltempElement = document.createElement('div');
htmltempElement.innerHTML = str;
for (var c = htmltempElement.childNodes, i = c.length; i--;) {
if (c[i].nodeType == 1) {
htmltempElement = null;
str = null;
return true;
}
}
return false;
}
The function is working great. For instance, if on our form, the user enters the following
<img src=a onerror=alert(1)>
The function returns true and we don't save the value.
Here is how we call this function
if (isHTML()) {
alert("Found HTML! Stop!");
instance = "";
$("#AttributeInstance").val(""); //clear the input field
}
else {
alert("No HTML! Continue");
alert(instance);
addKpi(group, name, instance, instanceSelection);
}
alert("Finished");
Now here is the issue. This code results in an alert of "Found HTML! Stop!" and then "Finished" being displayed.
But then we also get an alert of "1" which is from the original input value that contains the script. By this point, that field has been cleared and we are not storing the malicious script value anywhere, however, it pops it up as a message even though it was clearly detected and we stop processing.
Any ideas? Or any suggestion how to better detect cross site scripting values in an input field?
If we remove the following from the function
htmltempElement.innerHTML = str;
for (var c = htmltempElement.childNodes, i = c.length; i--;) {
if (c[i].nodeType == 1) {
htmltempElement = null;
str = null;
return true;
}
}
Then the script does not pop up the "1" There's something about checking for a script this way that ends up processing the script it seems.

Related

how to catch the event and distinguish close and refresh event

In my project I need to use close event in browser through web, server and database deal with the information when user log out.
I do not know how to catch the event and distinguish close and refresh event.
I tried these code:
window.onbeforeunload = function() {
var n = window.event.screenX - window.screenLeft;
var b = n > document.documentElement.scrollWidth-20;
if(b && window.event.clientY < 0 || window.event.altKey) {
alert("close event");
}else{
alert("refresh event");
}
}
But it only catches the refresh event.
Is there a better way to solve the problem?
Besides,I have read the How to differentiate browser close and refresh events in Chrome?,but it doesn't give me the answer.
An idea: Judge by cookie to get the information if it is log in.
And the browser usually doesn't disable cookies.
If the cookie is disable, you may ask user to enable it.
Here is an example for cookie:
function setCookie(name, value) //cookies setting
{
var argv = setCookie.arguments;
var argc = setCookie.arguments.length;
var expires = (argc > 2) ? argv[2] : null;
if(expires!=null)
{
var LargeExpDate = new Date ();
LargeExpDate.setTime(LargeExpDate.getTime() + (expires*1000*3600*24));
}
document.cookie = name +value }
//In Js
setCookie("a","34234523542");
//read cookie:
function WM_readCookie(name)
{
//if there is no cookie,return false;or get value and return value
if(document.cookie == '')
return false;
else
return
unescape(WM_getCookieValue(name));
}
function WM_getCookieValue(name)
{
// Declare variables.
var firstChar,lastChar;
// Get the entire cookie string.
// (This may have other
name=value pairs in it.)
var theBigCookie = document.cookie;
// Grab
just this cookie from theBigCookie string.
// Find the start of
'name'.
firstChar = theBigCookie.indexOf(name);
// If you found it,
if(firstChar != -1)
{
// skip 'name' and '='.
firstChar +=
name.length + 1;
// Find the end of the value string (i.e. the next
';').
lastChar = theBigCookie.indexOf(';', firstChar);
if(lastChar == -1) lastChar = theBigCookie.length;
// Return the
value.
return theBigCookie.substring(firstChar, lastChar);
} else
{
// If there was no cookie, return false.
return false;
}
}

How to know if browser tab is already open using Javascript?

How to know or check if the two browser tab is already open and if those tab are open, the user will receive an alert box or msg box saying that 'the url is already open', something like that, in pure/native JavaScript? This browser tab is contain an external website which is I don't have any privileges to manipulate or change it. Thanks
Example URLs
yahoo.com and google.com
I want to alert the user if there's already open tab for yahoo.com and google.com
And I want to use tabCreate to open the url like this:
tabCreate("http://maps.google.com/", "tabMapsPermanentAddress");
mean to open a new tab, it is use in creating chrome extension
You may use something like following
<!-- HTML -->
<a id="opener">Open window</a>
// JavaScript
var a = document.getElementById('opener'), w;
a.onclick = function() {
if (!w || w.closed) {
w = window.open("https://www.google.com","_blank","menubar = 0, scrollbars = 0");
} else {
console.log('window is already opened');
}
w.focus();
};
Working jsBin | More on window.open method
If you want to control more than one window, use the snippet below
<!-- HTML -->
Open google.com |
Open yahoo.com
//JavaScript
window.onload = function(){
var a = document.querySelectorAll('.opener'), w = [], url, random, i;
for(i = 0; i < a.length; i++){
(function(i){
a[i].onclick = function(e) {
if (!w[i] || w[i].closed) {
url = this.href;
random = Math.floor((Math.random() * 100) + 1);
w[i] = window.open(url, "_blank", random, "menubar = 0, scrollbars = 0");
} else {
console.log('window ' + url + ' is already opened');
}
e.preventDefault();
w[i].focus();
};
})(i);
}
};
Working jsBin
If you don't want them to load in separated window, just exclude this line
random = Math.floor((Math.random()*100)+1);
and remove random reference from the next line
w[i] = window.open(url, "_blank", random, "menubar=0,scrollbars=0");
Side note: As you can see above, we created two windows with some third party content; you should know that there's no way to get any reference (to the parent/opener window) from them.
One basic idea is to store the tab count in either a cookie or localStorage, incrementing it on page load and decrementing it on page unload:
if (+localStorage.tabCount > 0)
alert('Already open!');
else
localStorage.tabCount = 0;
localStorage.tabCount = +localStorage.tabCount + 1;
window.onunload = function () {
localStorage.tabCount = +localStorage.tabCount - 1;
};
Try opening this fiddle in multiple tabs.
Note that this technique is pretty fragile, though. For example, if for some reason the browser crashes, the unload handler won't run, and it'll go out of sync.
The answer by Casey Chu works fine until the browser crashes with the page open. On any next execution, the localStorage object will have initialized tabCount with non zero value. Therefore a better solution is to store the value in a session cookie. The session cookie will be removed when browser exits successfully. When the browser crashes the session cookie will actually be preserved but fortunately only for one next execution of the browser.
Object sessionStorage is distinct for each tab so it cannot be used for sharing tab count.
This is the improved solution using js-cookie library.
if (+Cookies.get('tabs') > 0)
alert('Already open!');
else
Cookies.set('tabs', 0);
Cookies.set('tabs', +Cookies.get('tabs') + 1);
window.onunload = function () {
Cookies.set('tabs', +Cookies.get('tabs') - 1);
};
This answer: https://stackoverflow.com/a/28230846 is an alternative that doesn't require Cookies/js-cookie library. It better suited my needs. In a nutshell (see linked answer for full description):
$(window).on('storage', message_receive);
...
// use local storage for messaging. Set message in local storage and clear it right away
// This is a safe way how to communicate with other tabs while not leaving any traces
//
function message_broadcast(message)
{
localStorage.setItem('message',JSON.stringify(message));
localStorage.removeItem('message');
}
// receive message
//
function message_receive(ev)
{
if (ev.originalEvent.key!='message') return; // ignore other keys
var message=JSON.parse(ev.originalEvent.newValue);
if (!message) return; // ignore empty msg or msg reset
// here you act on messages.
// you can send objects like { 'command': 'doit', 'data': 'abcd' }
if (message.command == 'doit') alert(message.data);
// etc.
}
Just going to throw this up here, because I wish I had something like it. Make what you will of it.
If you want a solution for checking if you are the active tab that doesn't require a cookie, works as a React hook, and works whether or not the browser crashes, you can use this useIsActiveTab webhook which returns true if you are the most recent active tab/window. You can also set yourself as the active tab with activateTab.
import { useEffect, useState } from 'react';
const CHARACTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const CHARACTERS_LENGTH = CHARACTERS.length;
function generateTabId() {
let result = '';
const prefix = 'TAB_';
const length = 15;
for (let i = 0; i < length - prefix.length; i++) {
result += CHARACTERS.charAt(Math.floor(Math.random() * CHARACTERS_LENGTH));
}
if (prefix.includes('_')) {
return `${prefix}${result}`;
}
return `${prefix}_${result}`;
};
const tabId = generateTabId();
export function activateTab(): void {
localStorage.setItem('activeTab', tabId);
const event = new Event('thisStorage');
window.dispatchEvent(event);
}
export function useIsActiveTab(): boolean {
const [isActiveTab, setIsActiveTab] = useState(false);
useEffect(() => {
setActiveTab();
function updateIsActiveTab() {
setIsActiveTab(checkIfActiveTab());
}
window.addEventListener('storage', updateIsActiveTab);
window.addEventListener('thisStorage', updateIsActiveTab);
updateIsActiveTab();
return () => {
window.removeEventListener('storage', updateIsActiveTab);
window.removeEventListener('thisStorage', updateIsActiveTab);
};
}, []);
return isActiveTab;
}
function checkIfActiveTab(): boolean {
const activeTab = localStorage.getItem('activeTab');
if (!activeTab) {
console.error('localStorage.activeTab is not set');
return true;
}
if (activeTab === tabId) {
return true;
}
return false;
}
function setActiveTab(): void {
localStorage.setItem('activeTab', tabId);
}

Display All ().html in Javascript

Sorry for the lack of description in title, it's difficult to explain.
So I have a simple signup page and I made a bunch of functions in my code that check things such as the username length, make sure the passwords match, etc..
The problem is, if there is more than one error in the users input, it only displays one error at the bottom.
HEre is the JSfiddle: http://jsfiddle.net/LCBradley3k/xqcJS/19/
Javascript:
$('#join').on('click', function () {
var correct = true;
$('input[type="text"], input[type="password"]').each(function (indx) {
var $currentField = $(this);
if ($currentField.val() === '') {
$currentField.addClass('empty');
correct = false;
$currentField.one('keydown', function () {
$currentField.removeClass('empty');
});
} else {
$currentField.removeClass('empty');
}
});
function userLength() {
var x = $('input[name="user"]').val();
if (x.length < 6) {
$('#answer').html('Less than six characters.');
$('input[name="user"]').addClass('empty');
return false;
} else {
return true;
}
}
function passwordCheck() {
var x = $('input[name="password"]').val();
var y = $('input[name="passwordcheck"]').val();
if (x === y) {
return true;
} else {
$('#answer').html('Two different passwords');
$('input[name="password"], input[name="passwordcheck"]').addClass('empty');
return false;
}
}
function validateForm() {
var x = $('input[name="email"]').val();
if (x.indexOf('#') !== -1 && x.lastIndexOf(".") !== -1) {
return true;
} else {
$('#answer').html('Not a valid email');
$('input[name="email"]').addClass('empty');
return false;
}
}
if (correct) {
if (userLength()) {
if (passwordCheck()) {
if (validateForm()) {
$('#answer').html('Thank You!');
setTimeout(function () {
$('.inputs').hide("slide", {
direction: "up"
}, 1000);
}, 2000);
}
}
}
} else {
$('#answer').html('Please fill highlighted fields.');
}
});
You can see that all of them edit the #('#answer') div with .html(). But only one is displayed when there is more than one error. Once that error is fixed and the button is pressed, it will then display the next error. I want them all to be displayed in a list.
I created a fiddle that may be of some help. The idea is to create an array with the errors in it like so:
var errors = [];
errors.push("Error 1");
errors.push("Error 2");
As you step through the validation, every time an error is encountered you simply push the error string onto the array. When you get to the end of the validation you need to compile these errors into html like that can be appended to your $('#answer') element. In this case the items are compiled into an unordered list. You can change this to fit your needs.
var content = "<ul>";
for(var a = 0, len = errors.length; a < len; a++) {
content += "<li>" + errors[a] + "</li>";
}
content += "</ul>";
$('#answer').html(content);
The html is built dynamically and stored in the variable content. content is then appended to your html element that displays the errors (in your case answer).
You have 2 issues with doing what you want.
First, you are only continuing your checks if the first one passes, due to your nested if statements.
Second, you are replacing the #answer html with the message, which means even if you do each check, you will only see the results of the last one.
A simple fix would be to un-nest your if statements, and keep a variable that tracks the overall pass state. Secondly, instead of using .html(), use .append(), but make sure to clear out #answer before starting your checks.
correct &= checkFilled();
correct &= userLength();
correct &= passwordCheck();
correct &= validateForm();
if (correct) {
// ...
}
Fiddle: http://jsfiddle.net/jtbowden/9cFKW/
Note: I made your form filled check it's own function to work better with this method.
You can do some more fancy things, like pushing error messages on an array, and then checking the array for errors at the end and appending all of the messages, but this should get you started.

Cannot figure out why form error messages are cleared on resubmission

On first submit the error messages come up. In order to clear out error messages for correct values, I created a loop to clear out any spans on those labels, with the thinking that ALL messages would be cleared out, then run through the error checking again and re-apply the error messages.
Even if I return false on the loop to clear out the error messages it just refreshes the page. And the code does not appear to make it past that point and go through the standard error checking.
var label = document.getElementsByTagName("label");
var span = document.getElementsByTagName("span");
var spanMatch = false;
//attempting to remove any span tags once it's resubmitted
for (var k=0; k<label.length; k++) {
if (label.childNodes = span[1]) {
label.removeChild.span[1];
spanMatch = true;
}
}
if (spanMatch) {return false;}
var match = false;
//created a single loop so it would check all without return false until all were checked
for (var i=0; i<1; i++) {
if (!loanVal.match(regexOne)) {
wholeError(obj.loanAmt.name);
match = true;
}
if (!interestVal.match(regexTwo)){
floatError(obj.interest.name);
match = true;
}
if (!periodVal.match(regexOne)) {
wholeError(obj.period.name);
match = true;
}
}
if (match) {return false;}
else {alert("Something is right");}
}
I hope that is enough code to tell where the problem is. Here's a link to this problem online: http://russet.wccnet.edu/~sfloyd/inp271/php-js-project/loan-calc/index.php
Thanks

How to check table for new content, and then update browser tab title?

I am working on a way to flash a browser tab when a new message appears in a table. I have the flashing of the tab part working, my only problem is that I can't seem to get it to flash when a message is received (which is the whole point of my exercise :) )
The newMessage() function is working fine, I just can't seem to get the notification() function to work.
My code is as follows:
function newMessage()
{
var oldTitle = "Your Page";
var msg = "New Message";
var timeout = setInterval(function()
{
document.title = document.title == msg ? '' : msg;
}, 1000);
window.onmousemove = function() {
clearInterval(timeout);
document.title = oldTitle;
window.onmousemove = null;
};
}
function notification()
{
var index = 2;
var content = document.getElementById('refreshMessages').childNodes[index];
var content = document.getElementById('refreshMessages').getElementByTagName("tr")[1];
var knownContent = content.toString();
updater.start();
updater2.start();
var newContent = document.getElementById('refreshMessages').childNodes[index];
var newContent = document.getElementById('refreshMessages').getElementByTagName("tr")[1];
if(knownContent != newContent.toString())
{
newMessage();
knownContent = newContent;
}
else if(knownContent = newContent.toString())
{
alert("No need to flash title.");
}
}
notification();
In the notification() function, I am trying to call the newMessage() function by comparing the strings at the appropiate cell in the table.
I put the alert() into the else if just to see if it would be called, but it does not happen. update.start() and update2.start() are carried out however, as I can see the messages appearing in the table.
I would be happier to use JavaScript but I am open to jQuery also.
My JavaScript is very very rusty so excuse me if I have made any silly mistakes!
Thanks,
Chuck
You have several mistakes in function notification(), see my comments:
function notification()
{
var index = 2;
//Why are you assigning value to "content" for twice?
var content = document.getElementById('refreshMessages').childNodes[index];
/*
* function getElementByTagName is undefined, should be getElementsByTagName,
* 's' is missing. And [1] means the second one not the first one, make sure
* that's exactly what you want.
*/
var content = document.getElementById('refreshMessages').getElementByTagName("tr")[1];
/*
* content is a tr dom object, content.toString() is something like "[object]".
* If you want to get content inside a cell, you should use cell.innerHTML.
* e.g. A table:
* <table id="refreshMessages">
* <tr><td>Hello world</td></tr>
* </table>
* var table = document.getElementById('refreshMessages');
* var firstTr = table.getElementsByTagName("tr")[0];
* var firstTd = firstTr.getElementsByTagName("td")[0];
* alert(firstTd.innerHTML); //alerts "Hello world"
*/
var knownContent = content.toString();
//I doubt these functions really get invoked cuz there's javascript error above.
updater.start();
updater2.start();
//assigning twice, "getElementByTagName" is missing "s"
var newContent = document.getElementById('refreshMessages').childNodes[index];
var newContent = document.getElementById('refreshMessages').getElementByTagName("tr")[1];
//Remove toString(), use innerHTML i metioned above.
if(knownContent != newContent.toString())
{
newMessage();
knownContent = newContent;
}
//You miss an "=" here, to judge a equals b, you should use "=="
else if(knownContent = newContent.toString())
{
alert("No need to flash title.");
}
}

Categories