siteguard-login-history-table.php
1 month ago
siteguard-menu-admin-filter.php
4 weeks ago
siteguard-menu-author-query.php
2 weeks ago
siteguard-menu-captcha.php
4 weeks ago
siteguard-menu-dashboard.php
4 weeks ago
siteguard-menu-fail-once.php
4 weeks ago
siteguard-menu-init.php
1 month ago
siteguard-menu-login-alert.php
4 weeks ago
siteguard-menu-login-history.php
4 weeks ago
siteguard-menu-login-lock.php
4 weeks ago
siteguard-menu-protect-xmlrpc.php
4 weeks ago
siteguard-menu-rename-login.php
2 weeks ago
siteguard-menu-same-error.php
4 weeks ago
siteguard-menu-updates-notify.php
4 weeks ago
siteguard-menu-waf-tuning-support.php
4 weeks ago
siteguard-waf-exclude-rule-table.php
1 month ago
siteguard-menu-author-query.php
188 lines
| 1 | <?php |
| 2 | |
| 3 | class SiteGuard_Menu_Author_Query extends SiteGuard_Base { |
| 4 | const OPT_NAME_FEATURE = 'block_author_query_enable'; |
| 5 | const OPT_NAME_RESTAPI = 'disable_restapi_enable'; |
| 6 | const OPT_NAME_EXCLUDE = 'disable_restapi_exclude'; |
| 7 | |
| 8 | function __construct() { |
| 9 | $this->render_page(); |
| 10 | } |
| 11 | private function get_rest_api_namespaces() { |
| 12 | $server = rest_get_server(); |
| 13 | $namespaces = $server->get_namespaces(); |
| 14 | |
| 15 | natcasesort( $namespaces ); |
| 16 | |
| 17 | return array_values( $namespaces ); |
| 18 | } |
| 19 | private function normalize_rest_api_namespace( $namespace ) { |
| 20 | $namespace = trim( $namespace ); |
| 21 | return trim( $namespace, '/' ); |
| 22 | } |
| 23 | private function is_rest_api_namespace_excluded( $namespace, $excluded_namespaces ) { |
| 24 | $namespace = $this->normalize_rest_api_namespace( $namespace ); |
| 25 | if ( '' === $namespace ) { |
| 26 | return false; |
| 27 | } |
| 28 | |
| 29 | foreach ( $excluded_namespaces as $excluded_namespace ) { |
| 30 | $excluded_namespace = $this->normalize_rest_api_namespace( $excluded_namespace ); |
| 31 | if ( '' === $excluded_namespace ) { |
| 32 | continue; |
| 33 | } |
| 34 | if ( $namespace === $excluded_namespace || strpos( $namespace, "$excluded_namespace/" ) === 0 ) { |
| 35 | return true; |
| 36 | } |
| 37 | } |
| 38 | return false; |
| 39 | } |
| 40 | function render_page() { |
| 41 | global $siteguard_config, $siteguard_author_query; |
| 42 | |
| 43 | $opt_val_feature = $siteguard_config->get( self::OPT_NAME_FEATURE ); |
| 44 | $opt_val_restapi = $siteguard_config->get( self::OPT_NAME_RESTAPI ); |
| 45 | $opt_val_exclude = $this->cvt_camma2ret( $siteguard_config->get( self::OPT_NAME_EXCLUDE ) ); |
| 46 | if ( isset( $_POST['update'] ) && check_admin_referer( 'siteguard-menu-block-author-query-submit' ) ) { |
| 47 | $error = false; |
| 48 | $errors = siteguard_check_multisite(); |
| 49 | if ( is_wp_error( $errors ) ) { |
| 50 | echo '<div class="error settings-error"><p><strong>'; |
| 51 | echo esc_html( $errors->get_error_message() ); |
| 52 | echo '</strong></p></div>'; |
| 53 | $error = true; |
| 54 | } |
| 55 | if ( false === $error && false === $this->is_switch_value( $_POST[ self::OPT_NAME_FEATURE ] ) ) { |
| 56 | echo '<div class="error settings-error"><p><strong>'; |
| 57 | esc_html_e( 'ERROR: Invalid input value.', 'siteguard' ); |
| 58 | echo '</strong></p></div>'; |
| 59 | $error = true; |
| 60 | } |
| 61 | if ( false === $error ) { |
| 62 | $old_opt_val_feature = $opt_val_feature; |
| 63 | $old_opt_val_restapi = $opt_val_restapi; |
| 64 | $old_opt_val_exclude = $opt_val_exclude; |
| 65 | $opt_val_feature = sanitize_text_field( $_POST[ self::OPT_NAME_FEATURE ] ); |
| 66 | if ( isset( $_POST[ self::OPT_NAME_RESTAPI ] ) ) { |
| 67 | $opt_val_restapi = '1'; |
| 68 | } else { |
| 69 | $opt_val_restapi = '0'; |
| 70 | } |
| 71 | $opt_val_exclude = stripslashes( sanitize_textarea_field( $_POST[ self::OPT_NAME_EXCLUDE ] ) ); |
| 72 | $siteguard_config->set( self::OPT_NAME_FEATURE, $opt_val_feature ); |
| 73 | $siteguard_config->set( self::OPT_NAME_RESTAPI, $opt_val_restapi ); |
| 74 | $siteguard_config->set( self::OPT_NAME_EXCLUDE, $this->cvt_ret2camma( $opt_val_exclude ) ); |
| 75 | $siteguard_config->update(); |
| 76 | $opt_val_exclude = $this->cvt_camma2ret( $opt_val_exclude ); |
| 77 | ?> |
| 78 | <div class="updated"><p><strong><?php esc_html_e( 'Options saved.', 'siteguard' ); ?></strong></p></div> |
| 79 | <?php |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | echo '<div class="wrap">'; |
| 84 | echo '<img src="' . SITEGUARD_URL_PATH . 'images/sg_wp_plugin_logo_40.png" alt="SiteGuard Logo" />'; |
| 85 | echo '<h2>' . esc_html__( 'Block Author Query', 'siteguard' ) . '</h2>'; |
| 86 | $documentation_link = '<a href="' . esc_url( __( 'https://www.jp-secure.com/siteguard_wp_plugin_en/howto/author_query/', 'siteguard' ) ) . '" target="_blank">' . esc_html__( 'online documentation', 'siteguard' ) . '</a>'; |
| 87 | echo '<div class="siteguard-description">' |
| 88 | . sprintf( |
| 89 | /* translators: %1$s: Link to the online documentation. */ |
| 90 | esc_html__( 'See the %1$s.', 'siteguard' ), |
| 91 | $documentation_link |
| 92 | ) |
| 93 | . '</div>'; |
| 94 | ?> |
| 95 | <form name="form1" method="post" action=""> |
| 96 | |
| 97 | <table class="form-table"> |
| 98 | <tr> |
| 99 | <th scope="row" colspan="2"> |
| 100 | <ul class="siteguard-radios"> |
| 101 | <li> |
| 102 | <input type="radio" name="<?php echo self::OPT_NAME_FEATURE; ?>" id="<?php echo self::OPT_NAME_FEATURE . '_on'; ?>" value="1" <?php checked( $opt_val_feature, '1' ); ?> > |
| 103 | <label for="<?php echo self::OPT_NAME_FEATURE . '_on'; ?>"><?php echo esc_html_e( 'ON', 'siteguard' ); ?></label> |
| 104 | </li><li> |
| 105 | <input type="radio" name="<?php echo self::OPT_NAME_FEATURE; ?>" id="<?php echo self::OPT_NAME_FEATURE . '_off'; ?>" value="0" <?php checked( $opt_val_feature, '0' ); ?> > |
| 106 | <label for="<?php echo self::OPT_NAME_FEATURE . '_off'; ?>"><?php echo esc_html_e( 'OFF', 'siteguard' ); ?></label> |
| 107 | </li> |
| 108 | </ul> |
| 109 | <?php |
| 110 | $error = siteguard_check_multisite(); |
| 111 | if ( is_wp_error( $error ) ) { |
| 112 | echo '<p class="description">'; |
| 113 | echo esc_html( $error->get_error_message() ); |
| 114 | echo '</p>'; |
| 115 | } |
| 116 | ?> |
| 117 | </th> |
| 118 | </tr> |
| 119 | <tr> |
| 120 | <th scope="row"><?php esc_html_e( 'Option', 'siteguard' ); ?></th> |
| 121 | <td> |
| 122 | <input type="checkbox" name="<?php echo self::OPT_NAME_RESTAPI; ?>" id="<?php echo self::OPT_NAME_RESTAPI; ?>" value="1" <?php checked( $opt_val_restapi, '1' ); ?> > |
| 123 | <label for="<?php echo self::OPT_NAME_RESTAPI; ?>"><?php esc_html_e( 'Disable REST API', 'siteguard' ); ?></label> |
| 124 | </td> |
| 125 | </tr> |
| 126 | <tr> |
| 127 | <th scope="row"><label for="<?php echo self::OPT_NAME_EXCLUDE; ?>"><?php echo esc_html_e( 'Excluded REST API Namespaces', 'siteguard' ); ?></label></th> |
| 128 | <td> |
| 129 | <textarea name="<?php echo self::OPT_NAME_EXCLUDE; ?>" id="<?php echo self::OPT_NAME_EXCLUDE; ?>" class="siteguard-box-300" cols=40 rows=10 ><?php echo esc_textarea( $opt_val_exclude ); ?></textarea> |
| 130 | <p class="description"><?php esc_html_e( 'Specify REST API namespaces to exclude. Enter one per line. Existing plugin-based entries are still supported.', 'siteguard' ); ?></p></br> |
| 131 | <script> |
| 132 | function add_value() { |
| 133 | const crlf = String.fromCharCode(13) + String.fromCharCode(10); |
| 134 | const namespaces = document.form1.namespaces; |
| 135 | const excludes = document.form1.disable_restapi_exclude; |
| 136 | const num = namespaces.selectedIndex; |
| 137 | if (num < 0) { |
| 138 | return; |
| 139 | } |
| 140 | const sel = namespaces.options[num]; |
| 141 | const str = sel.value; |
| 142 | const sep = excludes.value.trim() === '' ? '' : crlf; |
| 143 | excludes.value = excludes.value + sep + str; |
| 144 | namespaces.removeChild(sel); |
| 145 | } |
| 146 | </script> |
| 147 | <select name="namespaces" class="siteguard-box-300" size="15"> |
| 148 | <?php |
| 149 | $val_excludes = explode( "\r\n", $opt_val_exclude ); |
| 150 | $namespaces = $this->get_rest_api_namespaces(); |
| 151 | if ( ! empty( $namespaces ) ) { |
| 152 | foreach ( $namespaces as $namespace ) { |
| 153 | if ( ! $this->is_rest_api_namespace_excluded( $namespace, $val_excludes ) ) { |
| 154 | ?> |
| 155 | <option value="<?php echo esc_attr( $namespace ); ?>"><?php echo esc_html( $namespace ); ?></option> |
| 156 | <?php |
| 157 | } |
| 158 | } |
| 159 | } |
| 160 | ?> |
| 161 | </select> |
| 162 | <input type="button" value="<?php esc_attr_e( 'Add Excluded Namespace', 'siteguard' ); ?>" onclick="add_value()" /> |
| 163 | <p class="description"><?php esc_html_e( 'This list shows REST API namespaces registered on this site. Select a namespace and add it to the exclusion list.', 'siteguard' ); ?></p></br> |
| 164 | </td> |
| 165 | </tr> |
| 166 | </table> |
| 167 | <input type="hidden" name="update" value="Y"> |
| 168 | <div class="siteguard-description"> |
| 169 | <?php |
| 170 | $author_query_example = '<code>' . esc_html( '/?author=123' ) . '</code>'; |
| 171 | printf( |
| 172 | /* translators: %1$s: Example author query. */ |
| 173 | esc_html__( 'Prevents username leakage through author queries such as %1$s. You can also disable the REST API to prevent username leakage through REST API requests. If disabling the REST API causes compatibility issues, add the affected REST API namespaces to the exclusion list.', 'siteguard' ), |
| 174 | $author_query_example |
| 175 | ); |
| 176 | ?> |
| 177 | </div> |
| 178 | <hr /> |
| 179 | <?php |
| 180 | wp_nonce_field( 'siteguard-menu-block-author-query-submit' ); |
| 181 | submit_button(); |
| 182 | ?> |
| 183 | </form> |
| 184 | </div> |
| 185 | <?php |
| 186 | } |
| 187 | } |
| 188 |