Changeset 3448278
- Timestamp:
- 01/27/2026 11:48:13 PM (6 weeks ago)
- Location:
- snow-monkey-forms/trunk
- Files:
-
- 7 edited
-
App/Helper.php (modified) (1 diff)
-
App/Model/Csrf.php (modified) (2 diffs)
-
App/Model/Directory.php (modified) (7 diffs)
-
App/Rest/Route/View.php (modified) (1 diff)
-
changelog.txt (modified) (1 diff)
-
readme.txt (modified) (1 diff)
-
snow-monkey-forms.php (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
snow-monkey-forms/trunk/App/Helper.php
r3089760 r3448278 129 129 ); 130 130 } 131 132 /** 133 * Return true when form ID format is valid. 134 * 135 * @param mixed $form_id Form ID. 136 * @return boolean 137 */ 138 protected static function _is_valid_form_id_format( $form_id ) { 139 if ( ! is_scalar( $form_id ) ) { 140 return false; 141 } 142 143 $form_id = (string) $form_id; 144 if ( '' === $form_id || ! preg_match( '/^[0-9]+$/', $form_id ) ) { 145 return false; 146 } 147 148 $form_id = absint( $form_id ); 149 if ( 0 === $form_id ) { 150 return false; 151 } 152 153 return true; 154 } 155 156 /** 157 * Validate and sanitize form ID. 158 * 159 * @param mixed $form_id Form ID. 160 * @return int|false 161 */ 162 public static function sanitize_form_id( $form_id ) { 163 if ( false === static::_is_valid_form_id_format( $form_id ) ) { 164 return false; 165 } 166 167 return absint( $form_id ); 168 } 169 170 /** 171 * Return true when token format is valid. 172 * 173 * @param mixed $token Token value. 174 * @return boolean 175 */ 176 public static function is_valid_token_format( $token ) { 177 if ( ! is_scalar( $token ) ) { 178 return false; 179 } 180 181 $token = (string) $token; 182 if ( '' === $token ) { 183 return false; 184 } 185 186 return (bool) preg_match( '|^[a-z0-9]+$|', $token ); 187 } 131 188 } -
snow-monkey-forms/trunk/App/Model/Csrf.php
r3172643 r3448278 7 7 8 8 namespace Snow_Monkey\Plugin\Forms\App\Model; 9 10 use Snow_Monkey\Plugin\Forms\App\Helper; 9 11 10 12 class Csrf { … … 28 30 } 29 31 30 if ( ! preg_match( '|^[a-z0-9]+$|',$posted_token ) ) {32 if ( ! Helper::is_valid_token_format( $posted_token ) ) { 31 33 return false; 32 34 } -
snow-monkey-forms/trunk/App/Model/Directory.php
r3172643 r3448278 12 12 use Snow_Monkey\Plugin\Forms\App\Model\Csrf; 13 13 use Snow_Monkey\Plugin\Forms\App\Model\Meta; 14 use Snow_Monkey\Plugin\Forms\App\Helper; 14 15 15 16 class Directory { … … 46 47 $saved_token = Csrf::saved_token(); 47 48 48 if ( ! preg_match( '|^[a-z0-9]+$|',$saved_token ) ) {49 if ( ! Helper::is_valid_token_format( $saved_token ) ) { 49 50 throw new \RuntimeException( 50 51 sprintf( … … 53 54 ) 54 55 ); 56 } 57 58 $form_id = Helper::sanitize_form_id( $form_id ); 59 if ( false === $form_id ) { 60 throw new \RuntimeException( '[Snow Monkey Forms] Invalid form ID.' ); 55 61 } 56 62 … … 112 118 } 113 119 120 if ( ! static::_is_within_expected_dir( $dir ) ) { 121 return false; 122 } 123 114 124 return static::_remove_children( $dir, $force ); 115 125 } … … 117 127 /** 118 128 * Remove child directories and files. 129 * Callers should ensure the path is within the upload base directory. 119 130 * 120 131 * @param string $dir Target directory. … … 208 219 */ 209 220 public static function remove( $file ) { 221 if ( ! static::_is_within_expected_dir( $file ) ) { 222 return false; 223 } 224 210 225 $fileinfo = new SplFileInfo( $file ); 211 226 … … 243 258 $survival_time = apply_filters( 'snow_monkey_forms/saved_files/survival_time', 60 * 15 ); 244 259 return ! $mtime || time() > $mtime + $survival_time; 260 } 261 262 /** 263 * Return true when path is inside upload base directory. 264 * 265 * @param string $path Target path. 266 * @return boolean 267 */ 268 protected static function _is_within_expected_dir( $path ) { 269 $base_dir = realpath( static::get() ); 270 $realpath = realpath( $path ); 271 272 if ( false === $base_dir || false === $realpath ) { 273 return false; 274 } 275 276 $token = Csrf::saved_token(); 277 if ( ! Helper::is_valid_token_format( $token ) ) { 278 return false; 279 } 280 281 $form_id = Helper::sanitize_form_id( Meta::get_formid() ); 282 if ( false === $form_id ) { 283 return false; 284 } 285 286 $base_dir = wp_normalize_path( $base_dir ); 287 $realpath = wp_normalize_path( $realpath ); 288 289 $user_dir = wp_normalize_path( 290 path_join( 291 path_join( $base_dir, $token ), 292 (string) $form_id 293 ) 294 ); 295 $user_dir = untrailingslashit( $user_dir ); 296 $user_dir_slash = trailingslashit( $user_dir ); 297 298 return $realpath === $user_dir || 0 === strpos( $realpath, $user_dir_slash ); 245 299 } 246 300 -
snow-monkey-forms/trunk/App/Rest/Route/View.php
r3172643 r3448278 188 188 189 189 if ( 'input' === $method || 'complete' === $method || 'systemerror' === $method ) { 190 // If the token cannot be verified, 191 // the file deletion process will not be performed. 192 if ( ! Csrf::validate( Meta::get_token() ) ) { 193 return $controller->send(); 194 } 195 190 196 $user_dirpath = Directory::generate_user_dirpath( $this->setting->get( 'form_id' ), false ); 191 197 -
snow-monkey-forms/trunk/changelog.txt
r3431387 r3448278 1 1 *** Changelog *** 2 3 = 12.0.4 = 4 * Fixed a path traversal vulnerability. We strongly encourage you to update to it immediately. 2 5 3 6 = 12.0.3 = -
snow-monkey-forms/trunk/readme.txt
r3431387 r3448278 3 3 Donate link: https://www.amazon.co.jp/registry/wishlist/39ANKRNSTNW40 4 4 Tags: gutenberg, block, blocks, editor, gutenberg blocks, page builder, form, forms, mail, email, contact 5 Stable tag: 12.0. 35 Stable tag: 12.0.4 6 6 Requires at least: 6.8 7 7 Tested up to: 6.9 -
snow-monkey-forms/trunk/snow-monkey-forms.php
r3431387 r3448278 2 2 /** 3 3 * Plugin name: Snow Monkey Forms 4 * Version: 12.0. 34 * Version: 12.0.4 5 5 * Description: The Snow Monkey Forms is a mail form plugin for the block editor. 6 6 * Author: inc2734 … … 21 21 use Snow_Monkey\Plugin\Forms\App\Model\Directory; 22 22 use Snow_Monkey\Plugin\Forms\App\Model\Meta; 23 use Snow_Monkey\Plugin\Forms\App\Helper; 23 24 use Snow_Monkey\Plugin\Forms\App\Rest; 24 25 use Snow_Monkey\Plugin\Forms\App\Service\Admin\Admin; … … 184 185 185 186 // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 186 $form_id = isset( $_SERVER['HTTP_X_SMF_FORMID'] ) ? wp_unslash( $_SERVER['HTTP_X_SMF_FORMID'] ) : false; 187 $form_id = isset( $_SERVER['HTTP_X_SMF_FORMID'] ) 188 ? wp_unslash( $_SERVER['HTTP_X_SMF_FORMID'] ) 189 : ''; 187 190 // phpcs:enable 188 191 189 if ( ! $form_id ) { 192 $form_id = Helper::sanitize_form_id( $form_id ); 193 if ( false === $form_id ) { 190 194 return new WP_REST_Response( 'Bad request.', 400 ); 191 195 } … … 221 225 222 226 if ( isset( $data[ Meta::get_key() ] ) ) { 227 $raw_form_id = isset( $data[ Meta::get_key() ]['formid'] ) 228 ? $data[ Meta::get_key() ]['formid'] 229 : ''; 230 231 $raw_form_id = Helper::sanitize_form_id( $raw_form_id ); 232 if ( false === $raw_form_id ) { 233 return new WP_REST_Response( 'Bad request.', 400 ); 234 } 235 236 $data[ Meta::get_key() ]['formid'] = $raw_form_id; 223 237 $data[ Meta::get_key() ]['sender'] = wp_get_current_user(); 224 238 }
Note: See TracChangeset
for help on using the changeset viewer.