In a previous tutorial, we discussed gathering software inventory, including Chrome extensions.
Knowing what you have is half the battle. But once you know what you have, how do you decide what you should keep?
In general, browser extensions are super useful. Extensions like password managers and ad blockers can often increase the security of your environment.
That being said, extensions can and do request multiple permissions to access the browser and the websites being used within them, often for good reasons, and sometimes for shady reasons.
If the reasons are good, it becomes a matter of trusting the extension to be secure, and the vendor to not exploit that level of access. If the reasons are bad, it’s a good enough reason to disallow that extension in your environment.
But how would you get started inventorying Chrome extensions and their permissions using osquery?
There are three goals we’re looking to achieve with an inventory of Chrome extensions:
- Create a list of Chrome extensions
- Identify extensions with high privileges
- Identify extensions with scripts that can run on any website
With this information, we’ll be able to decide which extensions we want to allow everywhere, as well as start looking at extensions that will require extra attention or research.
If any extension is suspected of being malicious, or simply vulnerable, understanding the scope and potential impact will be much easier, as we will understand the level of permissions an attacker could achieve.
We’ll be using three osquery tables to achieve our goals. Click on each item below to see its schema.
chrome_extensions—This table contains information such as the identifier, name, version, as well as permissions the installed extensions require.
users—Since extensions are a per-user concept, we’ll need to join our results to the
userstable to know which user is using which extension on each system.
Let’s inventory the extensions, their permissions, and scripts, and see which users have them installed.
How to get a basic Chrome extension permissions inventory with osquery
Start by running this query:
SELECT u.username, extensions.name, extensions.identifier, extensions.version, extensions.permissions, extensions.optional_permissions FROM users u CROSS JOIN chrome_extensions extensions USING (uid);
This query will generate the following data, shown here in a spreadsheet for readability:
As you can see, the permissions field is quite verbose. If we decide to first drill down on permissions
*://*/*, we can add a list of filters by using
LIKE that will filter on dangerous permissions:
SELECT u.username, extensions.name, extensions.identifier, extensions.version, extensions.permissions, extensions.optional_permissions FROM users u CROSS JOIN chrome_extensions extensions USING (uid) WHERE extensions.permissions LIKE '%%' OR extensions.permissions LIKE '%tabs%' OR extensions.permissions LIKE '*%://*/*%D';
After running the query above, we now have a shorter list of extensions to worry about:
As you work down the list from the most dangerous permissions to the still dangerous but lesser ones, you can simply extend your list of filters. Then, you might want to exclude some known good extensions from the results. In this case, using the
identifier is the most reliable way. For example, the next query will exclude uBlock Origin from my results, as it is an extension I trust to access my tabs, and the Chrome Media Router, which is a built-in extension.
To make this query easier, we will use a sub-query, so we can separate the evaluation of filters on permissions from the omission of certain identifiers. This lets us filter on dangerous permissions with specific extensions allowed:
SELECT * FROM (SELECT u.username, extensions.name, extensions.identifier, extensions.version, extensions.permissions, extensions.optional_permissions FROM users u CROSS JOIN chrome_extensions extensions USING (uid) WHERE extensions.permissions LIKE '%%' OR extensions.permissions LIKE '%tabs%' OR extensions.permissions LIKE '*%://*/*%D') WHERE identifier != 'cjpalhdlnbpafiamejdnhcphjbkeiagm' AND identifier != 'pkedcjkdefgpdelpbcmbmeomcjbeemfm';
We now have a shorter list of extensions to drill into:
Once you have identified all of the permissions you want to track, and all of the extensions you have approved and want to exclude from the results, you can then configure your centralized osquery data environment to warn you when new results are seen. Be sure to keep an eye on permissions that generate a warning, but also look for URLs to critical domains.
If you use G Suite extensively, an extension could cause a serious compromise even if it only has access to Gmail, so looking for extensions that can read everything is not always sufficient.
chrome_extension_content_scripts table contains this data, but it must be joined to the
chrome_extensions table to get more basic information. That table, as you recall from the earlier examples, needs to be joined to the
users table. We will explore how to use
chrome_extension_content_scripts in a future tutorial!
At this point you should have a solid understanding of how to inventory Chrome extensions and how to review those that might be dangerous. This lets you create a list of allowed extensions, disallowed extensions, or simply to keep an eye on things. You can use this data with your mobile device management (MDM) tool to push a Chrome profile, a group policy object (GPO) on Windows, or with G Suite’s Chrome Extension Management feature.
Guillaume is a Principal Security Researcher at Uptycs. With experience as a security architect, consultant and with managing security operations, he loves to find ways to help organizations prevent attacks and reduce the noise that security and IT teams are subjected to. He believes that while it is impossible to...
Other posts you might be interested in
6 min read | July 20, 2017
Finding browser extensions in osquery [with video]Read More
5 min read | July 23, 2020
Osquery tutorial: Gathering software inventoryRead More
7 min read | December 3, 2020