Unfortunately Firefox is not offering much control over the privileges of the script execution: in chrome script has all the privileges. netscape.security.PrivilegeManager.disablePrivilege is not working and, correct me if I'm wrong, all you have as alternative is to run the code in the sandbox, where you have limited privileges and again no way to control them. I would much more prefere to have sandbox privileges by default and ask for more privileges I require.
Enough ranting and lets show the code. Here is the old version of the code:
var scriptCollection = document.getElementsByTagName("script");
var reader = new httpReader(scriptCollection[scriptCollection.length - 1].src);
function evaluateJs(aReader){
if(aReader && aReader.mData) {
eval(aReader.mData);
}
}
reader.AsyncLoad(bind(evaluateJs, this, reader));
Here is improved script to execute this code in the sandbox:
var scriptCollection = document.getElementsByTagName("script");
var reader = new httpReader(scriptCollection[scriptCollection.length - 1].src);
function runInSandbox(scriptToEval){
//this line is for testing purposes this privilege will be enabled in chrome anyway
//netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var safewin = new XPCNativeWrapper(window);
var sandbox = Components.utils.Sandbox(safewin);
sandbox.window = safewin;
sandbox.document = sandbox.window.document;
sandbox.__proto__ = safewin;
//add jsonp method to the safe window
for(var prop in window){
if(typeof window[prop] == "function"
&& prop.substring(0, 5) == "jsonp"){
sandbox.window[prop] = window[prop];
break;
}
}
Components.utils.evalInSandbox(scriptToEval, sandbox);
}
function evaluateJs(aReader){
if(aReader && aReader.mData) {
//eval(aReader.mData);
runInSandbox(aReader.mData);
}
}
reader.AsyncLoad(bind(evaluateJs, this, reader));
Since after wrapping the window the JSONP function is missing we are adding it by cycling through all the properties of the original window and upon finding the right function we are adding it to the safe window. We know that jQuery created the JSONP function so it is pretty safe to do this. After that evalInSandbox can be called and we have our JSONP function executed in sandbox without possiblity to do any damage.
To illustrate what's been shown so far I will create a couple of simple tests.
Simplistic injection testing
First of all to note that all of this I am showing is done by opening XUL window in Firefox, feel free to wrap it up into extension and test it properly.Lets prepare our testing ground for exploring vulnerabilities arising. The full source code is here. Please put injection*.js files somewhere on your local web server if you have it so you can access it easily. They are simulating JSONP scripts injection and basically they are simulating what some malicious server might serve to our extension.
The injection1.js is simply showing alert window so we know that we have access to injection files.
Injection2.js is reading C:\temp\security.txt file from the disk (you create some test file) and showing its contents. It is there just to prove the point, it might easily delete your system files if you are running Firefox as admin, or read your Gmail username and password and send it to some 3rd party via web service, etc; the point is it can do anything if called from chrome.
Injection3.js is trying to add click event handler to existing window and attempt to make malicious script pass boundaries of the sandbox.
Injection4.js is using some function we deliberately made unsafe to make the point that even when running in sandbox we have to keep in mind what we are doing and that we might cause voulnerabilities ourselves.
The securityText.xul has 5 buttons and they are doing the following stuff:
Simple test - loads injection1.js - shows alert 'injection', if it shows alert we are injecting scripts as expected
Voulnerability! - executes Injection2.js in chrome and is reading content of C:\temp\security.txt
Safe 1! - executes Injection2.js in sandbox - showing that it will not read the file
Safe ! - on click changes txt to still safe - we are attaching malicious code to click event of the button, but since it is executed on the wrapper it will not read the file
Safe (not really) ! - on click will change the text to Unsafe! since it will use voulnerable function we added to safe window and will actually add malicious code to click event of the button. Click on it again and it will read the contents of the file.
To change the location of the injection files change line 2: var scripturl = 'http://localhost/' + scriptFile; to wherever you put the script files. To change what file is read from the local disk find c:\\\\temp\\\\security.txt in injection scripts and change them to whatever file you want to read.
Hopefuly this helps.
Comments