wordpress wp-includes/http.php漏洞修复

在wp-includes/http.php中有一处检验规则漏洞,文件中的wp_http_validate_url函数对输入IP验证不当,导致黑客可构造类似于012.10.10.10这样的畸形IP绕过验证,进行SSRF。

源代码的第534行中,调用了preg_match方法对传入的IP地址进行校验,这里可以构造一个畸形的IP地址,以跳过if去执行else,从而使用了gethostbyname。

核心问题出在此正则表达式的校验比较弱,正确的IPv4地址是xxx.xxx.xxx.xxx,但是首位不能是0。

 

解决办法-:增强正则表达式。

^(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$

function wp_http_validate_url( $url ) {
 509      $original_url = $url;
 510      $url = wp_kses_bad_protocol( $url, array( 'http', 'https' ) );
 511      if ( ! $url || strtolower( $url ) !== strtolower( $original_url ) )
 512          return false;
 513  
 514      $parsed_url = @parse_url( $url );
 515      if ( ! $parsed_url || empty( $parsed_url['host'] ) )
 516          return false;
 517  
 518      if ( isset( $parsed_url['user'] ) || isset( $parsed_url['pass'] ) )
 519          return false;
 520  
 521      if ( false !== strpbrk( $parsed_url['host'], ':#?[]' ) )
 522          return false;
 523  
 524      $parsed_home = @parse_url( get_option( 'home' ) );
 525  
 526      if ( isset( $parsed_home['host'] ) ) {
 527          $same_host = ( strtolower( $parsed_home['host'] ) === strtolower( $parsed_url['host'] ) || 'localhost' === strtolower( $parsed_url['host'] ) );
 528      } else {
 529          $same_host = false;
 530      }
 531  
 532      if ( ! $same_host ) {
 533          $host = trim( $parsed_url['host'], '.' );
 534          if ( preg_match( '#^(([1-9]?\d|1\d\d|25[0-5]|2[0-4]\d)\.){3}([1-9]?\d|1\d\d|25[0-5]|2[0-4]\d)$#', $host ) ) {
 535              $ip = $host;
 536          } else {
 537              $ip = gethostbyname( $host );
 538              if ( $ip === $host ) // Error condition for gethostbyname()
 539                  $ip = false;
 540          }
 541          if ( $ip ) {
 542              $parts = array_map( 'intval', explode( '.', $ip ) );
 543              if ( 127 === $parts[0] || 10 === $parts[0] || 0 === $parts[0]
 544                  || ( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] )
 545                  || ( 192 === $parts[0] && 168 === $parts[1] )
 546              ) {
 547                  // If host appears local, reject unless specifically allowed.
 548                  /**
 549                   * Check if HTTP request is external or not.
 550                   *
 551                   * Allows to change and allow external requests for the HTTP request.
 552                   *
 553                   * @since 3.6.0
 554                   *
 555                   * @param bool   false Whether HTTP request is external or not.
 556                   * @param string $host IP of the requested host.
 557                   * @param string $url  URL of the requested host.
 558                   */
 559                  if ( ! apply_filters( 'http_request_host_is_external', false, $host, $url ) )
 560                      return false;
 561              }
 562          }
 563      }
 564  
 565      if ( empty( $parsed_url['port'] ) )
 566          return $url;
 567  
 568      $port = $parsed_url['port'];
 569      if ( 80 === $port || 443 === $port || 8080 === $port )
 570          return $url;
 571  
 572      if ( $parsed_home && $same_host && isset( $parsed_home['port'] ) && $parsed_home['port'] === $port )
 573          return $url;
 574  
 575      return false;
 576  }

发表评论

电子邮件地址不会被公开。