Is safety of Object as dictonary really really guaranteed by standard? - javascript

var x = Object.create(null);
x["hello"] = "world";
But can I allow unverified user input as keys? I want to use it as player name -> player object map. Player names will only be constrained by length of 32. I'm worried if there are special property keys that would allow players to gain control of the server.
EDIT: I'm not making web server. JavaScript will be ran server-side via SpiderMonkey embedded into the game server. If someone hijacks the JavaScript running there, they could ruin the game.

In one word: no, just remember the Google Docs __proto__ fail
You should use a Hash-like class, or at least access these keys prefixed:
var hash = {}, key = "something-evil", value = Math.PI;
hash["$" + key] = value;
console.log( hash["$" + key] == value );

Property keys are always strings. You'll never encounter a problem with any property name, except for maybe:
Object.prototype.hasOwnProperty. For example in:
var obj = {hasOwnProperty:'fail'};
for (var i in obj) {
if (obj.hasOwnProperty(i)) ; // ...
}
which can be solved by using Object.keys(obj).forEach( ... ) or:
for (var i in obj) {
if (Object.hasOwnProperty.call(obj, i)) ; // ...
}
The only hazard is caused by how you deal with the object. The previous example is not an uncommon usage of hasOwnProperty, but it can be used to break your script, because you don't expect the key name hasOwnProperty. The same can apply to .toString, or any other property of the object which can be overriden by setting a new name.

No, an object is basically a blank slate, there are no special keys. On top of that, even if somebody hacks your Javascript it is very unlikely that they will gain control of your server unless you are using very lax security policies (like putting the root password in your Javascript or something silly like that).

You cannot control what will be sent to your web server. At all. Ever.
So, you need to put restrictions on what you server will do, in response to anything sent to it. Part of this is validating all user input, even if it's JSON representing a JavaScript object that was created by your code.

Related

javascript How do I "dereference" a variable's content for use as a variable name?

I want to reduce the I/O overhead of fetching information from the server using XMLHttpRequest() or ActiveXObject(), as appropriate, by making a general-purpose function for doing the fetch which then stores the fetched data using sessionStorage.<variable>. The trouble is, I don't know in advance what the variable names all are, and I intentionally don't want to know.
I was thinking that if there is some way to "dereference" a variable, like we can easily do in BASH, for example, this would be trivial. For example, if the fetched data was in newData, and the name of the file it was fetched from is in dataFile, and if the dereference syntax was, say $(<variableName>), then one could write code like this to store and fetch the data:
//Store the data:
sessionStorage.$(dataFile) = newData;
//Fetch the data:
var storedData = sessionStorage.$(dataFile);
Get it? ... OK, now, how do I ACTUALLY do this?!
...The only other way around this I can see is VERY clumsy - make arrays, one with name, another with values - there MUST be an easier way! TIA.
As always, it is good to visit the docs first. There you can see, that sessionStorage (like localStorage or Map) has no properties at all (except a hidden property pointing to internal memory but thats another thing), but rather makes the data available through its get or set methods:
sessionStorage.set("a name", "a value");
However the session/localStorage provides also global getters/setters, so in theory one can do:
sessionStorage.name = "value";
If the keys name is dynamic one could use bracket notation:
sessionStorage[aName] = aValue;
However, they havent it even mentioned in the docs, so this feature is neither widely supported nor a good coding style.
Try this. Not exactly sure I followed your question clearly but I would try this if you are having issues using the variable name as string within your other code.
var_param = GET_YOUR_VAR_SOMEHOW; // strip your params as needed
let f1 = { getVarName:var_param.toString()} // object = to f2
let f2 = 'getVarName'; // string = to f1 key
var storedData = sessionStorage.$(f1[f2]); // result of f1[f2] should be your incoming var string, de-referenced from any content.

Breakpoint on any string assignment if string contains a certain substring

Can I put a data breakpoint which triggers if any variable is assigned to a string containing a certain substring?
For example, I want to reverse-engineer how a URL containing &ctoken= is constructed. It's done with complicated JavaScript where the goal is to obfuscate it.
If I could tell the JS VM to monitor all string variables and break when a certain substring appears on any variable, this would help me a lot.
Is this possible?
Before I start - as of my knowledge this is not possible.
What you'd need (even before creating the debugging feature) is the raw string types already boxed to String the native built-in object and String then already proxied.
Some more explanation:
only having
const s = "hi"
is not yet an instance of String - the built-in native object, which is supplied by the ECMAScript implementation to your scope - but a raw type.
Such raw types are nothing more than pointers to a raw data memory reference. I even assume there are built in pools like in Java to optimize cases like
const s = "hi"
const x = new String("hi")
to be the same memory reference of the data object. but the later of course would be boxed by String.
http://bespin.cz/~ondras/html/classv8_1_1String.html
On raw types we couldn't - even if we wanted to - add a subscriber.
for example then:
s.charAt(i)
will autobox s to its wrapper String.
to observe every raw type would mean that we'd have to box all raw strings to String which wouldn't be a good thing for performance at all.
not only that but also the implementation of String itself would have to allow us to add a subscriber and therefore be proxied already.
in JS such proxy would look like this (to make it more understandable what I mean by proxied):
var proxiedString = new Proxy(String, {
defineProperty(target, propKey, propDesc) {
console.log('defined a new string')
},
set(obj, prop, value) {
console.log('set a new value to a string')
}
});
proxiedString.x = 'newPropValue'
and that again I guess - wouldn't be good for performance.
You can use condition breakpoints at browser devTools, by right
click with a menu.
If you can write a js somewhere in a page, you
can do this:
.
if(window.location.pathname.indexOf("&ctoken=") > -1){
debugger;// browser will put breakpoint automaticaly here, if condition is trully.
console.dir(window.location);
}

Could this be considered a security vulnerability?

I discovered some javascript in a site that didn't sanitize external data (siteName), but it's used in such a way that I think does not represent a problem. Certainly, the best thing to do would be to filter it so that only expected values could interact with code and there would be no worry about unexpected input. But, how much damage could be inflicted in the current setup?
var branding = {
'website1.com' : {
color: 'red'
},
'website2.com' : {
color: 'blue'
}
};
var siteName = document.referrer.split('/')[2];
var myElements = document.querySelectorAll(".some-class-name");
for (var i = 0; i < myElements.length; i++) {
myElements[i].style.color = branding[siteName]['color'];
}
This code is poorly conceived, but I don't think it's exploitable.
document.referrer.split('/')[2] extracts the hostname of the referrer. An attacker might have control over the hostname, but only to a limited degree; they can't put anything into that field that they can't register or set up as a domain name.
branding[siteName] could be made to do some interesting things if siteName is the name of an internal property on Object, like __proto__, or a method name, like hasOwnProperty. However, none of these properties would have been valid as Internet hostnames, as none of them have periods in them. __proto__ contains underscores, which aren't even valid in hostnames!
If siteName were not constrained, the following ['color'] still limits this code. Functions (like hasOwnProperty) wouldn't have a color property; nor would the Object prototype, so this looks like a dead end.
Even if we assume that a weird value like a function somehow got into the result, assigning a value like that to .style.color wouldn't do anything weird.
The potential for a vulnerability could easily be avoided, though:
var siteName = document.referrer.split('/')[2];
if (branding.hasOwnProperty(siteName)) {
... everything else ...
}
Object.hasOwnProperty is false for method names and "weird" properties like __proto__; it's only true for properties that have been explicitly declared on an object. This would limit the following code to only running for the intended site names.

Securing JavaScript eval function

We want to give our users the ability to execute self created JavaScript code within our application. For this we need to use eval to evaluate the code. To reduce all security concerns to a minimum (if not zero), our idea is to prevent the usage of any window or document function within the code. So no XMLHttpRequest or anything similar.
This is the code:
function secure_eval(s) {
var ret;
(function(){
var copyXMLHttpRequest = XMLHttpRequest; // save orginal function in copy
XMLHttpRequest = undefined; // make orignal function unavailable
(function() {
var copyXMLHttpRequest; // prevent access to copy
try {
ret = eval(s)
} catch(e) {
console.log("syntax error or illegal function used");
}
}())
XMLHttpRequest = copyXMLHttpRequest; // restore original function
}())
return ret;
}
This works as follows:
secure_eval('new XMLHttpRequest()'); // ==> "illegal function used"
Now I have several questions:
Is this pattern the right way to secure eval?
What functions of window and document are the ones which are considered harmful?
To ship around question 2. I tried to mask all (native) functions of window But I am not able to enumerate them:
This does not list XMLHttpRequest for instance:
for( var x in window) {
if( window[x] instanceof Function) {
console.log(x);
}
}
Is there a way to get a list of all native functions of window and document?
EDIT:
One of my ideas is to perform the eval within a Worker and prevent access to XMLHttpRequest and document.createElement (see my solution above). This would have (to my mind) the following consequences:
no access to the original document
no access to the original window
no chance to communicate with external resources (no ajax, no scripts)
Do you see any drawback or leaks here?
EDIT2:
In the meantime I have found this question which answer solves many of my problems plus a couple of things I did not even think about (i.e. browser dead lock with "while(true){}".
Your code does not actually prevent the use of XMLHttpRequest. I can instantiate an XMLHttpRequest object with these methods:
secure_eval("secure_eval = eval"); // Yep, this completely overwrites secure_eval.
secure_eval("XMLHttpRequest()");
Or:
secure_eval("new (window.open().XMLHttpRequest)()")
Or:
secure_eval("new (document.getElementById('frame').contentWindow.XMLHttpRequest)()")
This 3rd method relies on the presence of an iframe in the HTML of the page, which someone could add by manipulating the DOM in their browser. I do such manipulations every now and then with Greasemonkey to remove annoyances or fix broken GUIs.
This took me about 5 minutes to figure out, and I am not by any means a security guru. And these are only the holes I was able to find quickly, there are probably others, that I don't know about. The lesson here is that it is really really really hard to secure code through eval.
Using A Worker
Ok, so using a Worker to run the code is going to take care of the 2nd and 3rd cases above because there's no window accessible in a Worker. And... hmm.. the 1st case can be handled by shadowing secure_eval inside its scope. End of story? If only...
If I put secure_eval inside a web worker and run the following code, I can reacquire XMLHttpRequest:
secure_eval("var old_log = console.log; console.log = function () { foo = XMLHttpRequest; old_log.apply(this, arguments); };");
console.log("blah");
console.log(secure_eval("foo"));
The principle is to override a function that is used outside secure_eval to capture XMLHttpRequest by assigning it to a variable that will be deliberately leaked to the global space of the worker, wait until that function is used by the worker outside secure_eval, and then grab the saved value. The first console.log above simulates the use of the tampered function outside secure_eval and the 2nd console.log shows that the value was captured. I've used console.log because why not? But really any function in the global space could be modified like this.
Actually, why wait until the worker may use some function we tampered with? Here's another, better, quicker way to do access XMLHttpRequest:
secure_eval("setTimeout(function () { console.log(XMLHttpRequest);}, 0);");
Even in a worker (with a pristine console.log), this will output the actual value of XMLHttpRequest to the console. I'll also note that the value of this inside the function passed to setTimeout is the global scope object (i.e. window when not in a worker, or self in a worker), unaffected by any variable shadowing.
What About the Other Question Mentioned in This Question?
What about the solution here? Much much better but there is still a hole when run in Chrome 38:
makeWorkerExecuteSomeCode('event.target.XMLHttpRequest',
function (answer) { console.log( answer ); });
This will show:
function XMLHttpRequest() { [native code] }
Again, I'm no security guru or cracker bent on causing trouble. There are probably still more ways I'm not thinking about.
I'll try and answer your questions in order here.
Is this pattern the right way to secure eval?
This part is slightly subjective. I don't see any major security drawbacks to this. I tried several ways to access XMLHttpRequest, but i couldn't:
secure_eval('XMLHttpRequest')
secure_eval('window.XMLHttpRequest')
secure_eval('eval("XMLHttpRequest")()')
secure_eval('window.__proto__.XMLHttpRequest') // nope, it's not inherited
However, it will be a lot if you want to blacklist more things.
What functions of window and document are the ones which are considered harmful?
That depends on what you consider "harmful". Is it bad if the DOM is accessible at all? Or what about WebKit desktop notifications, or speech synthesis?
You'll have to decide this based on your specific use case.
To ship around question 2. I tried to mask all (native) functions of window, but I am not able to enumerate them:
That's because most of the methods are non-enumerable. To enumerate, you can use Object.getOwnPropertyNames(window):
var globals = Object.getOwnPropertyNames(window);
for (var i = 0; i < globals.length; i++) {
if( window[globals[i]] instanceof Function) {
console.log(globals[i]);
}
}
One of my ideas is to perform the eval within a Worker and prevent access to XMLHttpRequest and document.createElement (see my solution above).
This sounds like a good idea.
I stumbled across a really, really nice blog article about the notorious Eval here. The article does discuss in detail. You won't be able to alleviate all security concerns, but you can prevent Cross-Script Attacks by building tokens for the input. This would in theory prevent malicious code that could be harmful from being introduced.
Your only other hurdle will be Man-In-The-Middle Attacks. I'm not sure if that would be possible, as you can't trust input and output.
The Mozilla Developer Network does explicitly state:
eval() is a dangerous function, which executes the code it's passed
with the privileges of the caller. If you run eval() with a string
that could be affected by a malicious party, you may end up running
malicious code on the user's machine with the permissions of your
webpage / extension. More importantly, third party code can see the
scope in which eval() was invoked, which can lead to possible attacks
in ways to which the similar Function is not susceptible.
eval() is also generally slower than the alternatives, since it has to
invoke the JS interpreter, while many other constructs are optimized
by modern JS engines.
There are safer (and faster!) alternatives to eval() for common
use-cases.
I'm slightly against Eval and truly try to use it when warranted.
I have stated it yet in my question, but to make it more clear I will post it as an answer also:
I think the accepted answer on this question is the correct and only way to completely isolate and constrain eval().
It is also secure against these hacks:
(new ('hello'.constructor.constructor)('alert("hello from global");'))()
(function(){return this;})().alert("hello again from global!");
while(true){} // if no worker --> R.I.P. browser tab
Array(5000000000).join("adasdadadasd") // memory --> boom!
There was a question long ago much like this. So I dusted off some old code and fixed it up.
It essentially works by taking advantage of the with keyword and providing it with a frozen empty object. The prototype of the empty object is filled with null properties, the keys of which match the names global variables like self, window and their enumerable property keys; The prototype object is also frozen. eval is then called within the with statement (Almost the same way that scripts run with an implicit with(window){} block if I understand correctly). When you try to access window or its properties you get redirected (via the with block) to null versions (with same key) found in empty object (or rather the empty object's prototype):
function buildQuarantinedEval(){
var empty=(function(){
var exceptionKeys = [
"eval", "Object", //need exceptions for these else error. (ie, 'Exception: redefining eval is deprecated')
"Number", "String", "Boolean", "RegExp", "JSON", "Date", "Array", "Math",
"this",
"strEval"
];
var forbiddenKeys=["window","self"];
var forbidden=Object.create(null);
[window,this,self].forEach(function(obj){
Object.getOwnPropertyNames(obj).forEach(function(key){
forbidden[key]=null;
});
//just making sure we get everything
Object.keys(obj).forEach(function(key){
forbidden[key]=null;
});
for(var key in obj){
forbidden[key]=null;
}
});
forbiddenKeys.forEach(function(key){
forbidden[key]=null;
});
exceptionKeys.forEach(function(key){
delete forbidden[key];
});
Object.freeze(forbidden);
var empty=Object.create(forbidden);
Object.freeze(empty);
return empty;
})();
return function(strEval){
return (function(empty,strEval){
try{
with(empty){
return eval(strEval);
}
}
catch(err){
return err.message;
}
}).call(empty,empty,strEval);
};
}
Setup by building a function/closure that evaluates some expression:
var qeval=buildQuarantinedEval();
qeval("'some expression'"); //evaluate
Tests:
var testBattery=[
"'abc'","8*8","console","window","location","XMLHttpRequest",
"console","eval('1+1+1')","eval('7/9+1')","Date.now()","document",
"/^http:/","JSON.stringify({a:0,b:1,c:2})","HTMLElement","typeof(window)",
"Object.keys(window)","Object.getOwnPropertyNames(window)",
"var result; try{result=window.location.href;}catch(err){result=err.message;}; result;",
"parseInt('z')","Math.random()",
"[1,2,3,4,8].reduce(function(p,c){return p+c;},0);"
];
var qeval=buildQuarantinedEval();
testBattery.map(function(code){
const pad=" ";
var result= qeval(code);
if(typeof(result)=="undefined")result= "undefined";
if(result===null)result= "null";
return (code+pad).slice(0,16)+": \t"+result;
}).join("\n");
Results:
/*
'abc' : abc
8*8 : 64
console : null
window : null
location : null
XMLHttpRequest : null
console : null
eval('1+1+1') : 3
eval('7/9+1') : 1.7777777777777777
Date.now() : 1415335338588
document : null
/^http:/ : /^http:/
JSON.stringify({: {"a":0,"b":1,"c":2}
HTMLElement : null
typeof(window) : object
Object.keys(wind: window is not an object
Object.getOwnPro: can't convert null to object
var result; try{: window is null
parseInt('z') : parseInt is not a function
Math.random() : 0.8405481658901747
[1,2,3,4,8].redu: 18
*/
Notes: This technique can fail when some properties of window are defined late (after initializing/creating our quarantined eval function). In the past, I've noticed some property keys are not enumerated until after you access the property, after which Object.keys or Object.getOwnPropertyNames will finally be able grab their keys. On the other hand this technique can also be quite aggressive in blocking objects/functions you do not want blocked (an example would be like parseInt); In these cases, you'll need to manually add global objects/functions that you do want into the exceptionKeys array.
*edit* Additional considerations: How well this all performs depends entirely on how well the mask matches that of the property keys of the window object. Any time you add an element to the document and give it a new ID, you just inserted a new property into the global window object, potentially allowing our 'attacker' to grab it and break out of the quarantine/firewall we've setup (i.e. access element.querySelector then eventually window obj from there). So the mask (i.e., the variable forbidden) either needs to be updated constantly perhap with watch method or rebuilt each time; The former conflicts with the necessity of the mask to have a frozen interface, and the latter is kinda expensive having to enumerate all the keys of window for each evaluation.
Like I said earlier, this is mostly old code I was working on, then abandoned, that was quickly fixed up on short order. So it's not by any means thoroughly tested. I'll leave that to you.
and a jsfiddle
I have small idea about secure eval for small or limited things if you know well what u going to use eval in you can create white list and black list and excute only the strings that has the valid but it good for small covered app for example calculator has few options (x, y) and (+,*,-,/) if i added this characters in white list and add check for script length and study what excepted length of the script run it can be secure and no one can pass that
const x = 5;
const y = 10;
function secureEval(hack_string){
// 0 risk eval calculator
const whiteList = ['',' ', 'x', 'y','+','*','/','-'];
for (let i=0; i<hack_string.length; i++){
if (!whiteList.includes(hack_string[i])){
return 'Sorry u can not hack my systems';
}
}
return 'good code system identify result is : ' + eval(hack_string);
}
// bad code
document.getElementById("secure_demo").innerHTML = secureEval('x * y; alert("hacked")');
document.getElementById("demo").innerHTML = secureEval('x * y');
<!DOCTYPE html>
<html>
<body>
<h1>Secure Eval</h1>
<p id="secure_demo"></p>
<p id="demo"></p>
</body>
</html>

Pitfalls using DOM-Javascript VS pure Javascript objects?

Background
First of, I would like to mention, that a SO-search for figuring out differences of
(host objects) DOM-Javascript Objects (var domJSobj = document.createElement("div")) and
(native objects) pure Javascript Objects (var pureJSobj = {})
has been done, but still I cannot claim that I found very much (great is, that there is this question-answers: what-is-the-difference-between-native-objects-and-host-objects). Maybe I overlooked something here, then a comment is very appreciated.
I also read MDN Mozillas Docu on DOM and Javascript to get some idea before asking here.
Question
Being a little "glueless" I started playing in the Javascript Console and I encountered some first pitfall (arising from expectations I have regarding the behaviour of (native objects) which are not true for (host objects)). To be clear many things -at first sight- seem similar:
var nativeObject = {}; //create new object
nativeObject.someAttribute = "something"; //set some attribute
nativeObject.someMethod = function() { return this.someAttribute; } // define some method
console.log(nativeObject.someAttribute); // "something"
console.log(nativeObject.someMethod()); // "something"
var hostObject = document.createElement("div"); //create a "div" one type of host object
hostObject.someAttribute = "something"; //set some attribute
hostObject.someMethod = function() { return this.someAttribute; } // define some method
console.log(hostObject.someAttribute); // "something"
console.log(hostObject.someMethod()); // "something"
For me it seems at first sigth that a (host object) is just as usable as a (native object) and has already more:
console.log(nativeObject.tagName); // undefined
console.log(hostObject.tagName); // "DIV"
as it has the all the nice DOM-attributes already there.
My Question is about a list of pitfalls (possible troubles) that can arrise if I decide to (mis)use a (host object) instead of simple (native object)?
already I am aware of this:
speed considerations (I assume that native objects are created more quickly)
memory usage consideratoins (native objects might be better here too)
Anyways I cannot see much trouble (if those considerations are not very important in a case) yet? This is the reason for the question.
I think answers to this question would be best showing/telling one potential pitfall, that is a case or situation in which it is bad or impossible to use a (host object) over a (native object). In this way this question should adhere to the SO-quality requirement of being passed on real facts and not provoking mere opinion-based-discussion.
For me, the pitfall of using a DOM-based object is that from the moment it's created it already has dozens of properties. Your document.createElement("div") object has an id property and a title property and a style property that is an object of its own, etc. If you want to use a DOM-based object to store arbitrary data, you need to be careful not to name your property something that already exists or you may get unexpected results; for example in my tests in Chrome, the code hostObject.id = null would actually cause hostObject.id to be "" rather than true null; or hostObject.id = false would cause it to be "false" (i.e. the string, not true false) for the hostObject variable defined in your code.
Try adding this to your code:
for (property in document.createElement("div"))
console.log(property);
In Chrome, I see 134 properties listed. That's a lot of landmines to potentially avoid. And beyond that, the properties differ between browsers. The same code in Firefox lists 192 properties.
I would only create a DOM object if you actually intend to use it as a DOM object. Then the properties have some purpose; otherwise they're just potential bugs in your code. Like the comments say, KISS; I mean, sure, I could decide to save the integer value 123456789 within a Date object:
myInt = new Date(123456789);
myInt.getTime(); // returns 123456789
But what's the point of that? Why not just do myInt = 123456789? Just as I wouldn't use a Date object to store integer data, don't use a DOM object to store arbitrary data.

Categories