PluginProbe ʕ •ᴥ•ʔ
Advanced Access Manager – Access Governance for WordPress / trunk
Advanced Access Manager – Access Governance for WordPress vtrunk
6.8.4 6.8.5 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13 6.9.14 6.9.15 6.9.16 6.9.17 6.9.18 6.9.19 6.9.2 6.9.20 6.9.21 6.9.22 6.9.23 6.9.24 6.9.25 6.9.26 6.9.27 6.9.28 6.9.29 6.9.3 6.9.30 6.9.31 6.9.32 6.9.33 6.9.34 6.9.35 6.9.36 6.9.37 6.9.38 6.9.39 6.9.4 6.9.41 6.9.42 6.9.43 6.9.44 6.9.45 6.9.46 6.9.47 6.9.48 6.9.49 6.9.5 6.9.51 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.0-alpha.6 7.0.0-alpha.7 7.0.0-beta.1 7.0.0-rc1 7.0.0-rc2 7.0.0-rc3 7.0.1 7.0.10 7.0.11 7.0.2 7.0.3 7.0.4 7.0.5 7.0.6 7.0.7 7.0.8 7.0.9 7.1.0 7.1.1 trunk 3.0 4.0 4.0.1 4.1 4.2 4.3 4.4 4.4.1 4.5 4.6 4.6.1 4.6.2 4.7 4.7.1 4.7.2 4.7.5 4.7.6 4.8 4.8.1 4.9 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.5.1 4.9.5.2 5.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1 5.1.1 5.10 5.11 5.2 5.2.1 5.2.5 5.2.6 5.2.7 5.3 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.4 5.4.1 5.4.2 5.4.3 5.4.3.1 5.4.3.2 5.5 5.5.1 5.5.2 5.6 5.6.1 5.6.1.1 5.7 5.7.1 5.7.2 5.7.3 5.8 5.8.1 5.8.2 5.8.3 5.9 5.9.1 5.9.1.1 5.9.2 5.9.2.1 5.9.3 5.9.4 5.9.5 5.9.6 5.9.6.1 5.9.6.2 5.9.6.3 5.9.7 5.9.7.1 5.9.7.2 5.9.7.3 5.9.8 5.9.8.1 5.9.9 5.9.9.1 6.0.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.1.0 6.1.1 6.2.0 6.2.1 6.2.2 6.3.0 6.3.1 6.3.2 6.3.3 6.4.0 6.4.1 6.4.2 6.4.3 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.6.0 6.6.1 6.6.2 6.6.3 6.6.4 6.7.0 6.7.1 6.7.2 6.7.3 6.7.4 6.7.5 6.7.6 6.7.7 6.7.8 6.7.9 6.8.0 6.8.1 6.8.2 6.8.3
advanced-access-manager / application / Audit / HighPrivilegeUserCountCheck.php
advanced-access-manager / application / Audit Last commit date
AuditCheckTrait.php 1 year ago CoreUserRoleOptionIntegrityCheck.php 1 year ago EditableFileSystemCheck.php 7 months ago ElevatedCoreRoleCheck.php 7 months ago EmptyUnusedRoleCheck.php 7 months ago HighPrivilegeContentModeratorCheck.php 7 months ago HighPrivilegeOrElevatedUserCheck.php 7 months ago HighPrivilegeRoleCheck.php 7 months ago HighPrivilegeUserCountCheck.php 7 months ago RestfulAutoDiscoverEndpointCheck.php 7 months ago RoleCapabilityNamingConventionCheck.php 7 months ago RoleIntegrityCheck.php 7 months ago RoleTransparencyCheck.php 7 months ago XmlRpcEndpointCheck.php 7 months ago
HighPrivilegeUserCountCheck.php
245 lines
1 <?php
2
3 /**
4 * ======================================================================
5 * LICENSE: This file is subject to the terms and conditions defined in *
6 * file 'license.txt', which is part of this source code package. *
7 * ======================================================================
8 */
9
10 /**
11 * Check for the elevated number of high privilege users
12 *
13 * @package AAM
14 * @version 7.0.0
15 */
16 class AAM_Audit_HighPrivilegeUserCountCheck
17 {
18
19 use AAM_Audit_AuditCheckTrait;
20
21 /**
22 * Step ID
23 *
24 * @version 7.0.0
25 */
26 const ID = 'high_privilege_users_count';
27
28 /**
29 * List of core capabilities that can cause damage to the site through content
30 *
31 * @version 7.0.0
32 */
33 const CONTENT_HIGH_CAPS = [
34 'manage_categories',
35 'unfiltered_html',
36 'edit_published_pages',
37 'delete_published_pages',
38 'unfiltered_upload'
39 ];
40
41 /**
42 * List of core capabilities that can cause damage to the site
43 *
44 * @version 7.0.0
45 */
46 const SITE_HIGH_CAPS = [
47 'edit_themes',
48 'edit_plugins',
49 'edit_files',
50 'activate_plugins',
51 'manage_options',
52 'delete_users',
53 'create_users',
54 'update_plugins',
55 'delete_plugins',
56 'install_plugins',
57 'update_themes',
58 'install_themes',
59 'update_core',
60 'promote_users',
61 'delete_themes'
62 ];
63
64 /**
65 * Run the check
66 *
67 * @return array
68 *
69 * @access public
70 * @static
71 *
72 * @version 7.0.0
73 */
74 public static function run()
75 {
76 $issues = [];
77 $response = [ 'is_completed' => true ];
78
79 try {
80 // Step #1. Identifying the list of roles that have high privileges
81 $identified_roles = self::_get_high_privilege_roles(
82 self::_read_role_key_option()
83 );
84
85 // Scan for high privilege roles
86 array_push(
87 $issues,
88 ...self::_identify_elevated_user_count($identified_roles)
89 );
90 } catch (Exception $e) {
91 array_push($issues, self::_format_issue(
92 'APPLICATION_ERROR',
93 [
94 'message' => $e->getMessage()
95 ],
96 'error'
97 ));
98 }
99
100 if (count($issues) > 0) {
101 $response['issues'] = $issues;
102 }
103
104 // Determine final status for the check
105 self::_determine_check_status($response);
106
107 return $response;
108 }
109
110 /**
111 * Get a collection of error messages for current step
112 *
113 * @return array
114 * @access private
115 * @static
116 *
117 * @version 7.0.0
118 */
119 private static function _get_message_templates()
120 {
121 return [
122 'ELEVATED_ADMIN_USER_COUNT' => __(
123 'Detected elevated user count (%d) with admin level privileges',
124 'advanced-access-manager'
125 ),
126 'ELEVATED_EDITOR_USER_COUNT' => __(
127 'Detected elevated user count (%d) with high content moderation privileges',
128 'advanced-access-manager'
129 )
130 ];
131 }
132
133 /**
134 * Identify the list of roles that have high privilege caps
135 *
136 * @param array $db_roles
137 *
138 * @return array
139 * @access private
140 *
141 * @version 7.0.0
142 */
143 private static function _get_high_privilege_roles($db_roles)
144 {
145 $response = [
146 'content' => [],
147 'website' => []
148 ];
149
150 foreach($db_roles as $role_id => $role) {
151 $assigned_caps = array_keys(
152 array_filter($role['capabilities'], function($v) {
153 return !empty($v);
154 })
155 );
156
157 $content = array_intersect($assigned_caps, self::CONTENT_HIGH_CAPS);
158 $website = array_intersect($assigned_caps, self::SITE_HIGH_CAPS);
159
160 if (!empty($content) && $role_id !== 'administrator') {
161 array_push($response['content'], $role_id);
162 }
163
164 if (!empty($website)) {
165 array_push($response['website'], $role_id);
166 }
167 }
168
169 return $response;
170 }
171
172 /**
173 * Identify the elevated number of high-privilege users
174 *
175 * @param array $elevated_roles
176 *
177 * @return array
178 *
179 * @access private
180 * @static
181 *
182 * @version 7.0.0
183 */
184 private static function _identify_elevated_user_count($elevated_roles)
185 {
186 global $wpdb;
187
188 $issues = [];
189 $users = count_users();
190 $sums = [
191 'content' => 0,
192 'website' => 0
193 ];
194
195 foreach($users['avail_roles'] as $role_id => $count) {
196 if (in_array($role_id, $elevated_roles['content'], true)) {
197 $sums['content'] += $count;
198 }
199
200 if (in_array($role_id, $elevated_roles['website'], true)) {
201 $sums['website'] += $count;
202 }
203 }
204
205 $suggested_admins = AAM::api()->config->get(
206 'service.security_audit.recommended_admins_count', 1
207 );
208
209 // Let's calculate the recommended number of editors based on the number of
210 // published posts
211 $total = $wpdb->get_var(
212 "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_status = 'publish'"
213 );
214
215 // Let's be real here. How many articles one senior editor can review per
216 // biz day? Let's put an arbitrary number 4 with 250 working days, it may be
217 // max 1,000 articles per year.
218 $suggested_editors = AAM::api()->config->get(
219 'service.security_audit.recommended_editors_count', ceil($total / 1000)
220 );
221
222 if ($sums['website'] > $suggested_admins) {
223 array_push($issues, self::_format_issue(
224 'ELEVATED_ADMIN_USER_COUNT',
225 [
226 'user_count' => $sums['website']
227 ],
228 'critical'
229 ));
230 }
231
232 if ($sums['content'] > $suggested_editors) {
233 array_push($issues, self::_format_issue(
234 'ELEVATED_EDITOR_USER_COUNT',
235 [
236 'user_count' => $sums['content']
237 ],
238 'warning'
239 ));
240 }
241
242 return $issues;
243 }
244
245 }