Reputation: 613
I use PDO to access my MySQL database, and want to use IN. But sadly it don't seam to work with prepare, so I wrote this function
function is_numeric_array($array){
if(!is_array($array))
return is_numeric($array);
if(is_array($array))
foreach($array as $int)
if(!is_numeric($int))
return false;
return true;
}
Then used it like this
if(!is_numeric_array($_SESSION['story'])){
die("Error, array contains non-integers");
}
$query = "(";
for($i = 0; $i<count($_SESSION['story']); $i++)
$query .= $_SESSION['story'][$i].(count($_SESSION['story'])-1 != $i ? "," : "");
$query .= ")";
//Collect all data needed
$stories = openConnection() -> query("SELECT * FROM `stories` WHERE `id` IN {$query}") -> fetchAll();
I know it, looks ugly. But I don't want any SQL injects.
Upvotes: 1
Views: 133
Reputation: 562681
You don't really have to test for the input being numeric, because in MySQL, any string e.g. '123abc'
in a numeric context (like being compared to an integer column id
) implicitly takes only the digits and ignores the rest. A non-numeric string like 'abc'
simply has the integer value 0 because there are no leading digits.
The point is, values are safe from SQL injection if you use query parameters. Whether the inputs come from $_SESSION or another source is irrelevant. $_SESSION is neither safe or unsafe with respect to SQL injection, it's how you pass the data to your query that matters.
I would also simplify the code to format the list of parameter placeholders:
$placeholders = implode(',', array_fill(1, count((array)$_SESSION['story']), '?'));
And forget about bindParam(), just pass the array to execute()
.
//Collect all data needed
$storyQuery = openConnection() -> prepare("SELECT * FROM `stories`
WHERE `id` IN ({$placeholders})");
$storyQuery -> execute((array)$_SESSION['story']);
$story = $storyQuery -> fetchAll();
Re your comment:
In PDO, you can use either named parameters like :id
, or you can use positional parameters, which are always ?
(but don't mix these two types in a given query, use one or the other).
Passing an array to execute()
automatically binds the array elements to the parameters. A simple array (i.e. indexed by integers) is easy to bind to positional parameters.
If you use named parameters, you must pass an associative array where the keys of the array match the parameter names. The array keys may optionally be prefixed with :
but it's not required.
If you're new to PDO, it really pays to read the documentation. There are code examples and everything!
Upvotes: 4
Reputation: 1631
$_SESSION is just a way to store data on server over a session. It's not direct related with SQL injection.
Upvotes: 1
Reputation: 3576
Even if it's a cookie or a session , the hash that I store is alphanumeric only, for security purposes. When I'm checking the cookie/session against any type of inject / modification , I use ctype_alnum:
if (ctype_alnum($_SESSION['value']))
// exec code
else
// trigger_error
This way, no matter who is setting the SESSION value (you or the client, if you give him the possibility to), there wont be any case in which non-alphanumeric chars like comma
, quotes
, double quotes
or whatever will be inserted.
Upvotes: -2