UserJS. Part 3: Security
This article describes the danger of some userjs tricks and how to deal with this danger.
Other articles in the series:
The danger of this technology is obvious. As soon as you allow access from some address to advanced features (for example, working with the clipboard), as all scripts from this address can use the advanced features for their own purposes (for example, sending the contents of the buffer to the site - suddenly there is a password).
The solution is to allow access to only one address - “http://0.0.0.0/”, open a frame with this address and perform all actions through XDM. The disadvantage is that all calls become asynchronous. But why not do it for safety. Yes, and there is some plus in this - the scripts on the page do not hang in anticipation of a long synchronous call.
Now you need to secure XDM.
Any script on the page can find the iframe and send it a message. Just know the message format. To find out is not a problem if userjs is posted on the network. Yes, even if userjs is written by you and for yourself, it is often easy to guess the format.
So, the task is to make the format unreadable. To do this, you need:
But even this is not enough to ensure security.
Unfortunately, userjs run in the context of the page. This means that all modifications of objects by scripts from the page are reflected on userjs.
Suppose password verification in userjs is as follows:
Then the script on the page can execute:
and get a password!
It is necessary to save the functions used in critical places of userjs:
Other articles in the series:
Liveconnect
The danger of this technology is obvious. As soon as you allow access from some address to advanced features (for example, working with the clipboard), as all scripts from this address can use the advanced features for their own purposes (for example, sending the contents of the buffer to the site - suddenly there is a password).
The solution is to allow access to only one address - “http://0.0.0.0/”, open a frame with this address and perform all actions through XDM. The disadvantage is that all calls become asynchronous. But why not do it for safety. Yes, and there is some plus in this - the scripts on the page do not hang in anticipation of a long synchronous call.
Now you need to secure XDM.
Xdm
Any script on the page can find the iframe and send it a message. Just know the message format. To find out is not a problem if userjs is posted on the network. Yes, even if userjs is written by you and for yourself, it is often easy to guess the format.
So, the task is to make the format unreadable. To do this, you need:
- generate a password for each user;
- Add to the beginning of each message
- Use the "BeforeEvent.message" event so that we are the first to know about the message;
- process only messages with a suitable password;
- use the "Event.preventDefault" function to prevent the script from receiving messages on the page.
We preserve functions
But even this is not enough to ensure security.
Unfortunately, userjs run in the context of the page. This means that all modifications of objects by scripts from the page are reflected on userjs.
Suppose password verification in userjs is as follows:
if (ev.data.substring (0, password.length) == password) {...}
Then the script on the page can execute:
String.prototype.substring = function (start, len) {alert (this); }
and get a password!
It is necessary to save the functions used in critical places of userjs:
// At the very beginning of the script. var functionCall = Function.prototype.call; var stringSubstring = String.prototype.substring; // In the event handler. stringSubstring.call = functionCall; if (stringSubstring.call (ev.data, 0, password.length) == password) {...}