PluginProbe ʕ •ᴥ•ʔ
CloudSecure WP Security / 1.4.7
CloudSecure WP Security v1.4.7
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 months ago cli 8 months ago lib 3 months ago captcha.php 3 months ago cloudsecure-wp.php 2 months ago common.php 2 months ago config.php 2 years ago disable-access-system-file.php 4 months ago disable-author-query.php 2 years ago disable-login.php 2 months ago disable-restapi.php 7 months ago disable-xmlrpc.php 1 year ago htaccess.php 3 months ago login-log.php 2 months ago login-notification.php 1 year ago rename-login-page.php 3 months ago restrict-admin-page.php 3 months ago server-error-notification.php 2 months ago two-factor-authentication.php 2 months ago unify-messages.php 2 years ago update-notice.php 7 months ago waf-engine.php 3 months ago waf.php 2 months ago
login-log.php
283 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 global $wpdb;
133 $ip = $this->get_client_ip();
134
135 $this->disable_login->remove_expired_login();
136
137 $data = array(
138 'ip' => $ip,
139 'status' => $this->disable_login->get_status_success(),
140 'failed_count' => 0,
141 'login_at' => current_time( 'mysql' ),
142 );
143
144 $row = $this->disable_login->get_row_by_ip( $ip );
145 if ( empty( $row ) ) {
146 $wpdb->insert( $this->disable_login->get_table_name(), $data );
147 } else {
148 $wpdb->update( $this->disable_login->get_table_name(), $data, array( 'ip' => $ip ) );
149 }
150
151 $this->write_log( $user_login, $ip, self::LOGIN_STATUS_SUCCESS, self::METHOD_PAGE );
152 }
153
154 /**
155 * XML-RPCログイン成功時
156 */
157 public function xmlrpc_call() {
158 $user = wp_get_current_user();
159
160 if ( empty( $user->ID ) ) {
161 return;
162 }
163
164 $user_login = $user->user_login;
165 $ip = $this->get_client_ip();
166 $this->write_log( $user_login, $ip, self::LOGIN_STATUS_SUCCESS, self::METHOD_XMLRPC );
167 }
168
169 /**
170 * ログイン失敗時
171 */
172 public function wp_login_failed( $user_login ) {
173 $ip = $this->get_client_ip();
174 $status = $this->disable_login->get_login_status();
175 $method = $this->is_xmlrpc() ? self::METHOD_XMLRPC : self::METHOD_PAGE;
176 $this->write_log( $user_login, $ip, $status, $method );
177 }
178
179 /**
180 * ログインログ取得
181 *
182 * @param array $conditions
183 * @return array
184 */
185 public function get_login_history( array $conditions ): array {
186 global $wpdb;
187 $table_name = $wpdb->prefix . self::TABLE_NAME;
188 $prepare = array();
189
190 $sql = 'SELECT ';
191 $sql .= '* ';
192 $sql .= "FROM {$table_name} ";
193 $sql .= 'WHERE %d ';
194
195 $prepare[] = 1;
196
197 if ( ! empty( $conditions['condition_status'] ?? '' ) ) {
198 $sql .= 'AND status = %d ';
199 $prepare[] = (int) $conditions['condition_status'];
200 }
201
202 if ( ! empty( $conditions['condition_method'] ?? '' ) ) {
203 $sql .= 'AND method = %d ';
204 $prepare[] = (int) $conditions['condition_method'];
205 }
206
207 if ( ! empty( $conditions['condition_ip'] ?? '' ) ) {
208 if ( ! empty( $conditions['condition_ip_other_than'] ?? '' ) && 't' === $conditions['condition_ip_other_than'] ) {
209 $sql .= 'AND ip <> %s ';
210 } else {
211 $sql .= 'AND ip = %s ';
212 }
213 $prepare[] = $conditions['condition_ip'];
214 }
215
216 if ( ! empty( $conditions['condition_name'] ?? '' ) ) {
217 if ( ! empty( $conditions['condition_name_other_than'] ?? '' ) && 't' === $conditions['condition_name_other_than'] ) {
218 $sql .= 'AND `name` <> %s ';
219 } else {
220 $sql .= 'AND `name` = %s ';
221 }
222 $prepare[] = $conditions['condition_name'];
223 }
224
225 array_unshift( $prepare, $sql );
226 $rows = $wpdb->get_results( call_user_func_array( array( $wpdb, 'prepare' ), $prepare ), ARRAY_A );
227
228 return $rows ?? array();
229 }
230
231 /**
232 * 絞込み条件保存
233 *
234 * @param array $conditions
235 * @return void
236 */
237 public function save_conditions( $conditions ): void {
238 $this->config->set( self::KEY_CONDITIONS, $conditions );
239 $this->config->save();
240 }
241
242 /**
243 * 絞込み条件取得
244 *
245 * @return array $conditions
246 */
247 public function get_conditions(): array {
248 $conditions = $this->config->get( self::KEY_CONDITIONS ) ?? '';
249 if ( ! empty( $conditions ) ) {
250 return $conditions;
251 }
252 return array();
253 }
254
255 /**
256 * 有効化
257 *
258 * @return void
259 */
260 public function activate(): void {
261 global $wpdb;
262 $table_name = $this->get_table_name();
263 $table = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table_name ) ) );
264
265 if ( is_null( $table ) ) {
266 $charset_collate = $wpdb->get_charset_collate();
267
268 $sql = "CREATE TABLE {$table_name} (
269 id BIGINT( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT,
270 name VARCHAR( 60 ) NOT NULL DEFAULT '',
271 ip VARCHAR( 39 ) NOT NULL DEFAULT '',
272 status INT NOT NULL DEFAULT 0,
273 method INT NOT NULL DEFAULT 0,
274 login_at DATETIME,
275 UNIQUE KEY id ( id )
276 ) {$charset_collate}";
277
278 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
279 dbDelta( $sql );
280 }
281 }
282 }
283