skip to Main Content

So I’m left a little confused why on WordPress there is a method like esc_like():
https://developer.wordpress.org/reference/classes/wpdb/esc_like/
The advice is that parameter that will be used by LIKE must be escaped with esc_like() to make it safe, like this:

$wild = '%';
$find = 'only 43% of planets';
$like = $wild . $wpdb->esc_like( $find ) . $wild;
$sql  = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like);

But why:

$sql  = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like);

Wouldn’t be enough in this case to properly prepare that LIKE parameter? I don’t understand where it could go wrong witout using esc_like and is it really that something can cause vulnerability if used without that esc_like method.

To my understanding $wpdb->prepare should be enough, but lately learning about this I’m not sure.

So the main question is, does it impose very serious security risk if I use it without $wpdb->esc_like() method?

3

Answers


  1. You’re right that for preventing SQL injection you have to use a query parameter.

    The purpose of "escaping" a string for LIKE isn’t the same purpose as preventing SQL injection.

    The % and _ characters are wildcards in a LIKE expression. But what if you want to match those characters literally?

    SQL provides a solution:

    https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like

    To test for literal instances of a wildcard character, precede it by the escape character.

    The default escape character is .

    Login or Signup to reply.
  2. WordPress uses a unique and incompletely documented scheme for doing $wpdb->prepare() processing. Display some SQL prepared that way and you’ll see what I mean — long uniqueid strings appear, and are later straightened out during the ->execute() phase.

    ->esc_like() is part of that scheme. And, of course a lot of this is in aid of injection prevention.

    Login or Signup to reply.
  3. You must escape it if the value it’s a user input or taken from a database or $SERVER global variable.
    I use it this way:

    $post_id = $wpdb->get_var(
                    $wpdb->prepare(
                        "SELECT ID from {$wpdb->prefix}posts     WHERE post_name LIKE %s LIMIT 1", 
                        '%' . $wpdb->esc_like( $basename ) . '%'
                    )
                );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search