PluginProbe ʕ •ᴥ•ʔ
CloudSecure WP Security / 1.4.14
CloudSecure WP Security v1.4.14
1.4.14 1.4.13 1.4.12 1.4.11 1.4.10 1.4.9 trunk 0.9.0 1.0.2 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.19 1.3.2 1.3.20 1.3.21 1.3.22 1.3.23 1.3.24 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8
cloudsecure-wp-security / modules / login-log.php
cloudsecure-wp-security / modules Last commit date
admin 2 weeks ago cli 2 weeks ago lib 1 month ago captcha.php 2 weeks ago cloudsecure-wp.php 6 days ago common.php 4 months ago config.php 2 years ago disable-access-system-file.php 1 month ago disable-author-query.php 2 weeks ago disable-login.php 1 month ago disable-restapi.php 2 weeks ago disable-xmlrpc.php 1 year ago htaccess.php 4 months ago login-log.php 1 month ago login-notification.php 3 months ago protect-rest-batch.php 1 month ago rename-login-page.php 4 months ago restrict-admin-page.php 3 months ago server-error-notification.php 3 months ago two-factor-authentication.php 6 days ago unify-messages.php 2 years ago update-notice.php 9 months ago waf-engine.php 6 days ago waf.php 1 month ago
login-log.php
277 lines
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 class CloudSecureWP_Login_Log extends CloudSecureWP_Common {
8 private const KEY_FEATURE = 'login_log';
9 private const KEY_CONDITIONS = self::KEY_FEATURE . '_conditions';
10 private const TABLE_NAME = 'cloudsecurewp_' . self::KEY_FEATURE;
11 private const COLUMN_ID = 'id';
12 private const COLUMN_NAME = 'name';
13 private const COLUMN_IP = 'ip';
14 private const COLUMN_STATUS = 'status';
15 private const COLUMN_METHOD = 'method';
16 private const COLUMN_LOGIN_AT = 'login_at';
17 private const COLUMNS = array(
18 self::COLUMN_ID => 'ID',
19 self::COLUMN_NAME => 'ユーザー名',
20 self::COLUMN_IP => 'IPアドレス',
21 self::COLUMN_STATUS => 'ログイン判定',
22 self::COLUMN_METHOD => 'ログイン種別',
23 self::COLUMN_LOGIN_AT => '日時',
24 );
25
26 private const MAX_LOG = 10000;
27 private $config;
28 private $disable_login;
29
30 function __construct( array $info, CloudSecureWP_Config $config, CloudSecureWP_Disable_Login $disable_login ) {
31 parent::__construct( $info );
32 $this->config = $config;
33 $this->disable_login = $disable_login;
34 }
35
36 /**
37 * 機能毎のKEY取得
38 *
39 * @return string
40 */
41 public function get_feature_key(): string {
42 return self::KEY_FEATURE;
43 }
44
45 /**
46 * テーブル名取得
47 *
48 * @return string
49 */
50 public function get_table_name(): string {
51 global $wpdb;
52 return $wpdb->prefix . self::TABLE_NAME;
53 }
54
55 /**
56 * LoginLogテーブルカラム�
57 報取得
58 */
59 public function get_cloumns(): array {
60 return self::COLUMNS;
61 }
62
63 /**
64 * ログイン種別取得
65 */
66 public function get_methods(): array {
67 return self::METHODS;
68 }
69
70 /**
71 * Xmlrpc判定
72 *
73 * @return bool
74 */
75 public function is_xmlrpc(): bool {
76 if ( 'xmlrpc.php' === basename( sanitize_text_field( $_SERVER['SCRIPT_NAME'] ) ) ) {
77 return true;
78 }
79 return false;
80 }
81
82 /**
83 * ログインログ登録
84 *
85 * @param string $name
86 * @param string $ip
87 * @param int $status
88 * @param int $method
89 * @return void
90 */
91 public function write_log( string $name, string $ip, int $status, int $method ): void {
92 global $wpdb;
93 $table_name = $wpdb->prefix . self::TABLE_NAME;
94 $max_log = self::MAX_LOG;
95
96 $data = array(
97 'name' => $name,
98 'ip' => $ip,
99 'status' => $status,
100 'method' => $method,
101 'login_at' => current_time( 'mysql' ),
102 );
103
104 try {
105 $wpdb->query( 'START TRANSACTION' );
106
107 $result = $wpdb->insert( $table_name, $data );
108 if ( $result === false || ! empty( $wpdb->last_error ) ) {
109 throw new Exception( 'Failed to insert login log.' );
110 }
111
112 $row = $wpdb->get_row( $wpdb->prepare( "SELECT id FROM {$wpdb->prefix}cloudsecurewp_login_log ORDER BY id DESC LIMIT 1 OFFSET %d", $max_log ), ARRAY_A );
113
114 if ( ! empty( $row ?? array() ) ) {
115 $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}cloudsecurewp_login_log WHERE id <= %d", $row['id'] ) );
116 if ( $result === false || ! empty( $wpdb->last_error ) ) {
117 throw new Exception( 'Failed to delete old login logs.' );
118 }
119 }
120
121 $wpdb->query( 'COMMIT' );
122 } catch ( Exception $e ) {
123 $wpdb->query( 'ROLLBACK' );
124 }
125 }
126
127 /**
128 * ログインページログイン成功時
129 */
130 public function wp_login( $user_login ) {
131
132 $ip = $this->get_client_ip();
133
134 $this->disable_login->reset_on_success( $ip );
135
136 $this->write_log( $user_login, $ip, self::LOGIN_STATUS_SUCCESS, self::METHOD_PAGE );
137 }
138
139 /**
140 * XML-RPCログイン成功時
141 */
142 public function xmlrpc_call() {
143 $user = wp_get_current_user();
144
145 if ( empty( $user->ID ) ) {
146 return;
147 }
148
149 $user_login = $user->user_login;
150 $ip = $this->get_client_ip();
151
152 $this->disable_login->reset_on_success( $ip );
153
154 $this->write_log( $user_login, $ip, self::LOGIN_STATUS_SUCCESS, self::METHOD_XMLRPC );
155 }
156
157 /**
158 * ログイン失敗時
159 */
160 public function wp_login_failed( $user_login, $error = null ) {
161 $ip = $this->get_client_ip();
162
163 if ( is_wp_error( $error ) && $error->get_error_code() === 'xmlrpc_login_denied' ) {
164 $status = self::LOGIN_STATUS_DISABLED;
165 } else {
166 $status = $this->disable_login->get_login_status();
167 }
168
169 $method = $this->is_xmlrpc() ? self::METHOD_XMLRPC : self::METHOD_PAGE;
170 $this->write_log( $user_login, $ip, $status, $method );
171 }
172
173 /**
174 * ログインログ取得
175 *
176 * @param array $conditions
177 * @return array
178 */
179 public function get_login_history( array $conditions ): array {
180 global $wpdb;
181 $table_name = $wpdb->prefix . self::TABLE_NAME;
182 $prepare = array();
183
184 $sql = 'SELECT ';
185 $sql .= '* ';
186 $sql .= "FROM {$table_name} ";
187 $sql .= 'WHERE %d ';
188
189 $prepare[] = 1;
190
191 if ( ! empty( $conditions['condition_status'] ?? '' ) ) {
192 $sql .= 'AND status = %d ';
193 $prepare[] = (int) $conditions['condition_status'];
194 }
195
196 if ( ! empty( $conditions['condition_method'] ?? '' ) ) {
197 $sql .= 'AND method = %d ';
198 $prepare[] = (int) $conditions['condition_method'];
199 }
200
201 if ( ! empty( $conditions['condition_ip'] ?? '' ) ) {
202 if ( ! empty( $conditions['condition_ip_other_than'] ?? '' ) && 't' === $conditions['condition_ip_other_than'] ) {
203 $sql .= 'AND ip <> %s ';
204 } else {
205 $sql .= 'AND ip = %s ';
206 }
207 $prepare[] = $conditions['condition_ip'];
208 }
209
210 if ( ! empty( $conditions['condition_name'] ?? '' ) ) {
211 if ( ! empty( $conditions['condition_name_other_than'] ?? '' ) && 't' === $conditions['condition_name_other_than'] ) {
212 $sql .= 'AND `name` <> %s ';
213 } else {
214 $sql .= 'AND `name` = %s ';
215 }
216 $prepare[] = $conditions['condition_name'];
217 }
218
219 array_unshift( $prepare, $sql );
220 $rows = $wpdb->get_results( call_user_func_array( array( $wpdb, 'prepare' ), $prepare ), ARRAY_A );
221
222 return $rows ?? array();
223 }
224
225 /**
226 * 絞込み条件保存
227 *
228 * @param array $conditions
229 * @return void
230 */
231 public function save_conditions( $conditions ): void {
232 $this->config->set( self::KEY_CONDITIONS, $conditions );
233 $this->config->save();
234 }
235
236 /**
237 * 絞込み条件取得
238 *
239 * @return array $conditions
240 */
241 public function get_conditions(): array {
242 $conditions = $this->config->get( self::KEY_CONDITIONS ) ?? '';
243 if ( ! empty( $conditions ) ) {
244 return $conditions;
245 }
246 return array();
247 }
248
249 /**
250 * 有効化
251 *
252 * @return void
253 */
254 public function activate(): void {
255 global $wpdb;
256 $table_name = $this->get_table_name();
257 $table = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table_name ) ) );
258
259 if ( is_null( $table ) ) {
260 $charset_collate = $wpdb->get_charset_collate();
261
262 $sql = "CREATE TABLE {$table_name} (
263 id BIGINT( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT,
264 name VARCHAR( 60 ) NOT NULL DEFAULT '',
265 ip VARCHAR( 39 ) NOT NULL DEFAULT '',
266 status INT NOT NULL DEFAULT 0,
267 method INT NOT NULL DEFAULT 0,
268 login_at DATETIME,
269 UNIQUE KEY id ( id )
270 ) {$charset_collate}";
271
272 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
273 dbDelta( $sql );
274 }
275 }
276 }
277