Saturday, October 13, 2007

[COW] Web RAM - a JavaScript function to share safely strings

This time my COW is really strange as Web concept ... a total size of 256 bytes (seems hilarius?) to share strings inside each browser window.

This idea is not so new, I wrote JSTONE few months ago to do something similar, however it seems that JSTONE requires dedicated JSON implementation or something similar to work correctly.

Now, let me explain why I wrote this tiny function and for what it should be used for.


Random Access Memory


window.name is a string always present every time We open a window.
The cool, but not so secure, behaviour of this property is that this persists even if We change site or domain or We refresh page using F5.
While We use the same window, window name will be available, seems cool?
RAM function is capable to save a lot of informations using a Random Access strategy, where the "memory address" is created by yourself, using your personal keyword.
Both keywords and saved data can contain every kind of char excepted for \x00 one (End Of String or null char).

It's based on a sort of automatic namespace management but your keyword is not really your one but as is for libraries, everyone should use a dedicated namespace without conflicts, don't You agree?
Finally, window.name can save strings of hundred of thousand chars, I didn't find a limit for saved informations but as is for real RAM, if You turn off your PC (in this case browser window) it will be automatically resetted.


Why RAM function ?


These days I'm testing my last creation, packed.it, to find problems or to test decompression speed with big data size.
One thing I tough is that with packed code (using packed.it, packer or similar compressors), size is not the real problem as decompression CPU overload is.
I was try to find a way to cache or speed up unpack operation but every test I did failed (bad results).
That's why I created this simple function, to test clear code evaluation performances instead of runtime decompression, allowing users to unpack every kind of code 1 time each window instead of every time.
This means that during navigation in the same window, a new user will unpack code only first time but after first clear code creation procedure, You sohuld save them inside window.name and evaluate them in every other page viewed inside same browser window.
At the same time, if user will leave your page and then come back using back button it will have again code stored if external site didn't modify window.name or modify them without RAM function.
Finally, I could save an address, called for example jQuery :-) ... saving clear source and check them every time one page that use them is called:

eval(RAM("jQuery") || RAM("jQuery", function(p,a,c,k,e,d){/* ... */}));

Every link in the same window and every site viewed after this one should use same strategy to perform packed sources evaluations faster than ever because decompression will be performed only first time ... not a real solution but at least a simple way to optmize, a bit, navigation and decompression speed?

So, RAM function should be used to ... ?



  • save each kind of informations rappresented as a string (JSON as every other kind of string)

  • share common libraries between different pages / sites

  • evaluate big strings if compressor believes in RAM function



I'll try to do some test with packed.it, probably as option.
The battle is between a little overload of 256 bytes against 1 to 5 seconds for really big packed sources ... uhm ... what do You think is better?

Do I forget something? Uhm, both keywords and sources could use SOH char too (\x01) without problems but each SOH will be duplicated inside window.name and replaced before You'll read them again to preserve string as is when You get them using RAM.


<script type="text/javascript" src="RAM.js"><!--// Function RAM //--></script>
<script type="text/javascript"><!--//
eval(
/* from second time You visit this page */
RAM("my personal key") ||

/* only first time You visit this page */
RAM("my personal key", "alert('Hello World')")
);
//--></script>




Update 2007/10/15
DarkCraft sayd that NoScript doesn't allow many chars inside window.name when You change domain, reload the page or do something similar.

I wonder why NoScript guys allows few chars in window.name (someone shoud use them to save user and passwords, for example) instead of clear one ... however, RAM should work without problems with NoScript enabled browsers too, just using a try catch statement.

// RAM example for NoScript browsers
try{
eval(RAM("my lib")||"this=0")
}catch(e){
eval(RAM("my lib", (function(p,a,c,k,e,d){return 'alert("hello my lib")'})()))
};

If You use this piece of code NoScript enabled browsers will just "decompile" each time saved informations, if these contains special chars too.
Please remember that RAM goal is to believe in itself, it's quite obvious that if some malicius site/page/code replace informations or uses malicius version of common libraries RAM function should become totally insecure.

The best practice I could suggest is to use a "private mutable key":

try{
eval(RAM("jQuery-1.2.1-" + location.hostname)||"this=0")
}catch(e){
eval(RAM("jQuery-1.2.1-" + location.hostname, (function(p,a,c,k,e,d){return 'alert("hello my lib")'})()))
};

That in a session based enviroment should be something like this code:

try{
eval(RAM("jQuery-1.2.1-<?php echo session_id();?>")||"this=0")
}catch(e){
eval(RAM("jQuery-1.2.1-<?php echo session_id();?>", (function(p,a,c,k,e,d){return 'alert("hello my lib")'})()))
};

To be sure library is shared only during a valid session.
A random cookie should be good enough too but paranoia is always with us :D

Finally, in packed.it I'll add a RAM option based on project name, different each time.
These practices disable cross site library sharing but I hope one day malicious site, developers, will be banned from the Web (just a "little utopia")

No comments:

Post a Comment