2016-05-27 3 views
0

Я хочу создать хранимую процедуру, которая принимает идентификаторы в качестве входов, и в зависимости от списка идентификаторов будет вести себя соответственно.Сохраненная процедура с SQL-инъекцией

Пример:

DROP PROCEDURE IF EXISTS sp_G; 
DELIMITER ;; 
CREATE PROCEDURE sp_G (
    IN IDs VARCHAR(20) -- Example: '1, 2, 3' 
    ) 
BEGIN 
    SET @Query='SELECT * FROM table_users as t'; 

    IF IDs!=NULL 
    THEN 
     SET @Query=CONCAT(@Query, ' WHERE t.ID in(', IDs, ')'); -- SQL Injection problem 
    END IF; 

    PREPARE stmt FROM @Query; 
    EXECUTE stmt; 

END ;; 
DELIMITER ; 

Случается, что у меня есть инъекции SQL в «CONCAT», потому что я не могу использовать «ВЫПОЛНИТЬ STMT ИСПОЛЬЗОВАНИЕ» идентификаторы как показано на следующая ссылка: http://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html

Поскольку параметр ID не является обязательным, он будет влиять только на запрос, если он не равен NULL. Однако, согласно документации, мы предполагаем, что этот параметр ID всегда будет существовать. Если параметр ID имеет SQL-инъекцию, будет выполнен. Может кто-нибудь мне помочь? Спасибо заранее.

+0

Можете ли вы подтвердить ввод в коде, который вызывает процедуру? – Barmar

+0

Если у вас есть что-то выше цифр и запятых в параметре, это попытка ввести sql. – Shadow

+0

@Barmar Я пытаюсь, но я боюсь забыть в некотором месте –

ответ

1

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

IF IDs IS NOT NULL AND IDs RLIKE '^[0-9, ]+$' 
THEN 
    SET @Query=CONCAT(@Query, ' WHERE t.ID in(', IDs, ')'); 
END IF 

Это работает для простого параметра, такого как список идентификаторов. Однако он не обобщает на более сложные ситуации. Лучшим решением является разработка вашего приложения, поэтому вам не нужно вставлять введенный пользователем ввод в запросы в первую очередь.

Например, вместо процедуры, которая принимает список значений, разделенных запятыми, для соответствия, вызывающий может помещать эту информацию во временную таблицу. Тогда запрос будет

SELECT u.* FROM table_users AS u 
JOIN temp_table AS t ON u.id = t.id