Breaking Apart Blockade — Part One

Brandon Dixon
Blockade.io
Published in
5 min readMar 20, 2017

If you’re reading this, then chances are you already know what Blockade does, but may not know how it functions. Fortunately, all the code that powers Blockade is open source and freely available. In this post, I want to dive into the one specific piece of Blockade — the browser extension. Keep an eye out for part two in which I go over the cloud node.

Reference diagram showing how Blockade works

Blockade’s purpose is to block malicious resources from being loaded inside of a browser, so what better way to facilitate that power then to use a browser extension. Both Firefox (help us make this) and Chrome expose extremely powerful Javascript APIs to developers that make interacting with the core pieces of the browser a breeze.

Blockade takes advantages of the following API calls for major functionality:

Inspection and Blocking (chrome.webRequest)

Snippet of code from the request inspection

If blocking is all you care about, look no further. Contained within the core logic of Blockade is a listener for webRequest.onBeforeRequest. Any networking call (sans websockets), dependent or otherwise, will run through this listener and provide details about the request including URL, type of request, tab ID, frame ID and method.

As you would expect, thousands of calls will run through this listener a day and so it needs to be performant. Blockade operates only on IP addresses and fully qualified domain names, so step one is taking the URL and loading it within an “A” element to extract the hostname. Once obtained, the value is hashed using client-side MD5 library and checked against the Blockade database (in-memory or localstorage).

Example warning page a user would see if a block occured

If no match is found, our inspection ends here and the request continues otherwise, it’s noted and blocked. In order to provide a good user experience, users are redirected to a local page within the extension that outlines why the block happened with some additional metadata.

Scheduling (chrome.alarms)

Snippet of code that outlines the Chrome alarm processing

In order to communicate back with the cloud nodes, Blockade employees two reoccurring jobs (alarms), one for database updates and the other for event syncing.

Blockade options page showing the different cloud nodes that have been configured

When performing the database update, Blockade consults a local configuration file that lists all the associated cloud nodes with the browser. For each cloud node, Blockade fetches a copy of the indicator database, merges it into an in-memory data structure and then attempts to save it locally. If the database can’t be saved locally due to size limitations, a configuration flag is marked to ensure an initial load is performed each time the browser is restarted.

Besides blocking traffic and generating a warning page, Blockade also capture details about the malicious event and saves them to a local structure. Every minute, these events are processed and sent to the corresponding cloud node (part of the configuration) for a deeper investigation by analysts.

Feedback Loop (chrome.contextMenus)

Context menu for Blockade to send indicators to a cloud node

Without a blocking capability, Blockade wouldn’t be much use, but without infrastructure to block, we wouldn’t have anything at all. At the start of this post, we showed the reference architecture of Blockade which makes mention of several “analysts” feeding in intelligence. In order to facilitate this feedback loop, we’ve published an analyst toolbench. Unfortunately, using this tool typically means switching over to the command line, inputting data and then sending it along.

Code used to create context menus based on cloud node configurations

Using the “contextMenu.create” API, we built a small right-click context menu for users to send highlighted indicators directly from the browser to a cloud node of their choice. In order for this to function, users need to associate their username and API key for each cloud node they have configured.

Warnings and Insights (chrome.notifications)

During the testing of early versions of Blockade, it was difficult to tell if the extension was working at all. It would get installed, configure itself and start blocking resources, but there was no way to see that happening without enabling the Chrome Debug Inspector window. As critical as it is to get the blocking correct, it’s almost just as critical to ensure the user feels confident in the tool.

Example of a notification pop-up when a block occurs

Blockade uses the notifications.create API in order to generate desktop alerts that can easily be seen by the user. For major events like database syncing, errors or blocking of malicious items, users will automatically see a pop-up message with detailed information.

Globalization (chrome.i18n)

Sample messages file outlining Spanish strings to use in Blockade

What good is a tool if you can’t read it or understand what it does? During my years of doing incident response and threat investigations, I’ve interacted with people from all over the world, both researchers and victims. Many people speak or read English, but it’s generally not their first language. Chrome’s i18n APIs make it possible to easily translate the strings found within the extension and show them in another language.

At the time of this writing, Blockade is currently supported in 10 languages (help us out), many of which are part of the most spoken/read in the world. In order to achieve this, each string from the extension is loaded into a “messages.json” file where it’s mapped to a key which includes a message, description and optional set of placeholders. Inside of the core code, keys are referenced against the configured browser language and then displayed within the application.

--

--

Brandon Dixon
Blockade.io

Founder of @BlockadeIO, PDF X-RAY, and @PassiveTotal. Partner and developer for @TheNinjaJobs. VP of Strategy for @RiskIQ. Roaster at @SplitKeyCoffee.