Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safely using prepared statements to query database

I'm trying to write a function that is versatile in the queries it is allowed to make, but also safe from injection. The code below throws an error as is, but if I run it with 'name' instead of ':field' it works fine.

$field = "name";
$value = "joe";

function selectquery($field, $value)
  {
  global $dbcon;

  $select = $dbcon->prepare('SELECT * FROM tester1 WHERE :field = :value');
  if($select->execute(array(':field' => $field, ':value' => $value)));
    {
    $row = $select->fetch();
    for ($i=0; $i<3; $i++)
      {
      echo $row[$i]."\n";
      }
    }  
  }

How would I allow the table/fields/values to be changed, without allowing injection attacks? mysql_real_escape_string() seems kind of like a step backwards. Any ideas?

like image 203
JoeCortopassi Avatar asked Oct 15 '22 10:10

JoeCortopassi


1 Answers

I may be mistaken, but I don't believe you can supply fields as parameters in PDO.

Why not just specify it as argument to the function? Unlike the data being supplied by the user, the fields are finite, well defined and don't change often. As in

selectquery('name',$value);

and have your query be

$field = "name";
$value = "joe";

function selectquery($field, $value)
  {
  global $dbcon;

  $select=$dbcon->prepare("SELECT * FROM tester1 WHERE $field = :value");
  if($select->execute(array(':value' => $value)));
 //etcetera  

Since you're supplying the field name for the function call yourself, this is safe unless you're worried you are going to attack yourself with SQL injection.

If for some odd reason the name of the field is coming from user input, you could make an array of allowed fields. That way, you're safe from injection because the values can only come from your array. I don't know why the field name would be coming from user input and thus be untrusted, unless perhaps you're making an API? Other wise there's probably a better way to achieve the goal.

Anyhow, this would be a potential solution, to use a whitelist for table names:

$field = "name";
$value = "joe";

$allowed_fields=array('name','other_name','sandwich');

function selectquery($field_name, $value)
  {
  global $dbcon,$allowed_fields;

  if(!in_array($field_name,$allowed_fields)){ return false; }
  else{ $field=$field_name; }

  $select=$dbcon->prepare("SELECT * FROM tester1 WHERE $field = :value");
  if($select->execute(array(':value' => $value)));
  //etcetera
like image 71
JAL Avatar answered Oct 27 '22 22:10

JAL