Home >Database >Mysql Tutorial >How Can We Securely Use Parameterized Table Names in Prepared Statements to Prevent SQL Injection?
Parameterized Table Names in Prepared Statements: A Dilemma
Although mysqli_stmt_bind_param has proven effective for protecting against SQL injection, it encounters limitations when variables affecting table names are involved. As illustrated in the provided code snippet:
function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ) { $statement = $mysqli->prepare("INSERT INTO " .$new_table . " VALUES (?,?,?,?,?,?,?);"); mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ); $statement->execute(); }
The problematic concatenation of $new_table introduces vulnerability to SQL injection. Attempts to replace this with another placeholder, as shown in the following snippet, fail:
function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ) { $statement = $mysqli->prepare("INSERT INTO (?) VALUES (?,?,?,?,?,?,?);"); mysqli_stmt_bind_param( $statment, 'ssssisss', $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ); $statement->execute(); }
The Limitations of Prepared Statements
The core issue lies in the inability of prepared statements to protect parameters that define the SQL statement's structure, such as table names. This is because prepared statements exclusively allow parameters for values that do not alter the statement's meaning. Since table names determine the validity of the SQL statement, modifying them during execution would potentially invalidate it.
Even with database interfaces like PDO that emulate prepared statements by substituting parameters before sending them to the database, placeholder values are still strings enclosed within the SQL statement. As a result, SELECT FROM ? with mytable as the parameter would ultimately send SELECT FROM 'mytable' to the database, rendering it invalid.
Mitigating the Risk
The most secure approach remains using $mytable within a string, but it must be accompanied by a white-list of tables against which the user input is checked. This prevents malicious actors from executing SQL statements on arbitrary tables. Therefore, the following code demonstrates a secure implementation:
if (whitelisted_tables($mytable)) { $statement = $mysqli->prepare("INSERT INTO $mytable VALUES (?,?,?,?,?,?,?);"); mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol ); $statement->execute(); }
The above is the detailed content of How Can We Securely Use Parameterized Table Names in Prepared Statements to Prevent SQL Injection?. For more information, please follow other related articles on the PHP Chinese website!