PluginProbe
WP Admin Audit / 1.2.5
WP Admin Audit v1.2.5
1.2.9 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 All 26 releases
wp-admin-audit / wp-admin-audit.php

wp-admin-audit.php in WP Admin Audit 1.2.5, at wp-admin-audit.php

289 lines 12.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * Plugin Name: WP Admin Audit
4 * Plugin URI: https://wpadminaudit.com/
5 * Description: Monitor the security relevant activities on your site and get notified when something out of the usual is happening. Browse the event log to find out who did what at which time.
6 * Version: 1.2.5
7 * Author: brandtoss
8 * Author URI: https://wpadminaudit.com/
9 * License: GPL2
10 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
11 * Requires at least: 5.5
12 * Requires PHP: 5.6
13 *
14 * Text Domain: wp-admin-audit
15 * Domain Path: /languages
16 *
17 */
18
19
20 /*
21 WP Admin Audit is free software; you can redistribute it and/or modify
22 it under the terms of the GNU General Public License, version 2, as
23 published by the Free Software Foundation.
24
25 WP Admin Audit is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
29
30 You should have received a copy of the GNU General Public License
31 along with WP Admin Audit. If not, see <http://www.gnu.org/licenses/>.
32 */
33
34
35 if ( ! class_exists( 'WpAdminAudit' ) ) {
36 class WpAdminAudit
37 {
38 public $version = '1.2.5';
39 protected $eventListener;
40
41 public function __construct()
42 {
43 self::errorLog('construct');
44 if (self::onFrontend()) {
45 add_action('wp_loaded', array($this, 'setupWADA'), 0);
46 }else{
47 add_action('plugins_loaded', array($this, 'setupWADA'), 8);
48 }
49
50 register_activation_hook(__FILE__, array($this, 'installWADA'));
51 register_deactivation_hook(__FILE__, array($this, 'deactivateWADA'));
52 add_filter('cron_schedules', array($this, 'addCronSchedules'));
53 }
54
55 protected static function errorLog($msg){
56 if(self::isHeartbeatRequest()) return;
57 //$requestId = sprintf("%08x", abs(crc32($_SERVER['REMOTE_ADDR'] . $_SERVER['REQUEST_TIME'] . $_SERVER['REMOTE_PORT'])));
58 //error_log($requestId."\t".$msg);
59 }
60
61 public static function getInstance() {
62 static $instance = null;
63 if (!$instance) {
64 $instance = new self();
65 }
66 return $instance;
67 }
68
69 public function setupWADA(){
70 self::errorLog('setupWADA');
71 if(self::isHeartbeatRequest()){
72 return; // do not set up in that scenario
73 }
74
75 // Find out what kind of fun WP was having
76 //add_action ( 'shutdown', function() {
77 // self::errorLog('WP->shutdown actions: '.print_r($GLOBALS['wp_actions'], true));
78 //} );
79
80 if(!self::onFrontend() || (self::loadOnFrontend()) || (is_user_logged_in())){
81 self::errorLog('Go ahead');
82 $this->loadPluginDependencies();
83 $this->setupHooksAndFilters();
84 $this->completePendingUpdates();
85
86 if(is_admin()){
87 $lastActivityWidget = new WADA_Widget_LastActivities();
88 $loginAttemptsWidget = new WADA_Widget_LoginAttempts();
89 }
90
91 if (did_action('init')){
92 $this->initWADA();
93 }
94 }else{
95 self::errorLog('Skip WADA setup because Frontend: '.(self::onFrontend() ? 'y':'n').', Logged in: '.(is_user_logged_in() ? 'y':'n').', Rest API: '.(self::isRequestForRestAPI()?'y':'n'));
96 }
97 }
98
99 public function loadOnFrontend(){ // the frontend activities that are (potentially) relevant for our sensors
100 if(array_key_exists('login', $_REQUEST)) return true;
101 if(array_key_exists('register', $_REQUEST)) return true;
102 if(array_key_exists('reset_key', $_REQUEST)) return true;
103 if(array_key_exists('reset_login', $_REQUEST)) return true;
104 if(array_key_exists('wc_reset_password', $_REQUEST)) return true;
105 return false;
106 }
107
108 public function loadPluginDependencies(){
109 require_once 'classes/Constants.php';
110 require_once 'classes/Setup.php';
111 require_once 'classes/Application/BackendSum.php';
112 require_once 'classes/Application/BackendWoosl.php';
113 require_once 'classes/Application/Database.php';
114 require_once 'classes/Application/EventListener.php';
115 require_once 'classes/Application/Extensions.php';
116 require_once 'classes/Application/Log.php';
117 require_once 'classes/Application/Maintenance.php';
118 require_once 'classes/Application/Router.php';
119 require_once 'classes/Application/Settings.php';
120 require_once 'classes/Application/Updater.php';
121 require_once 'classes/Application/Version.php';
122 require_once 'classes/Utils/CommentUtils.php';
123 require_once 'classes/Utils/CompUtils.php';
124 require_once 'classes/Utils/DateUtils.php';
125 require_once 'classes/Utils/FileUtils.php';
126 require_once 'classes/Utils/PHPUtils.php';
127 require_once 'classes/Utils/PluginUtils.php';
128 require_once 'classes/Utils/PostUtils.php';
129 require_once 'classes/Utils/ScriptUtils.php';
130 require_once 'classes/Utils/TermUtils.php';
131 require_once 'classes/Utils/UserUtils.php';
132 require_once 'classes/Utils/UpgraderUtils.php';
133 if(is_admin()){
134 require_once 'classes/Application/Menu.php';
135 require_once 'classes/Utils/HtmlUtils.php';
136 }
137 }
138
139 public function setupHooksAndFilters(){
140 if(count($_POST)>0) {
141 WADA_Log::debug('WADA Setup POST: ' . print_r($_POST, true));
142 }
143 add_action( 'init', array( $this, 'initWADA' ), 5 );
144 add_action( 'admin_menu', array( 'WADA_Menu', 'adminMenu' ) );
145 add_action( 'admin_enqueue_scripts', array( 'WADA_Menu', 'adminAssets' ) );
146
147 // Schedules
148 add_action( 'wp_admin_audit_maintenance', array( 'WADA_Maintenance', 'scheduledRun' ) );
149 add_action( 'wp_admin_audit_queue_work', array( 'WADA_Notification_Queue', 'workOnQueue' ), 10 );
150 add_action( 'wp_admin_audit_queue_work', array( 'WADA_Replicator_Worker', 'workOnPendingReplications' ), 9 ); // same hook, higher priority for replications
151
152 // Internal hooks
153 add_action( 'wp_admin_audit_new_event', array( 'WADA_Notification_Queue', 'matchAndQueueEvent' ), 10, 2 );
154
155 WADA_BackendSum::autoResetExtensionCacheOnPluginLifecycleActivities();
156 add_filter('plugins_api', array('WADA_BackendSum', 'injectPluginInfos'), 25, 3);
157
158 // Ajax
159 WADA_Router::setupAjaxHooks();
160 }
161
162 public function completePendingUpdates(){
163 require_once 'classes/Setup.php';
164 $setup = new WADA_Setup();
165 if($setup->isDatabaseUpdateNeeded()){
166 WADA_Log::info('completePendingUpdates');
167 $setup->installOrUpdate();
168 }
169 }
170
171 public function addCronSchedules($schedules){
172 $schedules['15min'] = array(
173 'interval' => 900,
174 'display' => __('Every 15 minutes', 'wp-admin-audit'),
175 );
176 $schedules['5min'] = array(
177 'interval' => 300,
178 'display' => __('Every 5 minutes', 'wp-admin-audit'),
179 );
180 $schedules['1min'] = array(
181 'interval' => 60,
182 'display' => __('Every minute', 'wp-admin-audit'),
183 );
184 return $schedules;
185 }
186
187 function autoload($className){
188 $inclPath = null;
189 if(strpos($className , 'WADA_Layout_' ) === 0){
190 $namePart = substr($className, strlen('WADA_Layout_'));
191 $inclPath = 'classes/Views/Layouts/'.$namePart.'.php';
192 }elseif(strpos($className , 'WADA_Widget_' ) === 0) {
193 $namePart = substr($className, strlen('WADA_Widget_'));
194 $inclPath = 'classes/Views/Widgets/' . $namePart . '.php';
195 }elseif($className === 'WADA_HtmlUtils') {
196 $inclPath = 'classes/Utils/HtmlUtils.php';
197 }else{
198 $folders = array('Model', 'Sensor', 'View', 'Notification', 'Replicator');
199 if(strpos($className, 'WADA_') === 0) {
200 foreach($folders as $folder) {
201 if(strpos($className, 'WADA_' . $folder . '_') === 0) {
202 $namePart = substr($className, strlen('WADA_' . $folder . '_'));
203 $inclPath = 'classes/' . $folder . 's/' . $namePart . '.php';
204 //self::errorLog('WADA->autoload ' . $folder . ' ' . $namePart . ' via ' . $inclPath);
205 break; // no need to look further
206 }
207 }
208 }
209 }
210 if($inclPath){
211 //error_log('WADA autoload '.$className .' at '.$inclPath);
212 if(is_file(__DIR__.'/'.$inclPath)){
213 require_once __DIR__.'/'.$inclPath;
214 }else{
215 // error_log('WADA autoload '.$className .' NOT EXISTING where we thought ('.(__DIR__.'/'.$inclPath).')');
216 }
217 }
218 }
219
220 public function initWADA(){
221 self::errorLog('initWADA');
222 do_action( 'wp_admin_audit_loaded_pre_sensors', $this );
223 //WADA_Log::info('initWADA hey hey');
224 if(class_exists('WADA_EventListener')) {
225 $eventListener = new WADA_EventListener();
226 $this->eventListener = $eventListener;
227 $this->eventListener->startListening();
228 }
229
230 // Done initializing, tell whoever is interested
231 do_action( 'wp_admin_audit_loaded_post_sensors', $this );
232 }
233
234 public function installWADA(){
235 require_once 'classes/Setup.php';
236 $setup = new WADA_Setup();
237 $setup->installOrUpdate();
238 }
239
240 public function deactivateWADA(){ // we do some cleanup or notifications if needed
241 $setup = new WADA_Setup();
242 $setup->unscheduleEvents();
243 // TODO ONCE WE HAVE REPLICATION MAKE SURE THE PLUGIN DEACTIVATION EVENT GETS SENT
244 }
245
246 public static function onFrontend(){
247 $onLoginScreen = parse_url(site_url('wp-login.php'), PHP_URL_PATH) === parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
248 $isAdmin = is_admin();
249 $restApi = self::isRequestForRestAPI();
250 $isCron = wp_doing_cron();
251 $isWPCli = (defined('WP_CLI') && WP_CLI);
252 if($isAdmin || $restApi || $onLoginScreen || $isCron || $isWPCli){
253 return false;
254 }
255 return true;
256 }
257
258 public static function isRequestForRestAPI(){
259 $isWpJsonV2 = false;
260 $isRestUrlPath = false;
261 $isRestRoute = isset($_GET['rest_route']);
262 if (!empty($_SERVER['REQUEST_URI'])) {
263 $isWpJsonV2 = (array_key_exists('REQUEST_URI', $_SERVER) && (strpos($_SERVER['REQUEST_URI'], 'wp-json/wp/v2') !== false));
264 $restUrlPath = trim(parse_url(home_url('/wp-json/'), PHP_URL_PATH), '/');
265 $requestUrl = trim($_SERVER['REQUEST_URI'], '/');
266 $isRestUrlPath = (strpos($requestUrl, $restUrlPath) === 0);
267 }
268 return ($isWpJsonV2 || $isRestUrlPath || $isRestRoute);
269 }
270
271 public static function isHeartbeatRequest(){
272 if(array_key_exists('action', $_POST) && $_POST['action'] === 'heartbeat'){
273 return true;
274 }
275
276 /* */
277
278 return false;
279 }
280
281 } // class end
282
283 $adminAudit = WpAdminAudit::getInstance(); // init and run
284
285 spl_autoload_register(array($adminAudit, 'autoload')); // register autoloader
286
287 /* */
288
289 }