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
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
The default escape character is
.
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.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: