Please Seniors,
I have problem with searching the database using prepared statement, i have some variables which holds ip as column name and the ip address which is 127.0.01 for local host as ip values but when i use it to query the database it shows nothing, even when there is 16 rows that has that ip address in the table.
Please what am i doing wrong here, if i run those variables directly without using prepare or binding then it prints out 16 rows which is what is actually in the database but if use param nothing works.
Also i would like to know how to get the total row count of the affected rows using para binding too
something like this
$mygive = $con->prepare("SELECT COUNT(*) FROM givetable WHERE ? = ?");
It separates the data values from the sql query syntax, so that any sql special characters in the data cannot break the sql query syntax, which is how sql injection is accomplished.
It eliminates the extra communication time, between php and the database server, and the sql parsing and planning time, on the database server, in the rare cases where you execute the same query more than once. (I did a benchmark back when the mysqli extension came out, and this saves around 5% for a mass execution on an insert query.)
Database column names are not data values, they are part of the sql query syntax, specifically they are identifiers (database names, table names, and column names.) You cannot supply a column name via a prepared query place-holder.
If the column name, ip, is static, i.e. it will always be that column, you would just build the sql query statement with that column name in it. If the column name is dynamic, i.e. it is selected/specified based on an external user input, you MUST validate that it is exactly and only a permitted choice before building the sql query with it in it.
The only thing i can ensure it to make sure his $give contains any of the column names.
But how do you know which column was chosen?
Secondly i don’t trust my validation of if in array, i want param binding as a second layer attack proof
The only way you could (untested) ‘fool’ an in_array() comparison would be to take advantage of php’s number casting in comparisons. If you have columns with numerical names (never recommend) and you list the numerical columns in the array as literal numbers, rather than strings containing numbers, php will cast the input value being tested to a number, which would match a permitted column name, but the full value that you put into the sql query could also contain sql. While this involves a collection of bad practices, someone could unknowingly create this situation.
To prevent this possibility, add a level of indirection, where the selection is actually an id, starting at one, corresponding to the column names. You would then use the submitted id to give the actual column name that you put into the sql query.
I think i found a walk around this, in addition to validating if keyword is in array, i will also not take the entered variable directly to the database.
E.g
$supportedWords = array('city', 'state', 'country');
// validations
if(!in_array($give, $supportedWords)){
//failed validation code function goes here
}
// Now reconvert the variables
if($give === 'city'){
$newgive == 'city';
}elseif($give === 'state'){
$newgive == 'state';
}elseif($give === 'country'){
$newgive == 'country';
}else{
$newgive = 'country'; // to make it a default column
}
// Now my SQL will now be like this
$mygive = $con->prepare("SELECT * FROM givetable WHERE $newgive = ?");
$mygive->bind_param('s', $givevalue);
I think at this point am much safer, please if anyone spot something unsafe in the Code please indicate, Thank You Very Much.