как использовать bigint для предотвращения инъекции sql в php?

Я использую php и запускаю sql-запросы на сервере mysql. чтобы предотвратить инъекции sql, я использую mysql_real_escape_string.

я также использую (int) для приведения чисел следующим образом:

$desired_age = 12;
$query = "select id from users where (age > ".(int)$desired_age.")";
$result = mysql_query($query);

та работа.

Но когда переменная содержит большие числа, их приведение не выполняется, поскольку они больше, чем int.

$user_id = 5633847511239487;
$query = "select age from users where (id = ".(int)$user_id.")";
$result = mysql_query($query);
// this will not produce the desired result, 
// since the user_id is actually being cast to int

Есть ли другой способ приведения большого числа (например, BIGINT), кроме использования mysql_real_escape_string, когда дело доходит до предотвращения внедрения SQL?


person yehuda    schedule 08.07.2010    source источник
comment
здесь тоже есть подвох $user_id = 5633847511239487; не будет хранить то, что вы думаете, и нет способа вернуть это число bigint обратно, вам нужно сохранить его как строку, а не как int - $user_id = '5633847511239487';   -  person nathan    schedule 08.07.2010
comment
Вместо того, чтобы заниматься очисткой входных данных, используйте параметризованные запросы, чтобы избежать SQL-инъекций. bobby-tables.com/php.html показывает, как это делается на PHP.   -  person Andy Lester    schedule 13.12.2012


Ответы (6)


Вы можете использовать что-то вроде:

preg_replace('/[^0-9]/','',$user_id);

чтобы заменить все нечисловые символы в вашей строке. Но на самом деле в этом нет необходимости, просто используйте mysql_real_escape_string(), поскольку ваше целочисленное значение все равно будет преобразовано в строку после построения $query.

person michael    schedule 08.07.2010
comment
... просто публикуя это в отличие от is_numeric, который также допускает значения с плавающей запятой, такие как 1,12, что может быть не совсем тем, чего хотел yehuda :) - person michael; 08.07.2010
comment
я протестировал решение preg_replace и обнаружил, что оно ограничено 14 символами. и поэтому я использую mysql_real_escape_string как для строкового, так и для числового ввода пользователя. спасибо всем - person yehuda; 09.07.2010

Если вы создаете идентификатор пользователя самостоятельно, нет необходимости приводить его для MySQL, поскольку нет возможности SQL-инъекции или других проблем со строками.

Если это введенное пользователем значение, используйте filter_var() (или < a href="http://www.php.net/is_numeric" rel="noreferrer">is_numeric()), чтобы убедиться, что это число, а не строка.

person John Conde    schedule 08.07.2010
comment
Собирался сказать то же самое, кастинг полезен, но только для таких вещей, как числовые значения в строках запросов, которые не являются результатом пользовательского ввода. Это останавливает людей, манипулирующих строкой запроса. Что касается пользовательского ввода, проверка того, является ли значение числовым, является лучшим вариантом, поскольку это позволяет вам давать дружественные сообщения. - person Tom Gullen; 08.07.2010

Подтвердите ввод. Не просто избегайте его, подтвердите его, если это число. Есть пара функций PHP, которые делают свое дело, например, is_numeric() — определяет, является ли переменная числом или числовой строкой.

http://www.php.net/is_numeric

person dwich    schedule 08.07.2010

Используйте подготовленные параметризованные операторы на стороне сервера (и, таким образом, устраните необходимость в xyz_real_escape_string()) и/или обработайте идентификатор как строку. Сервер MySQL имеет встроенные правила для преобразования строк‹->чисел, и если вы решите изменить тип/структуру поля id, вам также не нужно менять php-код. Если у вас нет конкретных потребностей в (микро)оптимизации, обычно нет необходимости позволять коду делать такого рода предположения о структуре и диапазоне значений поля id в базе данных.

$pdo = new PDO('mysql:...');
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

$stmt = $pdo->prepare('SELECT age FROM users WHERE id=?');
$stmt->execute(array('5633847511239487'));
person VolkerK    schedule 08.07.2010

После некоторых исследований я пришел к такой настройке

private function escapeInt($value)
{
    if (is_float($value))
    {
        return number_format($value, 0, '.', ''); // may lose precision on big numbers
    }
    elseif(preg_match('/^-?[0-9]+$/', $value))
    {
        return (string)$value;
    }
    else
    {
        $this->error("Invalid value");
    }
}

Отдельный случай для чисел с плавающей запятой, потому что $i = 184467440737095; становится числом с плавающей запятой в 32-битной системе и, таким образом, рассыпается до экспоненциальной записи при преобразовании в строку.
И простое регулярное выражение для остального.

person Your Common Sense    schedule 12.12.2012

Вы даже можете умножить переменную на *1, вы можете проверить ее минимальные и максимальные значения, которые вы можете принять (для возраста bigint вообще не вариант... так зачем даже разрешать числа больше, чем значения, к которым вы готовы? И есть также PDO с подготовкой своего запроса.

person Seti    schedule 18.04.2014