I have some javascript functions on my website, but I don't know if it is safe to use them.
here is my code :
// works like PHP's $_GET
function get(name){
name=name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
regexS="[\\?&]"+name+"=([^&#]*)";
regex=new RegExp(regexS);
results=regex.exec(window.location.href);
if(results==null)
return '';
return results[1];
}
// and here is my anti xss filter
var param = unescape(decodeURI(get("q")));
param = param.replace(/<(.*?)>/gi, "");
someElement.innerHTML = param;
Is it possible to bypass this filters?
Do not try and find XSSes on the way into your application. Your program may transform the data internally in such a way that any filter you create is likely to be circumventable.
Instead, apply proper HTML encoding of data on the way out of your application. That way you avoid the vulnerabilities.
No, but if you simulate multiline mode in your second last line like this:
param = param.replace(/<([\s\S]*?)>/gi, "");
your example code would be safe as it is. The biggest flaw in your example code is using innerHTML when you do not want to add HTML at all. So instead of using innerHTML and trying to filter out HTML you should use createTextNode and you will not have to worry about XSS anymore. So keep your get function if you like it, and use the parameter values like this (adapted from MDN):
var param = unescape(decodeURI(get("q")));
var text = document.createTextNode(param);
document.getElementById(someElement).appendChild(newtext);
If you use jQuery, you can use .text() function, which itself uses createTextNode.
Related
I am running an API to retrieve email from external system. I managed to get HTML code from the returned JSON and store it in a variable. Now, I would like to run some further operations on this HTML - for example get all elements with
[data-type="whatever"].
It would be easy in html document:
var x = document.querySelectorAll('[data-type="whatever"]');
However the HTML document I want to work with is stored in the variable so the code I write in API does not recognise it as a document. How can I do it? Any suggestions with vanilla JS?
You can try something like this.
let rawDoc = '<html><head><title>Working with elements</title></head><body><div id="div1">The text above has been created dynamically.</div></body></html>'
let doc = document.createElement('html');
doc.innerHTML = rawDoc;
let div1 = doc.querySelector('#div1');
console.log(div1)
What if you use innerHTML? or maybe I don't fully understand the question.
Since you are working without a document you have 2 options.
1. Use regex to get what you need (something like /<.+>.+ data-type="whatever".+<\/.+>/gi) should do (but for an exact match you may need to make something better).
2. Insert the html in a hidden part of the dom and select what you need from it (like in Zohir answer - he provided a good example).
I used following code with angular to store whole html content in a variable and pass it as argument to call API.
var htmlBody = $('<div/>').append($('#htmlBody').clone()).html();
This might work for you as i was working on sending email to pass invoice template so try this.
I have some variables in javascript:
var something = 1;
var url = "#CSRF(routes.Some.thing(something))";
I get an error during compilation because "something" does not refer to the javascript variable, in other words; the compiler can't identify it. Is it possible to convert/inject the javascript variable somehow? Also, does this work in real time in javascript or do I need to prepare an "#CSRF(routes.Some.thing(something))" array containing each possible "something" value?
It's supposed to be a simple rest call, seen in routes file:
/something/:something controllers.Some.thing(something : Long)
An alternative would be to use a form, but I want to try not to.
You need to use a Javascript Routing and add the CSRF token to the request.
Javascript Rounting description: https://www.playframework.com/documentation/2.6.x/ScalaJavascriptRouting
Look at my answer to the question with explanation how to use it for assets("Correct and long solution"), the usage for other activities is the same: How to update src of a img from javascript in a play framework project?
So in your case, the Javascript routes generation can look like:
JavaScriptReverseRouter("jsRoutes")(
routes.javascript.Some.thing
)
And in the JavaScript:
var something = 1;
var url = jsRoutes.controllers.Some.thing(something).url;
The last - do not forget to add Csrf-Token header to the request.
Is there a more direct way of writing the following in jQuery?
var $b = $('b');
$b.text($b.text() + ', World!!');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<b>Hello</b>
This seams like something jQuery would have existing functionality for, as vanilla JavaScript can do it by direct access to the property.
document.querySelector('b').innerText += ', World!!';
I looked into the .append() method, however it appears that it isn't designed for appending text, even though it works:
$('b').append(', World!!');
Also the Additional Notes section warns of XSS vulnerabilities when using .append(), as it can potentially execute code.
No. As you have already pointed out, the cleanest way is by modifying the property directly.
To do that in jQuery you can get the DOM element reference from within the object:
var $b = $('b');
$b[0].innerText += ', World!!';
JSFiddle
Or,
You could pass a function to .text(), which isn't any 'cleaner' but can be very helpful if you want to use the context:
var $b = $('b');
$b.text(function(_,v){
return v += ', World!!';
});
JSFiddle
Or,
If it really bugs you, introduce your own jQuery method:
jQuery.fn.appendText = function(a){
return this.each(function(){
$(this).text(function(_,v){
return v += a;
});
});
};
For use like so:
$b.appendText(', World!!');
JSFiddle
'This seams like something jQuery would have existing functionality for, as vanilla JavaScript can do it by direct access to the property.'
Is probably exactly why jQuery doesn't implement its own method to do so. Why waste valuable bytes with a method that will carry out something that is so easily done with vanilla JavaScript?
use text()
$('b').text("Hello");
We need to be aware that this method escapes the string provided as
necessary so that it will render correctly in HTML. To do so, it calls
the DOM method .createTextNode(), which replaces special characters
with their HTML entity equivalents (such as < for <)
When you use .text() jQuery uses createTextNode internally, which escapes all special characters.
I have a problem with old website. All JavaScript code on it use getElemenById function. But tags of site markup doen't have id property, instead they have only name property. Although it still works for IE, browser returns elements even by name property. For all other browsers it's a mistake in JS.
I wonder if there any way to overload this function in other browser to make web site compatible to other browsers?
There's no way to "overload" a function in JavaScript in the sense that you would do so in a strongly-typed language like Java or C. In fact, every function in JavaScript is already overloaded in this sense in that you can call any function with any number and type of arguments.
What you can do, however, is insert your own proxy in front of the existing version, and implement the proxy with whatever behavior you prefer. For instance:
document._oldGetElementById = document.getElementById;
document.getElementById = function(elemIdOrName) {
var result = document._oldGetElementById(elemIdOrName);
if (! result) {
var elems = document.getElementsByName(elemIdOrName);
if (elems && elems.length > 0) {
result = elems[0];
}
}
return result;
};
I wouldn't count on overriding getElementById working properly. Sounds easy enough to do a search and replace that does something like this:
// Replace
document.getElementById("foo");
// With
myGetElementById("foo", document);
// Replace
myElement.getElementById("foo");
// With
myGetElementById("foo", myElement);
Then you can myGetElementById as you want, without worrying about what might happen in old IEs and what not if you override getElementById.
Try getElementsByName. This is used to get a collection of elements with respect to their name
I'm creating a website where I'm doing ajax requests to load some dynamic content AFTER I load a static container page. Basically, I need to pass an array of integers to the page from the server, and I'm using jQuery to load data. I am writing the ints inside a tag with a know name, and using eval to read data from it. Here's a sample tag (returned from ajax):
<span runat="server" class="hidden" id="PhotoList" />
with the codebehind list.ForEach(p => { sb.Append(p.ID.ToString() + ","); } ); where sb is a StringBuilder, so the server as a result returns something like:
<span runat="server" class="hidden" id="PhotoList">1,4,5,42,9</span>
I have a variable photoList declared in the javascript, and I call var scriptToEval = "photoList = [" + $("#PhotoList").html() + "];";
eval(scriptToEval);
I am not a master of Javascript and I just want to be sure that this is safe, as there's lots of discussion on whether eval is safe or not. I THINK this is safe (the ones I've pasted is all the code I'm using with eval), but I may have missed a point, so a professional's opinion is important for me. I know why they say eval is dangerous, as it is capable for interpreting any code, malicious or not, but here, I think this way cannot be compromised at all, as the response from the server is completely under my control. Another option would be making ANOTHER ajax call for the variables and load them directly without ajax from the returned array, but thay would sum to two calls, (I already make the load call anyway as it really loads some HTML content from the server) but this way, even though a bit hacky (putting variables into a hidden HTML tag), seems convenient (and ASP.NET also does this for viewstate too after all!).
My focus is on eval anyway, is this perfectly safe, or should I have some security considerations? Javascript experts please.
If you can be sure that the data is secure, then eval() will be harmless enough.
If you're not so sure, you can use JSON.parse() to take care of it:
var arr = JSON.parse( "[" + $("#PhotoList").html() + "]" );
For browsers that don't support JSON, you can include the json2 library.
Another possibility is to do a split() the loop the items, converting them to numbers from strings.
var arr = $("#PhotoList").html().split(',');
for( var i = 0, len = arr.length; i < len; i++ ) {
arr[i] = parseInt( arr[i], 10 );
}
EDIT: Since you're using jQuery, if for some reason you really don't want .eval(), then use the jQuery.parseJSON()[docs] method.
var arr = jQuery.parseJSON("[" + $("#PhotoList").html() + "]");
EDIT 2: Another way to do it would be to use .replace(), passing a function as the replace value. This will take care of the iteration for you.
var arr = [];
$("#PhotoList").html().replace(/\d+/g, function( s ) { arr.push( parseInt(s,10) ); });
...so many ways to do it.
Of course it's not safe. It's quite easy to stop the code using a debugger and change the content of the element or the variables that script uses.
What you have to consider is what you use the data for. If someone changes the data, can it be used to access something that should not be available, or can it be used to corrupt any data on the server?
If changing the data only affects what's shown on the page, then it's not a problem that the data can be changed.
Safe, yes, assuming your server is secure. Generally the only time you want to truly avoid using eval() is when users are able to add code which other users can see. Like you'd never ever want to use eval() when displaying a forum post, etc. If the code is coming from your server, or if the user's input is only being displayed back to himself/herself, eval() is fine. This is essentially what jsfiddle does.
Code
var result = eval(code);
May change with
var result = new Function('return '+code+');
While you can use eval in this case, I'd still not recommend it, due to the many subtle bugs and performance issues it can generate. It is almost never a good idea to use eval!
Also, it is just as possible to do what you want without eval:
1 - For setting a global variable, instead of using eval you can use the global scope object. All the following are equivalent if myList is a global variable:
myList = [1,2,3];
window.myList = [1,2,3];
window['myList'] = [1,2,3];
2 - For obtaining the array elements you can use the .split() method from strings:
node.innerHTML.split(',')
3 - If you want to convert a string to a number one of the simple ways is to use the unary + operator:
+"3" // is the number 3