PluginProbe ʕ •ᴥ•ʔ
CloudSecure WP Security / 1.3.20
CloudSecure WP Security v1.3.20
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 / captcha.php
cloudsecure-wp-security / modules Last commit date
admin 7 months ago cli 8 months ago lib 11 months ago captcha.php 2 years ago cloudsecure-wp.php 8 months ago common.php 1 year ago config.php 2 years ago disable-access-system-file.php 1 year ago disable-author-query.php 2 years ago disable-login.php 1 year ago disable-restapi.php 7 months ago disable-xmlrpc.php 1 year ago htaccess.php 1 year ago login-log.php 1 year ago login-notification.php 1 year ago rename-login-page.php 1 year ago restrict-admin-page.php 10 months ago server-error-notification.php 1 year ago two-factor-authentication.php 10 months ago unify-messages.php 2 years ago update-notice.php 7 months ago waf-engine.php 7 months ago waf.php 1 year ago
captcha.php
373 lines
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 class CloudSecureWP_CAPTCHA extends CloudSecureWP_Common {
8 private const KEY_FEATURE = 'captcha';
9 private const KEY_LOGIN = self::KEY_FEATURE . '_login';
10 private const KEY_COMMENT = self::KEY_FEATURE . '_comment';
11 private const KEY_LOST_PASSWORD = self::KEY_FEATURE . '_lost_password';
12 private const KEY_REGISTER = self::KEY_FEATURE . '_register';
13 private const LOGIN_VALUES = array( 1, 2 ); // 無効, 有効 .
14 private const COMMENT_VALUES = array( 1, 2 ); // 無効, 有効 .
15 private const LOST_PASSWORD_VALUES = array( 1, 2 ); // 無効, 有効 .
16 private const REGISTER_VALUES = array( 1, 2 ); // 無効, 有効 .
17 private const ERROR_CODE = 'cloudsecurewp_captcha_error';
18 private const CAPTCHA_FORM_NAME = 'cloudsecurewp_captcha';
19 private const PREFIX_FORM_NAME = 'cloudsecurewp_captcha_prefix';
20 private const CAPTCHA_ERROR_MESSAGE = 'エラー:画像認証に失敗しました';
21
22 private $config;
23 private $captcha;
24 private $allowed_html;
25
26 function __construct( array $info, CloudSecureWP_Config $config ) {
27 parent::__construct( $info );
28 $this->config = $config;
29 $this->captcha = new CloudSecureWP_ReallySimpleCaptcha();
30 $this->allowed_html = array(
31 'p' => array(
32 'class' => array(),
33 ),
34 'style' => array(),
35 'label' => array(
36 'for' => array(),
37 ),
38 'img' => array(
39 'src' => array(),
40 'alt' => array(),
41 ),
42 'input' => array(
43 'type' => array(),
44 'id' => array(),
45 'name' => array(),
46 'class' => array(),
47 'value' => array(),
48 'size' => array(),
49 'aria-required' => array(),
50 ),
51 );
52 }
53
54 /**
55 * 機能毎のKEY取得
56 *
57 * @return string
58 */
59 public function get_feature_key(): string {
60 return self::KEY_FEATURE;
61 }
62
63 /**
64 * 有効無効判定
65 *
66 * @return bool
67 */
68 public function is_enabled(): bool {
69 return $this->config->get( $this->get_feature_key() ) === 't' ? true : false;
70 }
71
72 /**
73 * ログインフォームの有効無効判定
74 */
75 public function is_login_form_enabled(): bool {
76 return ( (int) $this->config->get( self::KEY_LOGIN ) === (int) self::LOGIN_VALUES[1] ) ? true : false;
77 }
78
79 /**
80 * コメントフォームの有効無効判定
81 */
82 public function is_comment_form_enabled(): bool {
83 return ( (int) $this->config->get( self::KEY_COMMENT ) === (int) self::COMMENT_VALUES[1] ) ? true : false;
84 }
85
86 /**
87 * パスワードリセットフォームの有効無効判定
88 */
89 public function is_lost_password_form_enabled(): bool {
90 return ( (int) $this->config->get( self::KEY_LOST_PASSWORD ) === (int) self::LOST_PASSWORD_VALUES[1] ) ? true : false;
91 }
92
93 /**
94 * ユーザー登録フォームの有効無効判定
95 */
96 public function is_register_form_enabled(): bool {
97 return ( (int) $this->config->get( self::KEY_REGISTER ) === (int) self::REGISTER_VALUES[1] ) ? true : false;
98 }
99
100 /**
101 * 初期設定値取得
102 *
103 * @return array
104 */
105 public function get_default(): array {
106 return array(
107 self::KEY_FEATURE => 'f',
108 self::KEY_LOGIN => self::LOGIN_VALUES[1],
109 self::KEY_COMMENT => self::COMMENT_VALUES[1],
110 self::KEY_LOST_PASSWORD => self::LOST_PASSWORD_VALUES[1],
111 self::KEY_REGISTER => self::REGISTER_VALUES[1],
112 );
113 }
114
115 /**
116 * 設定値key取得
117 */
118 public function get_keys(): array {
119 return array(
120 self::KEY_FEATURE,
121 self::KEY_LOGIN,
122 self::KEY_COMMENT,
123 self::KEY_LOST_PASSWORD,
124 self::KEY_REGISTER,
125 );
126 }
127
128 /**
129 * 設定値取得
130 */
131 public function get_settings(): array {
132 $settings = array();
133 $keys = $this->get_keys();
134
135 foreach ( $keys as $key ) {
136 $settings[ $key ] = $this->config->get( $key );
137 }
138
139 return $settings;
140 }
141
142 /**
143 * 設定値保存
144 *
145 * @param array $settings
146 * @return void
147 */
148 public function save_settings( $settings ): void {
149 $keys = $this->get_keys();
150
151 foreach ( $keys as $key ) {
152 $this->config->set( $key, $settings[ $key ] ?? '' );
153 }
154 $this->config->save();
155 }
156
157 /**
158 * 設定定義値取得
159 *
160 * @return array
161 */
162 public function get_constant_settings(): array {
163 return array(
164 self::KEY_LOGIN => self::LOGIN_VALUES,
165 self::KEY_COMMENT => self::COMMENT_VALUES,
166 self::KEY_LOST_PASSWORD => self::LOST_PASSWORD_VALUES,
167 self::KEY_REGISTER => self::REGISTER_VALUES,
168 );
169 }
170
171 /**
172 * 動作環境チェック
173 *
174 * @return string
175 */
176 public function check_modules(): string {
177 $ret = $this->check_gd();
178 if ( '' !== $ret ) {
179 return $ret;
180 }
181
182 $ret = $this->check_captcha_save_dir();
183 if ( '' !== $ret ) {
184 return $ret;
185 }
186
187 return $ret;
188 }
189
190 /**
191 * GDライブラリチェック
192 *
193 * @return string
194 */
195 public function check_gd(): string {
196 $gd = gd_info();
197
198 if ( empty( $gd ) ) {
199 return 'GDライブラリを利用できません';
200 }
201
202 if ( ! array_key_exists( 'FreeType Support', $gd ) || false === $gd['FreeType Support'] ) {
203 return 'FreeType が無効です';
204 }
205
206 return '';
207 }
208
209 /**
210 * 画像認証画像保存確認
211 *
212 * @return string
213 */
214 public function check_captcha_save_dir(): string {
215 if ( ! $this->captcha->make_tmp_dir() ) {
216 return '画像認証画像保存ディレクトリを作成できません: ' . $this->captcha->tmp_dir;
217 }
218
219 return '';
220 }
221
222 /**
223 * 有効化
224 *
225 * @return void
226 */
227 public function activate(): void {
228 $settings = $this->get_default();
229 $this->save_settings( $settings );
230 }
231
232 /**
233 * 無効化
234 *
235 * @return void
236 */
237 public function deactivate(): void {
238 $settings = $this->get_settings();
239 $settings[ self::KEY_FEATURE ] = 'f';
240 $this->save_settings( $settings );
241 }
242
243 /**
244 * 画像認証
245 *
246 * @return string
247 */
248 function create_captcha(): string {
249 $word = $this->captcha->generate_random_word();
250 $prefix = mt_rand();
251 $this->captcha->generate_image( $prefix, $word );
252
253 $captcha = '<p class="cloudsecure-wp-captcha-block">' . "\n";
254 $captcha .= ' <style>' . "\n";
255 $captcha .= ' .cloudsecure-wp-captcha-block label{' . "\n";
256 $captcha .= ' display: block;' . "\n";
257 $captcha .= ' }' . "\n";
258 $captcha .= ' .cloudsecure-wp-captcha-block label img{' . "\n";
259 $captcha .= ' border: 1px solid #CCCCCC;' . "\n";
260 $captcha .= ' padding: 8px;' . "\n";
261 $captcha .= ' margin-top: 2px;' . "\n";
262 $captcha .= ' }' . "\n";
263 $captcha .= ' </style>' . "\n";
264 $captcha .= ' <label for="' . self::CAPTCHA_FORM_NAME . '">画像に表示された文字を�
265 �力してください</label>' . "\n";
266 $captcha .= ' <label for="' . self::CAPTCHA_FORM_NAME . '"><img src="' . $this->info['plugin_url'] . 'really-simple-captcha/tmp/' . $prefix . '.png" alt="CAPTCHA"></label>' . "\n";
267 $captcha .= ' <input type="text" id="' . self::CAPTCHA_FORM_NAME . '" name="' . self::CAPTCHA_FORM_NAME . '" class="input" value="" size="10" aria-required="true" />' . "\n";
268 $captcha .= ' <input type="hidden" id="' . self::PREFIX_FORM_NAME . '" name="' . self::PREFIX_FORM_NAME . '" value="' . $prefix . '" />' . "\n";
269 $captcha .= wp_nonce_field( $this->get_feature_key() . '_csrf', 'cloudsecurewp_captcha_wpnonce', true, false ) . "\n";
270 $captcha .= '</p>' . "\n";
271
272 return $captcha;
273 }
274
275 /**
276 * 画像認証チェック
277 *
278 * @return bool
279 */
280 public function check_captcha(): bool {
281 if ( ! empty( $_POST ) && check_admin_referer( $this->get_feature_key() . '_csrf', 'cloudsecurewp_captcha_wpnonce' ) ) {
282 return $this->captcha->check( sanitize_text_field( $_POST[ self::PREFIX_FORM_NAME ] ?? '' ), sanitize_text_field( $_POST[ self::CAPTCHA_FORM_NAME ] ?? '' ) );
283 }
284
285 return false;
286 }
287
288 /**
289 * 画像認証エラー
290 */
291 public function get_captcha_error() {
292 return new WP_Error( self::ERROR_CODE, self::CAPTCHA_ERROR_MESSAGE );
293 }
294
295 /**
296 * エラーコード追加
297 */
298 public function shake_error_codes( $error_codes ) {
299 array_push( $error_codes, self::ERROR_CODE );
300 return $error_codes;
301 }
302
303 /**
304 * ログインフォーム画像認証
305 */
306 public function login_form() {
307 echo wp_kses( $this->create_captcha(), $this->allowed_html );
308 }
309
310 /**
311 * ログインフォーム画像認証チェック
312 */
313 public function wp_authenticate_user( $user, $password ) {
314 if ( $this->check_captcha() ) {
315 return $user;
316 }
317
318 return $this->get_captcha_error();
319 }
320
321 /**
322 * コメントフォーム画像認証
323 */
324 public function comment_form_default_fields() {
325 echo wp_kses( $this->create_captcha(), $this->allowed_html );
326 }
327
328 /**
329 * コメントフォーム画像認証チェック
330 */
331 public function preprocess_comment( $comment_data ) {
332 if ( is_admin() || $this->check_captcha() ) {
333 return $comment_data;
334 }
335
336 wp_die( esc_html( self::CAPTCHA_ERROR_MESSAGE ), esc_html( 'ERROR' ), array( 'back_link' => true ) );
337 }
338
339 /**
340 * パスワードリセットフォーム画像認証
341 */
342 public function lostpassword_form() {
343 echo wp_kses( $this->create_captcha(), $this->allowed_html );
344 }
345
346 /**
347 * パスワードリセットフォーム画像認証チェック
348 */
349 public function allow_password_reset( $allow_reset, $user_id ) {
350 if ( $this->check_captcha() ) {
351 return $allow_reset;
352 }
353
354 return $this->get_captcha_error();
355 }
356
357 /**
358 * ユーザー登録フォーム画像認証
359 */
360 public function register_form() {
361 echo wp_kses( $this->create_captcha(), $this->allowed_html );
362 }
363
364 /**
365 * ユーザー登録フォーム画像認証チェック
366 */
367 public function register_post( $username, $email, $errors ) {
368 if ( ! $this->check_captcha() ) {
369 $errors->add( self::CAPTCHA_FORM_NAME, self::CAPTCHA_ERROR_MESSAGE );
370 }
371 }
372 }
373