PHP: While loop not working after adjusting SELECT

2019-03-02 12:53发布

I am trying to set up PHP queries for MySQL in a way to prevent SQL injection (standard website).

I had a couple of INSERT queries where changing this worked well but on the following SELECT I keep getting an error since the update and it looks like the while loop doesn't work with the changes I made (it works well without using the statement as in the old code).

Can someone tell me what I am doing wrong here ?

New PHP:

$stmt = $conn->prepare("SELECT ? FROM TranslationsMain WHERE location LIKE '%calendar weekday%' ORDER BY sortOrder, ?");
$stmt->bind_param('s', $selectedLang);
$stmt->execute();
$result = $stmt->get_result();  
while($arrCalWeekdays = $result->fetch_assoc()){
    $calWeekdays[] = $arrCalWeekdays;
}
$conn->close();

Old PHP (changed part):

$sql = "SELECT " . $selectedLang . " FROM TranslationsMain WHERE location LIKE '%calendar weekday%' ORDER BY sortOrder, " . $selectedLang;
$result = $conn->query($sql);  
while($arrCalWeekdays = $result->fetch_assoc()){
    $calWeekdays[] = $arrCalWeekdays;
}
$conn->close();

Error message:

Fatal error: Call to a member function fetch_assoc() on a non-object in /homepages/21/d580042014/htdocs/myform.php on line 21

Many thanks in advance.

1条回答
我欲成王,谁敢阻挡
2楼-- · 2019-03-02 13:26

You cannot bind column and table names, only data. You need to specify the table and then bind for your '%calendar weekday%'.

$stmt = $conn->prepare("SELECT " . $selectLang . " FROM `TranslationsMain` WHERE `location` LIKE ? ORDER BY `sortOrder`, " . $selectedLang);
$stmt->bind_param('s', $calendar_weekday);

If you want to use dynamic table / column names you should perform the minimal white-listing of those items. You can build a dynamic white list by asking the database what columns are valid for a given database table. For example:

SELECT `COLUMN_NAME` 
FROM `INFORMATION_SCHEMA`.`COLUMNS` 
WHERE `TABLE_SCHEMA` = `database_name`
AND `TABLE_NAME` = `table_name`

You could place all of this information in arrays and then check to make sure the table / column names used in the query are in the arrays. Extra consideration for table and column names should be performed, making sure that no key / reserved words are used for these names.

Finally, use backticks around the validated table / column names when calling the values for the dynamic queries. This will cover any potential changes to the key / reserved words list and provides an additional layer of protection.

查看更多
登录 后发表回答