Существует несколько способов подключения к базе данных MySQL на PHP. Наиболее распространенными являются MySQL API, MySQLi API и PDO API (объекты данных PHP). Последние два поддерживают больше функций, чем старый mysql API, и более безопасны. Если вы используете старые функции «mysql_», вам следует остановиться и изучить новый API PDO. Эти старые функции mysql устарели и больше не поддерживаются в PHP 7.x.
$con = mysql_connect("localhost", "root", "mypass") or die("Не удалось подключиться: " . mysql_error()); mysql_select_db("tutorials"); $result = mysql_query("select * from tutorials"); echo "<h2>Вот список тем:</h2>"; while ($row = mysql_fetch_array($result)) { echo $row['name']."<br />"; } mysql_close($con);
require_once('includes/conn.inc.php'); $sql= "SELECT name, age FROM employees WHERE company_id = 10"; $stmt = $pdo->query($sql); $row = $stmt->fetch(PDO::FETCH_ASSOC); echo $row['name']; echo $row[age];
Экранирование переменных запроса вручную с использованием mysql_real_escape_string считается небезопасным по двум причинам:
Вместо этого используйте подготовленные заявления (см. Дополнительную информацию ниже).
Цель подготовленных операторов состоит в том, чтобы отделить запрос от данных, чтобы данные были правильно вставлены в параметры запроса без каких-либо опций манипулирования. В большинстве случаев подготовленные операторы считаются очень безопасными для использования, и это считается наилучшей практикой для ввода пользовательских параметров в запросы.
require_once('includes/conn.inc.php'); $sql= "SELECT * FROM employees"; $stmt = $pdo->prepare($sql); $stmt->execute(); $result = $stmt->fetchAll(); foreach($result as $row){ echo " <li>{$row['employeeName']}</li>"; }
Так где же готовые заявления не хватает в PHP? Это тот случай, когда вы вводите пользовательский ввод в запрос, но подготовленные операторы не поддерживают это внедрение. Например, MySQL PDO не поддерживает введение параметра (используя заполнитель «?») В спецификаторе LIMIT. Кроме того, пользовательский ввод не может быть вставлен в виде имен таблиц или столбцов в запросе. Если вы используете подготовленные операторы в этих случаях, вам следует тщательно санировать данные вручную или, что лучше, использовать библиотеку, которая сделает это за вас и уже была протестирована.
Использование ORM может быть большим. Это говорит о том, что это не означает, что он не подвержен атакам SQL-инъекций. Это правда, что сложнее внедрить код в запрос, сгенерированный ORM, но это не значит, что программист не может сделать ошибку, которая откроет лазейку. В большинстве случаев эту атаку можно выполнить при объединении пользовательского ввода в запрос ORM без использования подготовленных операторов. Да, платформы ORM, такие как Doctrine, предоставляют возможность использовать подготовленные операторы, поэтому используйте их. Никогда не объединяйте строки в запрос, будь то запрос ORM или необработанный запрос SQL.
Кстати, недостаточно следовать правилам – обязательно проверяйте использование и реализацию ORM после кодирования, чтобы убедиться, что он не открыт для каких-либо SQL-инъекций.
В следующем примере кода вы можете видеть, что параметр, который был введен пользователем, объединяется с Doctrine DQL, который подвергает приложение внедрению SQL.
<?php // INSECURE $dql = "SELECT u FROM MyProject\Entity\User u WHERE u.status = '" . $_GET['status'] . "' ORDER BY " . $_GET['orderField'] . " ASC";
Как рекомендуется для пользователей, не являющихся ORM, использование подготовленных операторов рекомендуется при использовании платформы ORM (например, Doctrine).
<?php $orderFieldWhitelist = array('email', 'username'); $orderField = "email"; if (in_array($_GET['orderField'], $orderFieldWhitelist)) { $orderField = $_GET['orderField']; } $dql = "SELECT u FROM MyProject\Entity\User u WHERE u.status = ?1 ORDER BY u." . $orderField . " ASC"; $query = $entityManager->createQuery($dql); $query->setParameter(1, $_GET['status']);
Согласно OWASP (Open Security Application Project Project), отсутствие использования utf8mb4 откроет вам различные типы атак (вы можете узнать больше об обходе кодирования). Кроме того, вы должны регулярно использовать utf8mb4 в PHP и MySQL для лучшей и более стандартной многоязычной поддержки.
$dsn = 'mysql:host=example.com;dbname=testdb;port=3306;charset=utf8mb4';
Мы рассмотрели 5 очень распространенных ошибок, которые делают многие разработчики PHP. Некоторые из них происходят из-за недостатка знаний (новые платформы доступны постоянно, убедитесь, что вы знаете о них). Некоторые ошибки случаются из-за недостатка опыта (читайте, читайте и читайте больше, чтобы убедиться, что вы используете самые безопасные и лучшие API). Удачи в вашем следующем проекте!