Browsers have evolved a lot since the introduction of different alternatives and the growing development of them. They are becoming more and more useful, complex and necessary in communications nowadays.
Following the need to add new functionality or expand the existing ones comes the extensions, Javascript and HTML modules running along the loaded pages. Extensions allow us to do many things, to modify the web pages we are seeing, to send XMLHttp requests to servers outside the website’s domain, etc. This freedom comes with a big problem, security. Although all of this features need permissions to be used, very few people read the permissions requests, or understand them well enough to actually be conscious of what is going on.
We’ll create a password sniffer application to see how easy is to build one. The objective of this application is to intercept all form submissions to get the data being sent from the forms that have a password field (to avoid useless data).
First of all, we’ll start creating our application by defining our manifest.json:
1 | { |
The manifest.json file describes our application and its behavior. The important fields to our project are the following:
- Permissions: we are granting permissions to every page visited.
- Background: has the file that will be executed in the background and will receive and send (to our server) the data sniffed from the forms. The persistent field is set to false because our script will be executed on a specific event and it won’t be running all the time.
- Content_scripts: describes the files that will be injected in the pages. Our application will inject the files for our form sniffer. Due to the run_at (document_idle) field, the injection will occur when the DOM is loaded.
We now have the manifest.json file describing our application, lets get to the juicy part of it, we’ll start with the sniffer.js file, the file that will get injected into every loaded page. Here, we’ll define the event submit for all the forms in the website to the following:
1 | /* Adds the submit event to all the forms in the website */ |
The event in sniffer.js will be executed with each form submission. The form data, of the forms that include a password field, will be packed in an object and sent to the application using the chrome.extension.sendMessage function. Why are we sending the data to the application? In order to use the cross-domain XMLHttp requests that will send the data to our servers.
The receiver of the chrome.extension.sendMessage will be in the background.js file. This will be the core of our application. This file will have the event listener for the onMessage request (that will be called with the sendMessage function) and will upload the form’s data to our servers.
1 | /* Add a listener to the onMessage event */ |
Our servers will receive the data in a POST request with the fields data as a json object and the URL field as the action URL of the form.
The only thing left is to load our application to our browser, we can do that by enabling the developer mode in the extensions page and uploading the extension using the load unpacked extension button.
Chrome allows the installation of applications that aren’t from the Chrome Store only if the developer mode is enabled, this is an important security decision, but there’s a big lack of security knowledge (generally) that will result in people doing all the needed stuff to install them.