Related
Intro
This topic has been the bane of many questions and answers on StackOverflow -and in many other tech-forums; however, most of them are specific to exact conditions and even worse: "over-all" security in script-injection prevention via dev-tools-console, or dev-tools-elements or even address-bar is said to be "impossible" to protect. This question is to address these issues and serve as current and historical reference as technology improves -or new/better methods are discovered to address browser security issues -specifically related to script-injection attacks.
Concerns
There are many ways to either extract -or manipulate information "on the fly"; specifically, it's very easy to intercept information gathered from input -to be transmitted to the server - regardless of SSL/TLS.
intercept example
Have a look here
Regardless of how "crude" it is, one can easily use the principle to fabricate a template to just copy+paste into an eval() in the browser console to do all kinds of nasty things such as:
console.log() intercepted information in transit via XHR
manipulate POST-data, changing user-references such as UUIDs
feed the target-server alternative GET (& post) request information to either relay (or gain) info by inspecting the JS-code, cookies and headers
This kind of attack "seems" trivial to the untrained eye, but when highly dynamic interfaces are in concern, then this quickly becomes a nightmare -waiting to be exploited.
We all know "you can't trust the front-end" and the server should be responsible for security; however - what about the privacy/security of our beloved visitors? Many people create "some quick app" in JavaScript and either do not know (or care) about the back-end security.
Securing the front-end as well as the back-end would prove formidable against an average attacker, and also lighten the server-load (in many cases).
Efforts
Both Google and Facebook have implemented some ways of mitigating these issues, and they work; so it is NOT "impossible", however, they are very specific to their respective platforms and to implement requires the use of entire frameworks plus a lot of work -only to cover the basics.
Regardless of how "ugly" some of these protection mechanisms may appear; the goal is to help (mitigate/prevent) security issues to some degree, making it difficult for an attacker. As everybody knows by now: "you cannot keep a hacker out, you can only discourage their efforts".
Tools & Requirements
The goal is to have a simple set of tools (functions):
these MUST be in plain (vanilla) javascript
together they should NOT exceed a few lines of code (at most 200)
they have to be immutable, preventing "re-capture" by an attacker
these MUST NOT clash with any (popular) JS frameworks, such as React, Angular, etc
does NOT have to be "pretty", but readable at least, "one-liners" welcome
cross-browser compatible, at least to a good percentile
Runtime Reflection / Introspection
This is a way to address some of these concerns, and I don't claim it's "the best" way (at all), it's an attempt.
If one could intercept some "exploitable" functions and methods and see if "the call" (per call) was made from the server that spawned it, or not, then this could prove useful as then we can see if the call came "from thin air" (dev-tools).
If this approach is to be taken, then first we need a function that grabs the call-stack and discard that which is not FUBU (for us by us). If the result of this function is empty, hazaa! - we did not make the call and we can proceed accordingly.
a word or two
In order to make this as short & simple as possible, the following code examples follow DRYKIS principles, which are:
don't repeat yourself, keep it simple
"less code" welcomes the adept
"too much code & comments" scare away everybody
if you can read code - go ahead and make it pretty
With that said, pardon my "short-hand", explanation will follow
first we need some constants and our stack-getter
const MAIN = window;
const VOID = (function(){}()); // paranoid
const HOST = `https://${location.host}`; // if not `https` then ... ?
const stak = function(x,a, e,s,r,h,o)
{
a=(a||''); e=(new Error('.')); s=e.stack.split('\n'); s.shift(); r=[]; h=HOSTPURL; o=['_fake_']; s.forEach((i)=>
{
if(i.indexOf(h)<0){return}; let p,c,f,l,q; q=1; p=i.trim().split(h); c=p[0].split('#').join('').split('at ').join('').trim();
c=c.split(' ')[0];if(!c){c='anon'}; o.forEach((y)=>{if(((c.indexOf(y)==0)||(c.indexOf('.'+y)>0))&&(a.indexOf(y)<0)){q=0}}); if(!q){return};
p=p[1].split(' '); f=p[0]; if(f.indexOf(':')>0){p=f.split(':'); f=p[0]}else{p=p.pop().split(':')}; if(f=='/'){return};
l=p[1]; r[r.length]=([c,f,l]).join(' ');
});
if(!isNaN(x*1)){return r[x]}; return r;
};
After cringing, bare in mind this was written "on the fly" as "proof of concept", yet tested and it works. Edit as you whish.
stak() - short explanation
the only 2 relevant arguments are the 1st 2, the rest is because .. laziness (short answer)
both arguments are optional
if the 1st arg x is a number then e.g. stack(0) returns the 1st item in the log, or undefined
if the 2nd arg a is either a string -or an array then e.g. stack(undefined, "anonymous") allows "anonymous" even though it was "omitted" in o
the rest of the code just parses the stack quickly, this should work in both webkit & gecko -based browsers (chrome & firefox)
the result is an array of strings, each string is a log-entry separated by a single space as function file line
if the domain-name is not found in a log-entry (part of filename before parsing) then it won't be in the result
by default it ignores filename / (exactly) so if you test this code, putting in a separate .js file will yield better results than in index.html (typically) -or whichever web-root mechanism is used
don't worry about _fake_ for now, it's in the jack function below
now we need some tools
bore() - get/set/rip some value of an object by string reference
const bore = function(o,k,v)
{
if(((typeof k)!='string')||(k.trim().length<1)){return}; // invalid
if(v===VOID){return (new Function("a",`return a.${k}`))(o)}; // get
if(v===null){(new Function("a",`delete a.${k}`))(o); return true}; // rip
(new Function("a","z",`a.${k}=z`))(o,v); return true; // set
};
bake() - shorthand to harden existing object properties (or define new ones)
const bake = function(o,k,v)
{
if(!o||!o.hasOwnProperty){return}; if(v==VOID){v=o[k]};
let c={enumerable:false,configurable:false,writable:false,value:v};
let r=true; try{Object.defineProperty(o,k,c);}catch(e){r=false};
return r;
};
bake & bore - rundown
These are failry self-explanatory, so, some quick examples should suffice
using bore to get a property: console.log(bore(window,"XMLHttpRequest.prototype.open"))
using bore to set a property: bore(window,"XMLHttpRequest.prototype.open",function(){return "foo"})
using bore to rip (destroy carelessly): bore(window,"XMLHttpRequest.prototype.open",null)
using bake to harden an existing property: bake(XMLHttpRequest.prototype,'open')
using bake to define a new (hard) property: bake(XMLHttpRequest.prototype,'bark',function(){return "woof!"})
intercepting functions and constructions
Now we can use all the above to our advantage as we devise a simple yet effective interceptor, by no means "perfect", but it should suffice; explanation follows:
const jack = function(k,v)
{
if(((typeof k)!='string')||!k.trim()){return}; // invalid reference
if(!!v&&((typeof v)!='function')){return}; // invalid callback func
if(!v){return this[k]}; // return existing definition, or undefined
if(k in this){this[k].list[(this[k].list.length)]=v; return}; //add
let h,n; h=k.split('.'); n=h.pop(); h=h.join('.'); // name & holder
this[k]={func:bore(MAIN,k),list:[v]}; // define new callback object
bore(MAIN,k,null); let f={[`_fake_${k}`]:function()
{
let r,j,a,z,q; j='_fake_'; r=stak(0,j); r=(r||'').split(' ')[0];
if(!r.startsWith(j)&&(r.indexOf(`.${j}`)<0)){fail(`:(`);return};
r=jack((r.split(j).pop())); a=([].slice.call(arguments));
for(let p in r.list)
{
if(!r.list.hasOwnProperty(p)||q){continue}; let i,x;
i=r.list[p].toString(); x=(new Function("y",`return {[y]:${i}}[y];`))(j);
q=x.apply(r,a); if(q==VOID){return}; if(!Array.isArray(q)){q=[q]};
z=r.func.apply(this,q);
};
return z;
}}[`_fake_${k}`];
bake(f,'name',`_fake_${k}`); bake((h?bore(MAIN,h):MAIN),n,f);
try{bore(MAIN,k).prototype=Object.create(this[k].func.prototype)}
catch(e){};
}.bind({});
jack() - explanation
it takes 2 arguments, the first as string (used to bore), the second is used as interceptor (function)
the first few comments explain a bit .. the "add" line simply adds another interceptor to the same reference
jack deposes an existing function, stows it away, then use "interceptor-functions" to replay arguments
the interceptors can either return undefined or a value, if no value is returned from any, the original function is not called
the first value returned by an interceptor is used as argument(s) to call the original and return is result to the caller/invoker
that fail(":(") is intentional; an error will be thrown if you don't have that function - only if the jack() failed.
Examples
Let's prevent eval from being used in the console -or address-bar
jack("eval",function(a){if(stak(0)){return a}; alert("having fun?")});
extensibility
If you want a DRY-er way to interface with jack, the following is tested and works well:
const hijack = function(l,f)
{
if(Array.isArray(l)){l.forEach((i)=>{jack(i,f)});return};
};
Now you can intercept in bulk, like this:
hijack(['eval','XMLHttpRequest.prototype.open'],function()
{if(stak(0)){return ([].slice.call(arguments))}; alert("gotcha!")});
A clever attacker may then use the Elements (dev-tool) to modify an attribute of some element, giving it some onclick event, then our interceptor won't catch that; however, we can use a mutation-observer and with that spy on "attribute changes". Upon attribute-change (or new-node) we can check if changes were made FUBU (or not) with our stak() check:
const watchDog=(new MutationObserver(function(l)
{
if(!stak(0)){alert("you again! :D");return};
}));
watchDog.observe(document.documentElement,{childList:true,subtree:true,attributes:true});
Conclusion
These were but a few ways of dealing with a bad problem; though I hope someone finds this useful, and please feel free to edit this answer, or post more (or alternative/better) ways of improving front-end security.
What kind of programming technique am I applying when I call an Object inside a Object to extend the object?
On my Job, we have a rule that no JS file may have more 50 lines. So when we have an very large Object we separate the code on new child objects but work as single Object:
function ObjetoA(parent){
parent.showMessage() = function () {
console.log('HOLA MUNDO');
}
}
function Objeto(){
new ObjectoA(this); //this one
this.sayHiAgain() = function () {
console.log('HOLA MUNDO OTRA VEZ');
}
}
let Prueba = new Objecto();
Prueba.showMessage();// it works
Let's see what's going on:
When you call Objeto(), the code new ObjetoAA(this) is run.
Now, ObjetoAA(parent) is run, which sets the property showMessage on parent. This property is a function. So now the Objecto has a function property showMessage.
I don't think there's any particular name for this pattern in the way that you've implemented it. It's just... using objects. I will say that it's an inventive way to extend/modify/split/compose a class. It's sort of simulating a mixin.
But it shouldn't be necessary: look at the gymnastics you've had to go through just to meet an arbitrary line count limit. Did it improve your productivity? Did it improve the readability and maintainability of your code? Nope.
Some limit probably makes sense: nobody wants to scan through 30,000 lines of JavaScript in a single file (at least, not the unminified version); but 50 is a very, very small limit. I recommend that you push back on this policy if you can.
When converting an Applet with the GWT framework I stumbled over this piece of code, where the author finds out the length of the array imageNames in a loop until an out-of-bounds exception occurs. It worked in the Applet, but not in GWT! After GWT compile the browser loops and does not show a reaction. Replacing Exception by JavaScriptException does not help.
boolean error=false;
int n_img = -1;
String tmp;
String[] imageNames;
...
while (!error) {
try {
tmp = imageNames[(++n_img)];
} catch (Exception e) {
error = true;
}
}
Do you have any idea, how to catch the out-of-bounds-exception in GWT?
This is one of the "shortcomings" of GWT - in the name of performance, extra emulation is not added to solve what should be an entirely avoidable bug. This is one of the most overt examples though.
First, recall that JS, for better or worse, is totally okay with you assigning values to indexes in Arrays that it may not have room for - you can use this to make a sparse array by skipping far past the end of the array, you can even assign to negative indexes.
On top of that Array feature, the Java array is implemented, and rather than read the expression array[n] and rewrite it to check n against the length before assigning (requiring two more checks for each read or write), it leaves it as-is.
And, since typically array operations like this are in a loop (such as in your code), this change would make every step through the loop faster, since it is trivial to do the bounds check as part of the loop condition.
And, typically Java users aren't writing array code on a regular basis, but leaning on ArrayList or the like - which does do these checks (though they can be disabled or reduced to improve runtime performance).
One more reason this isn't so bad: Sometimes you'd like to write in Java, and expect (not unreasonably) that you are actually acting on JS output. This allows for tricks like this:
array[array.length] = item;
to grow the array with each item. Obviously will fail in a JVM, but this is natural code to write in JS.
Finally, unless I'm very much mistaken, that isn't even a very optimized way to write that loop, even if throwing and catching that exception is cheaper than just doing a < check each step of the loop - we're still checking if !error is true each step! Instead, just make the loop run forever, and actually exit it, instead of requiring an additional boolean to track what the exception already tracks for you:
// just like the code in the question, do not do this,
// this is just an example of how to get "too clever"
try {
while (true) {
tmp = imageNames[(++n_img)];
}
catch (Exception ignore) {
// do nothing, something "exceptional" but totally expected has occurred
}
So, thank you for the comment and the explaining answer. It will help me in further development. I now changed the faulty loop this way
while (!error) {
try {
tmp = this.imageNames[(++n_img)];
error=(n_img==imageNames.length); // correct severe bug
} catch (Exception e) {
error = true;
}
}
I'm coding a function that takes an object and a projection to know on which field it has to work.
I'm wondering if I should use a string like this :
const o = {
a: 'Hello There'
};
function foo(o, str) {
const a = o[str];
/* ... */
}
foo(o, 'a');
Or with a function :
function bar(o, proj) {
const a = proj(o);
/* ... */
}
bar(o, o => o.a);
I think V8 is creating classes with my javascript objects. If I use a string to access dynamically a field, will it be still able to create a class with my object and not a hashtable or something else ?
V8 developer here. The answer to "which pattern should I use?" is probably "it depends". I can think of scenarios where the one or the other would (likely) be (a bit) faster, depending on your app's behavior. So I would suggest that you either try both (in real code, not a microbenchmark!) and measure yourself, or simply pick whichever you prefer and/or makes more sense in the larger context, and not worry about it until profiling shows that this is an actual bottleneck that's worth spending time on.
If the properties are indeed known at the call site, then the fastest option is probably to load the property before the call:
function baz(o, str, a) {
/* ... */
}
baz(o, "a", o.a);
I realize that if things actually were this simple, you probably wouldn't be asking this question; if that assumption is true then this is a great example for how simplifications in microbenchmarks can easily change what the right answer is.
The answer to the classes question is that this decision has no impact on how V8 represents your objects under the hood -- that mostly depends on how you modify your objects, not on how you read from them. Also, for the record:
every object has a "hidden class"; whether or not it uses hash table representation is orthogonal to that
whether hash table mode or shape-tracking mode is better for any given object is one of the things that depend on the use case, which is precisely why both modes exist. I wouldn't worry too much about it, unless you know (from profiling) that it happens to be a problem in your case (more often than not, V8's heuristics get it right; manual intervention is rarely necessary).
I am basically quite sure this pattern must exist and possess a name... for now I will call it "gate pattern"...
Here it is:
In my webpage's javascript, I have to trigger various asynchronous processes. Let's not discuss how trully async js is, but anyway I have to trigger 2 or 3 AJAX calls, must be sure, the UI build-up has finished, and so on.
Only then, when all these processes have finished, I want to do run a certain function. And precisely once.
Example
1: cropStore loaded()
2: resizeEvent()
3: productStore loaded()
The Pattern:
At the end of every (sucessful) Ajax-load-callback, the end of the GUI construction routine, etc... I set a respective flag from false to true and call gatedAction()
onEvent( 'load',
{
.... // whatever has to happen in response to cropStored, resized, etc...
// lastly:
f1 = true; //resp f2, f3, ...
gatedAction();
}
Gate will check the flags, return if any flag is still unset, only calling the target function, if all flags (or as I call them: gates) are open. If all my async pre-conditions call gatedAction() exactly once, I hope I can be sure, the actual targetFunction is called exactly once().
gatedAction ()
{
// Gate
if ( ! f1) return;
if ( ! f2) return;
if ( ! f3) return;
// actual Action ( <=> f1==f2==f3==true )
targetFunction();
}
In practice it works reliably. On a side-note: I think java-typical (not js-typical) synchronization/volatile concerns can be ignored, because javascript is not truly multithreading. Afaik a function is never stopped in the middle of it, just to grant another javascript function in the same document run-time...
So, anyone, is there a name for this? :-)
I need this pattern actually quite often, especially with complex backend UIs.. (and yes, I think, I will turn the above butt-ugly implementation into a more reusable javascript... With a gates array and a target function.)
It sounds like Balking pattern to me.
It is similar to the Rendezvous pattern, although that pattern is generally used in the context of multithreaded real-time systems.
I have no idea, if your pattern has a special name, but it seems equivalent to just using a counting semaphore, which blocks the thread, which started all those other actions, until they all made a V-invocation. Of course, there are no threads and semaphores in JavaScript, but instead of using many boolean variables you could use just one integer for counting.
In addition to the actual answer to your question, you might be interested in the Rx framework for Javascript. It's a port of the .NET version and allows you to compose events, so you don't have to work with tons of flag variables. It's meant for this sort of thing.
http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx