cmc/cleberg.net

My personal web garden & blog.

clone: git clone https://gitbay.org/cmc/cleberg.net.git

main: content/blog/2023-09-19-audit-sql-scripts.org · raw

  1#+date:        [2023-09-19 Tue 00:00:00]
  2#+title:       SQL Scripts for Auditing User Privileges
  3#+description: SQL queries for auditing user access in Oracle, SQL Server, and MySQL.
  4#+slug:        audit-sql-scripts
  5#+filetags:    :audit:
  6
  7* Overview
  8
  9When you have to scope a database into your engagement, you may be
 10curious how to best extract the information from the database. While
 11there are numerous different methods to extract this type of
 12information, I'm going to show an example of how to gather all users and
 13privileges from three main database types: Oracle, Microsoft SQL, and
 14MySQL.
 15
 16* Oracle
 17
 18You can use the following SQL script to see all users and their
 19privileges in an Oracle database:
 20
 21#+begin_src sql
 22SELECT
 23    grantee AS "User",
 24    privilege AS "Privilege"
 25FROM
 26    dba_sys_privs
 27WHERE
 28    grantee IN (SELECT DISTINCT grantee FROM dba_sys_privs)
 29UNION ALL
 30SELECT
 31    grantee AS "User",
 32    privilege AS "Privilege"
 33FROM
 34    dba_tab_privs
 35WHERE
 36    grantee IN (SELECT DISTINCT grantee FROM dba_tab_privs);
 37#+end_src
 38
 39This script queries the =dba_sys_privs= and =dba_tab_privs= views to
 40retrieve system and table-level privileges respectively. It then
 41combines the results using =UNION ALL= to show all users and their
 42associated privileges. Please note that this method does not extract
 43information from the =dba_role_privs= table - use the method below for
 44that data.
 45
 46Please note that you might need appropriate privileges (e.g., DBA
 47privileges) to access these views, and you should exercise caution when
 48querying system tables in a production Oracle database.
 49
 50** Alternative Oracle Query
 51
 52You can also extract each table's information separately and perform
 53processing outside the database to explore and determine the information
 54necessary for the audit:
 55
 56#+begin_src sql
 57SELECT ** FROM sys.dba_role_privs;
 58SELECT ** FROM sys.dba_sys_privs;
 59SELECT ** FROM sys.dba_tab_privs;
 60SELECT ** FROM sys.dba_users;
 61#+end_src
 62
 63* Microsoft SQL
 64
 65You can use the following SQL script to see all users and their
 66privileges in a Microsoft SQL Server database
 67([[https://stackoverflow.com/a/30040784][source]]):
 68
 69#+begin_src sql
 70/*
 71Security Audit Report
 721) List all access provisioned to a sql user or windows user/group directly
 732) List all access provisioned to a sql user or windows user/group through a database or application role
 743) List all access provisioned to the public role
 75
 76Columns Returned:
 77UserName        : SQL or Windows/Active Directory user account.  This could also be an Active Directory group.
 78UserType        : Value will be either 'SQL User' or 'Windows User'.  This reflects the type of user defined for the
 79                  SQL Server user account.
 80DatabaseUserName: Name of the associated user as defined in the database user account.  The database user may not be the
 81                  same as the server user.
 82Role            : The role name.  This will be null if the associated permissions to the object are defined at directly
 83                  on the user account, otherwise this will be the name of the role that the user is a member of.
 84PermissionType  : Type of permissions the user/role has on an object. Examples could include CONNECT, EXECUTE, SELECT
 85                  DELETE, INSERT, ALTER, CONTROL, TAKE OWNERSHIP, VIEW DEFINITION, etc.
 86                  This value may not be populated for all roles.  Some built in roles have implicit permission
 87                  definitions.
 88PermissionState : Reflects the state of the permission type, examples could include GRANT, DENY, etc.
 89                  This value may not be populated for all roles.  Some built in roles have implicit permission
 90                  definitions.
 91ObjectType      : Type of object the user/role is assigned permissions on.  Examples could include USER_TABLE,
 92                  SQL_SCALAR_FUNCTION, SQL_INLINE_TABLE_VALUED_FUNCTION, SQL_STORED_PROCEDURE, VIEW, etc.
 93                  This value may not be populated for all roles.  Some built in roles have implicit permission
 94                  definitions.
 95ObjectName      : Name of the object that the user/role is assigned permissions on.
 96                  This value may not be populated for all roles.  Some built in roles have implicit permission
 97                  definitions.
 98ColumnName      : Name of the column of the object that the user/role is assigned permissions on. This value
 99                  is only populated if the object is a table, view or a table value function.
100,*/
101
102--List all access provisioned to a sql user or windows user/group directly
103SELECT
104    [UserName] = CASE princ.[type]
105                    WHEN 'S' THEN princ.[name]
106                    WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI
107                 END,
108    [UserType] = CASE princ.[type]
109                    WHEN 'S' THEN 'SQL User'
110                    WHEN 'U' THEN 'Windows User'
111                 END,
112    [DatabaseUserName] = princ.[name],
113    [Role] = null,
114    [PermissionType] = perm.[permission_name],
115    [PermissionState] = perm.[state_desc],
116    [ObjectType] = obj.type_desc,--perm.[class_desc],
117    [ObjectName] = OBJECT_NAME(perm.major_id),
118    [ColumnName] = col.[name]
119FROM
120    --database user
121    sys.database_principals princ
122LEFT JOIN
123    --Login accounts
124    sys.login_token ulogin on princ.[sid] = ulogin.[sid]
125LEFT JOIN
126    --Permissions
127    sys.database_permissions perm ON perm.[grantee_principal_id] = princ.[principal_id]
128LEFT JOIN
129    --Table columns
130    sys.columns col ON col.[object_id] = perm.major_id
131                    AND col.[column_id] = perm.[minor_id]
132LEFT JOIN
133    sys.objects obj ON perm.[major_id] = obj.[object_id]
134WHERE
135    princ.[type] in ('S','U')
136UNION
137--List all access provisioned to a sql user or windows user/group through a database or application role
138SELECT
139    [UserName] = CASE memberprinc.[type]
140                    WHEN 'S' THEN memberprinc.[name]
141                    WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI
142                 END,
143    [UserType] = CASE memberprinc.[type]
144                    WHEN 'S' THEN 'SQL User'
145                    WHEN 'U' THEN 'Windows User'
146                 END,
147    [DatabaseUserName] = memberprinc.[name],
148    [Role] = roleprinc.[name],
149    [PermissionType] = perm.[permission_name],
150    [PermissionState] = perm.[state_desc],
151    [ObjectType] = obj.type_desc,--perm.[class_desc],
152    [ObjectName] = OBJECT_NAME(perm.major_id),
153    [ColumnName] = col.[name]
154FROM
155    --Role/member associations
156    sys.database_role_members members
157JOIN
158    --Roles
159    sys.database_principals roleprinc ON roleprinc.[principal_id] = members.[role_principal_id]
160JOIN
161    --Role members (database users)
162    sys.database_principals memberprinc ON memberprinc.[principal_id] = members.[member_principal_id]
163LEFT JOIN
164    --Login accounts
165    sys.login_token ulogin on memberprinc.[sid] = ulogin.[sid]
166LEFT JOIN
167    --Permissions
168    sys.database_permissions perm ON perm.[grantee_principal_id] = roleprinc.[principal_id]
169LEFT JOIN
170    --Table columns
171    sys.columns col on col.[object_id] = perm.major_id
172                    AND col.[column_id] = perm.[minor_id]
173LEFT JOIN
174    sys.objects obj ON perm.[major_id] = obj.[object_id]
175UNION
176--List all access provisioned to the public role, which everyone gets by default
177SELECT
178    [UserName] = '{All Users}',
179    [UserType] = '{All Users}',
180    [DatabaseUserName] = '{All Users}',
181    [Role] = roleprinc.[name],
182    [PermissionType] = perm.[permission_name],
183    [PermissionState] = perm.[state_desc],
184    [ObjectType] = obj.type_desc,--perm.[class_desc],
185    [ObjectName] = OBJECT_NAME(perm.major_id),
186    [ColumnName] = col.[name]
187FROM
188    --Roles
189    sys.database_principals roleprinc
190LEFT JOIN
191    --Role permissions
192    sys.database_permissions perm ON perm.[grantee_principal_id] = roleprinc.[principal_id]
193LEFT JOIN
194    --Table columns
195    sys.columns col on col.[object_id] = perm.major_id
196                    AND col.[column_id] = perm.[minor_id]
197JOIN
198    --All objects
199    sys.objects obj ON obj.[object_id] = perm.[major_id]
200WHERE
201    --Only roles
202    roleprinc.[type] = 'R' AND
203    --Only public role
204    roleprinc.[name] = 'public' AND
205    --Only objects of ours, not the MS objects
206    obj.is_ms_shipped = 0
207ORDER BY
208    princ.[Name],
209    OBJECT_NAME(perm.major_id),
210    col.[name],
211    perm.[permission_name],
212    perm.[state_desc],
213    obj.type_desc--perm.[class_desc]
214#+end_src
215
216* MySQL
217
218You can use the following SQL script to see all users and their
219privileges in a MySQL database:
220
221#+begin_src sh
222mysql -u root -p
223#+end_src
224
225Find all users and hosts with access to the database:
226
227#+begin_src sql
228SELECT ** FROM information_schema.user_privileges;
229#+end_src
230
231This script retrieves user information and their associated
232database-level privileges from the =information_schema.user_privileges=
233table in MySQL. It lists various privileges such as SELECT, INSERT,
234UPDATE, DELETE, CREATE, and more for each user and database combination.
235
236Please note that you may need appropriate privileges (e.g., =SELECT=
237privileges on =information_schema.user_privileges=) to access this
238information in a MySQL database. Additionally, some privileges like
239GRANT OPTION, EXECUTE, EVENT, and TRIGGER may not be relevant for all
240users and databases.
241
242** Alternative MySQL Query
243
244You can also grab individual sets of data from MySQL if you prefer to
245join them after extraction. I have marked the queries below with
246=SELECT ...= and excluded most =WHERE= clauses for brevity. You should
247determine the relevant privileges in-scope and query for those
248privileges to reduce the length of time to query.
249
250#+begin_src sql
251-- Global Permissions
252SELECT ... FROM mysql.user;
253
254-- Database Permissions
255SELECT ... FROM mysql.db
256WHERE db = @db_name;
257
258-- Table Permissions
259SELECT ... FROM mysql.tables
260WHERE db = @db_name;
261
262-- Column Permissions
263SELECT ... FROM mysql.columns_priv
264WHERE db = @db_name;
265
266-- Password Configuration
267SHOW GLOBAL VARIABLES LIKE 'validate_password%';
268SHOW VARIABLES LIKE 'validate_password%';
269#+end_src