CVE-2017-14723 (published 2017-09-23T20:29Z)

Before version 4.8.2, WordPress mishandled % characters and additional placeholder values in $wpdb->prepare, and thus did not properly address the possibility of plugins and themes enabling SQL injection attacks.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-89
cwe_name: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/WordPress/WordPress
commit_details: repo_url: https://github.com/WordPress/WordPress
author: Aaron Campbell
author_date: 2017-09-19 17:56:45+00:00
msg: Database: Hardening to bring `wpdb::prepare()` inline with documentation.

`wpdb::prepare()` supports %s, %d, and %F as placeholders in the query string. Any other non-escaped % will be escaped.


Built from https://develop.svn.wordpress.org/trunk@41496


git-svn-id: http://core.svn.wordpress.org/trunk@41329 1a063a9b-81f0-0310-95a4-ce76da25c4cd
repository: repo_url: https://github.com/WordPress/WordPress
repo_name: WordPress/WordPress
description: WordPress, Git-ified. This repository is just a mirror of the WordPress subversion repository. Please do not send pull requests. Submit pull requests to https://github.com/WordPress/wordpress-develop and patches to https://core.trac.wordpress.org/ instead.
repo_language: PHP
owner: WordPress
file_changes: filename: version.php
change_type: ModificationType.MODIFY
diff: @@ -4,7 +4,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '4.9-alpha-41483';
+$wp_version = '4.9-alpha-41496';
 
 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.

programming_language: PHP
filename: wp-db.php
change_type: ModificationType.MODIFY
diff: @@ -1252,6 +1252,7 @@ class wpdb {
 		$query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
 		$query = preg_replace( '|(?<!%)%f|' , '%F', $query ); // Force floats to be locale unaware
 		$query = preg_replace( '|(?<!%)%s|', "'%s'", $query ); // quote the strings, avoiding escaped strings like %%s
+		$query = preg_replace( '/%(?:%|$|([^dsF]))/', '%%\\1', $query ); // escape any unescaped percents 
 		array_walk( $args, array( $this, 'escape_by_ref' ) );
 		return @vsprintf( $query, $args );
 	}
@@ -2821,7 +2822,8 @@ class wpdb {
 					}
 
 					if ( is_array( $value['length'] ) ) {
-						$queries[ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING $charset ), %.0f ) USING $connection_charset )", $value['value'], $value['length']['length'] );
+						$length = sprintf( '%.0f', $value['length']['length'] );
+						$queries[ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING $charset ), $length ) USING $connection_charset )", $value['value'] );
 					} else if ( 'binary' !== $charset ) {
 						// If we don't have a length, there's no need to convert binary - it will always return the same result.
 						$queries[ $col ] = $this->prepare( "CONVERT( CONVERT( %s USING $charset ) USING $connection_charset )", $value['value'] );

programming_language: PHP
repo_url: https://github.com/WordPress/WordPress
commit_details: repo_url: https://github.com/WordPress/WordPress
author: Aaron Campbell
author_date: 2017-09-19 14:48:47+00:00
msg: Database: Hardening for `wpdb::prepare()`

Previously if you passed an array of values for placeholders, additional values could be passed as well. Now additional values will be ignored.


Built from https://develop.svn.wordpress.org/trunk@41470


git-svn-id: http://core.svn.wordpress.org/trunk@41303 1a063a9b-81f0-0310-95a4-ce76da25c4cd
repository: repo_url: https://github.com/WordPress/WordPress
repo_name: WordPress/WordPress
description: WordPress, Git-ified. This repository is just a mirror of the WordPress subversion repository. Please do not send pull requests. Submit pull requests to https://github.com/WordPress/wordpress-develop and patches to https://core.trac.wordpress.org/ instead.
repo_language: PHP
owner: WordPress
file_changes: filename: version.php
change_type: ModificationType.MODIFY
diff: @@ -4,7 +4,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '4.9-alpha-41457';
+$wp_version = '4.9-alpha-41470';
 
 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.

programming_language: PHP
filename: wp-db.php
change_type: ModificationType.MODIFY
diff: @@ -1236,9 +1236,18 @@ class wpdb {
 
 		$args = func_get_args();
 		array_shift( $args );
+
 		// If args were passed as an array (as in vsprintf), move them up
-		if ( isset( $args[0] ) && is_array($args[0]) )
+		if ( is_array( $args[0] ) && count( $args ) == 1 ) {
 			$args = $args[0];
+		}
+
+		foreach ( $args as $arg ) {
+			if ( ! is_scalar( $arg ) ) {
+				_doing_it_wrong( 'wpdb::prepare', sprintf( __( 'Unsupported value type (%s).' ), gettype( $arg ) ), '4.8.2' );
+			}
+		}
+
 		$query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it
 		$query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
 		$query = preg_replace( '|(?<!%)%f|' , '%F', $query ); // Force floats to be locale unaware

programming_language: PHP