Intereting Posts
PHP: дата «вчера», «сегодня», Рекурсивно цикл каждого пути массива Неустранимая ошибка: вызов неопределенной функции openssl_random_pseudo_bytes () PHP не может писать вне корня документа независимо от того, что .htaccess URL-адрес: проблема с перезаписыванием: наличие ошибок, когда файлы и имена папок одинаковы Предупреждение: недопустимый параметр смещения строки в файле php Обработка нескольких файлов в Laravel 5.1 (как API) как получить значения переключателя, который был проверен, jquery Создать страницу, на которой отображаются файлы журнала Codeigniter на веб-странице. Объединение регулярного выражения для проверки номера телефона в Великобритании и США Синхронизация строк в PHP datetime Функциональность импорта Yii Простая PDO-обертка Как найти часовую разницу между двумя датами в PHP? Нарушение родительской функции из дочерней функции (PHP Preferrably)

Почему этот подготовленный MySQLI оператор разрешает SQL-инъекцию?

Поскольку я преподавал студентам, как предотвратить внедрение SQL сегодня, я был слегка смущен. В профессиональных проектах я использовал подготовленные заявления / параметризованные запросы как один уровень предотвращения внедрения SQL (хотя я никогда не использовал mySQL профессионально). Теоретически я думал, что SQL-инъекция невозможна при использовании подготовленного оператора.

Но потом это сработало …

$Search = $_GET['s']; $stmt = $mysqli->prepare("SELECT * FROM products WHERE id = ?"); $stmt->bind_param("i", $Search); $stmt->execute(); $Results = $stmt->get_result(); 

Если я передаю параметр «? S = 1 ИЛИ 1 = 1», тогда я могу получить полный список всех продуктов. Я все еще не могу вставить другой запрос в конце, но я смущен тем, почему этот тип базовой инъекции SQL возможен в mysql / php. Я предположил, что параметр «1 ИЛИ 1 = 1» будет отклонен, потому что он не является числовым (очевидно, я мог бы выполнить эту числовую проверку …).

Может ли кто-нибудь объяснить, почему это работает, и что я не понимаю о подготовленных инструкциях в php / mysql?

У моего школьного компьютера есть готовая установка Zend WAMP.

EDIT: это строковое значение, вызывающее мою путаницу:

 $Search = "1 OR 1=1"; 

Все в порядке, никакой какой-либо инъекции SQL здесь, вы не видите список всех продуктов (по крайней мере, код, который вы предоставили, не может показать его)

вам не нужно бросать в int, давайте глубже, что на самом деле делает bind_param:

он имеет строку «i», что означает 1 integer аргумент

вы передаете значение из $ _GET, которое является string

bind_param пытается преобразовать String в int, поэтому проверьте этот php-код:

 echo intval('a', 10); // output 0 echo intval('1a', 10); // output 1 echo intval('12a', 10); // output 12 echo intval('b1', 10); // output 0 echo intval('1 or 1=1', 10); // output 1 echo intval("?s=1 OR 1=1", 10); // output 0 

поэтому вы выводите продукты с id = 1, возможно, у вас есть некоторые из них?

Я попытался воспроизвести ваше дело, но не смог.

База данных

 CREATE TABLE `Document` ( `DataID` int(10) unsigned NOT NULL AUTO_INCREMENT, `Description` varchar(50) CHARACTER SET utf8 NOT NULL, PRIMARY KEY (`DataID`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; INSERT INTO `Document` VALUES (1,'BI8392'); INSERT INTO `Document` VALUES (2,'HE8492'); INSERT INTO `Document` VALUES (3,'HE8493'); INSERT INTO `Document` VALUES (4,'HE8490'); 

Код

 <?php $host = "localhost"; $passwd = ""; $user = "user"; $bdd = "test"; $conn = mysqli_connect( $host, $user, $passwd, $bdd); mysqli_set_charset($conn, "utf8"); if (!$conn) { printf('Error connecting to mysql. Error code: ', mysqli_connect_error()); exit; } $sql = "SELECT * FROM Document WHERE DataID = ?"; if ($stmt = $conn->prepare($sql)) { $param = "2 OR 1=1"; $stmt->bind_param("i", $param); $stmt->execute(); $results = $stmt->get_result(); $data = mysqli_fetch_all($results); var_dump($data); } 

Вывод

 array(1) { [0]=> array(2) { [0]=> int(2) [1]=> string(6) "HE8492" } } 

Кажется, что условие 1 = 1 было проигнорировано.