[wp-trac] [WordPress Trac] #54042: Extending wpdb::prepare() to support IN() operator (was: Extending wpdb::prepare() to support table/field names, and IN() operator)
WordPress Trac
noreply at wordpress.org
Sun Oct 30 12:25:20 UTC 2022
#54042: Extending wpdb::prepare() to support IN() operator
-------------------------------------------------+-------------------------
Reporter: craigfrancis | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Future
| Release
Component: Database | Version:
Severity: normal | Resolution:
Keywords: has-patch dev-feedback needs- | Focuses:
testing early has-unit-tests |
-------------------------------------------------+-------------------------
Description changed by craigfrancis:
Old description:
> wpdb::prepare() has really helped avoid SQL Injection vulnerabilities,
> ensuring most variables are escaped correctly.
>
> But it does not support table/field names, so developers need to
> implement their own escaping, which is not always done safely.
> [https://github.com/WordPress/WordPress/blob/988c8be693e0d12aeacae30f1d4bebfb98f7e5a0
> /wp-includes/wp-db.php#L2778 If this example was copied], with no other
> checks, there could be an issue if `$table` included backtick or other
> invalid characters:
>
> {{{#!php
> <?php
> $table_parts = explode( '.', $table );
> $table = '`' . implode( '`.`', $table_parts ) . '`'; // INSECURE?
> }}}
>
> Likewise, it's also fairly common to make a mistake when including values
> with the `IN ()` operator, for example:
>
> {{{#!php
> <?php
> $where = 'WHERE id IN (' . implode( ',', $ids ) . ')'; // INSECURE?
> }}}
>
> Developers need to be sure that `$ids` has come from a trusted source, or
> use something like `wp_parse_id_list()` or `array_map('intval', $ids)`.
>
> ----
>
> Considering the `wpdb::prepare()` documentation says it "Uses
> sprintf()-like syntax", could we add a couple of placeholders to safely
> include these values? e.g.
>
> {{{#!php
> <?php
> $wpdb->prepare('SELECT * FROM %i WHERE ID IN (%...d)', $table, $ids);
> }}}
>
> Where `%i` would be used for Identifiers (e.g. table/field names), where
> the value would be quoted with backticks, and invalid characters removed.
>
> And `%...d` or `%...s` would safely (and easily) include a comma
> separated array of integers or strings - taking the idea of using '...'
> for variadics in PHP.
>
> https://dev.mysql.com/doc/refman/8.0/en/identifiers.html
> https://dev.mysql.com/doc/refman/8.0/en/comparison-
> operators.html#operator_in
New description:
wpdb::prepare() helps avoid SQL Injection vulnerabilities, by escaping
most variables correctly.
WP 6.1 added support for Identifiers (table/field names) with `%i`, in
#52506.
But it's also fairly common to make a mistake to include values with the
`IN()` operator, for example:
{{{#!php
<?php
$where = 'WHERE id IN (' . implode( ',', $ids ) . ')'; // INSECURE?
}}}
Developers need to be sure `$ids` has come from a trusted source, or use
something like `wp_parse_id_list()` or `array_map('intval', $ids)`.
----
Maybe support could be added with:
{{{#!php
<?php
$wpdb->prepare('WHERE id IN (%...d)', $ids);
}}}
Where `%...d` or `%...s` would safely (and easily) include a comma
separated array of integers or strings - taking the idea of using '...'
for variadics in PHP.
https://wiki.php.net/rfc/variadics
https://www.php.net/manual/en/functions.arguments.php#functions.variable-
arg-list
https://dev.mysql.com/doc/refman/8.0/en/comparison-
operators.html#operator_in
--
--
Ticket URL: <https://core.trac.wordpress.org/ticket/54042#comment:38>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list