Leveling Up with osquery for Workloads: Locating local administrator accounts (windows) - Part 2
Audit and Remediation provide direct access to osquery functionality within the VMware Carbon Black Cloud console to enable security, compliance, and IT teams to query over 2,000 individual attributes across endpoints and workloads. osquery can help teams with gathering information at scale across environments for IT and help desk operations, compliance and M&A reporting, incident response, and security investigations.
Audit and Remediation allow administrators to ask questions about the environment across hardware, software, and network metadata at scale. VMware Carbon Black Cloud Workload customers also have access to the full Audit and Remediation capabilities. In this blog series, we’ll be laying out relevant queries for VMware Carbon Black Cloud Workload customers to use to achieve a variety of use cases. All queries are available in the VMware Carbon Black Cloud console, or in the VMware Carbon Black User Exchange.
Requirements:
This blog series is intended for readers that have a basic understanding of SQLite and have an osquery test environment. If neither of these things are true for you, please take a moment to read the Audit and Remediation Best Practices Guide before reading the rest of the blog.
Resources
-
https://osquery.io/schema/ (Refer to the Best Practices guide to determine the version currently installed)
-
VMware Carbon Black Query Exchange (*Requires you sign up for a free account in the VMware Carbon Black User Community unless you are a customer)
Locating Local Windows Admin Accounts
Local administrator accounts get created for a variety of reasons, from trying to overcome remote management obstacles, shadow IT, or trying to bypass security policies. If these accounts are left on endpoints, then they can be an attack vector for malicious actors or insiders. In some cases, these local administrator accounts share passwords across the enterprise, so if the credentials are compromised, they can be used for lateral movement. Help desk analysts, security teams, system administrators, and auditors need the ability to identify these accounts with speed and confidence across their Windows environments.
In this blog post, we will construct a query that allows us to identify local administrator accounts across all Windows endpoints. This query can also be modified to look for users in any other local group, such as the Remote Desktop Users group.
We are going to be making use of three different tables in this query:
-
users
-
groups
-
user_groups
Let's take a look at an example of the data in each table. Since there are a lot of columns in two of these tables, I have switched the output to line mode, and truncated the output to save space:
osquery> .mode line
osquery> select * from users;
uid = 500
gid = 544
uid_signed = 500
gid_signed = 544
username = Administrator
description = Built-in account for administering the computer/domain
directory =
shell = C:\Windows\system32\cmd.exe
uuid = S-1-5-21-2643456277-1205808317-3239813547-500
type = local
uid = 1001
gid = 544
uid_signed = 1001
gid_signed = 544
username = bit9se
description =
directory = C:\Users\bit9se
shell = C:\Windows\system32\cmd.exe
uuid = S-1-5-21-2643456277-1205808317-3239813547-1001
type = local
uid = 503
gid = 581
uid_signed = 503
gid_signed = 581
username = DefaultAccount
description = A user account managed by the system.
directory =
shell = C:\Windows\system32\cmd.exe
uuid = S-1-5-21-2643456277-1205808317-3239813547-503
type = local
uid = 501
gid = 546
uid_signed = 501
gid_signed = 546
username = Guest
description = Built-in account for guest access to the computer/domain
directory =
shell = C:\Windows\system32\cmd.exe
uuid = S-1-5-21-2643456277-1205808317-3239813547-501
type = local
osquery> select * from groups;
gid = 579
gid_signed = 579
groupname = Access Control Assistance Operators
group_sid = S-1-5-32-579
comment = Members of this group can remotely query authorization attributes and permissions for resources on this computer.
gid = 544
gid_signed = 544
groupname = Administrators
group_sid = S-1-5-32-544
comment = Administrators have complete and unrestricted access to the computer/domain
gid = 551
gid_signed = 551
groupname = Backup Operators
group_sid = S-1-5-32-551
comment = Backup Operators can override security restrictions for the sole purpose of backing up or restoring files
osquery> select * from user_groups;
uid = 500
gid = 544
uid = 1001
gid = 544
uid = 1001
gid = 555
uid = 503
gid = 581
uid = 501
gid = 546
In looking at the data in the users table there is no indication that any of the accounts are administrator accounts unless you know that 544 is the UID (user ID) for the Administrators group.
If we look at the groups table, there is no way for us to identify which accounts are in any of the groups. This is where the user_groups table comes into play, as it is a list of the UIDs associated with specific GIDs (group IDs).
To pull all of this data together in one query we are going to use two JOIN statements. Let's start out with a very basic query against the users table only using the columns that would be of interest, and focusing on local accounts:
osquery> select username, uid, gid, uuid from users where type = 'local';
username = Administrator
uid = 500
gid = 544
uuid = S-1-5-21-2643456277-1205808317-3239813547-500
username = bit9se
uid = 1001
gid = 544
uuid = S-1-5-21-2643456277-1205808317-3239813547-1001
username = DefaultAccount
uid = 503
gid = 581
uuid = S-1-5-21-2643456277-1205808317-3239813547-503
username = Guest
uid = 501
gid = 546
uuid = S-1-5-21-2643456277-1205808317-3239813547-501
username = WDAGUtilityAccount
uid = 504
gid = 513
uuid = S-1-5-21-2643456277-1205808317-3239813547-504
Now we need to use the first JOIN to the user_groups table to identify which GIDs are associated with each account. Since we are joining to a table that has the same column names as our first table, we need to identify which table and column we are using. This is easier to do using aliases:
osquery> select username, u.uid, ug.gid, uuid
...> from users as u
...> join user_groups as ug
...> using(uid)
...> where type = 'local';
username = Administrator
uid = 500
gid = 544
uuid = S-1-5-21-2643456277-1205808317-3239813547-500
username = bit9se
uid = 1001
gid = 544
uuid = S-1-5-21-2643456277-1205808317-3239813547-1001
username = bit9se
uid = 1001
gid = 555
uuid = S-1-5-21-2643456277-1205808317-3239813547-1001
username = DefaultAccount
uid = 503
gid = 581
uuid = S-1-5-21-2643456277-1205808317-3239813547-503
username = Guest
uid = 501
gid = 546
uuid = S-1-5-21-2643456277-1205808317-3239813547-501
Now we can use our second JOIN on the groups table to get the name and description for the groups:
osquery> select username, u.uid, groupname,ug.gid, description, uuid
...> from users as u
...> join user_groups as ug
...> using(uid)
...> join groups
...> using(gid)
...> where type = 'local';
username = Administrator
uid = 500
groupname = Administrators
gid = 544
description = Built-in account for administering the computer/domain
uuid = S-1-5-21-2643456277-1205808317-3239813547-500
username = bit9se
uid = 1001
groupname = Administrators
gid = 544
description =
uuid = S-1-5-21-2643456277-1205808317-3239813547-1001
username = bit9se
uid = 1001
groupname = Administrators
gid = 555
description =
uuid = S-1-5-21-2643456277-1205808317-3239813547-1001
username = DefaultAccount
uid = 503
groupname = System Managed Accounts Group
gid = 581
description = A user account managed by the system.
uuid = S-1-5-21-2643456277-1205808317-3239813547-503
username = Guest
uid = 501
groupname = Guests
gid = 546
description = Built-in account for guest access to the computer/domain
uuid = S-1-5-21-2643456277-1205808317-3239813547-501
Lastly, we need to limit the results to only include accounts in the Administrators group, which we can do by adding an additional WHERE clause:
osquery> select username, u.uid, groupname,ug.gid, description, uuid
...> from users as u
...> join user_groups as ug
...> using(uid)
...> join groups
...> using(gid)
...> where type = 'local'
...> and groupname = 'Administrators';
username = Administrator
uid = 500
groupname = Administrators
gid = 544
description = Built-in account for administering the computer/domain
uuid = S-1-5-21-2643456277-1205808317-3239813547-500
username = bit9se
uid = 1001
groupname = Administrators
gid = 544
description =
uuid = S-1-5-21-2643456277-1205808317-3239813547-1001
username = bit9se
uid = 1001
groupname = Administrators
gid = 555
description =
uuid = S-1-5-21-2643456277-1205808317-3239813547-1001
This query is available on the VMware Carbon Black User Exchange.
By changing the last query to include any other group you are interested in, you can easily query for those groups as well.
In this blog post, we have shown the power of osquery to identify local administrator accounts. Help desk analysts, security teams, system administrators, and auditors can then use the queries in this post to gain a better understanding of where these accounts persist in their Windows environments. In case you missed our last query feature, check out “Identifying and Contextualizing Windows Login Failures” here and stay tuned for our next blog.
To learn more about how Audit and Remediation capabilities can help you gather data at scale across your environments, please visit: