PHP безопасно получает ввод пользователя

Я хотел бы быть приятным для своих пользователей, но не хочу ошибочно вводить вредоносный код. Глядя на множество вопросов, я решил пойти в белый список, поэтому я получаю только тех, кого одобряю.

Как можно быть добрым к пользователю, поэтому я позволяю им вводить много символов и по-прежнему держать мои входы в безопасности от вредоносного кода?
Я использую Apache с PHP 5.3.8, я не включил PDO, потому что, когда я слышал об этом, я был глубоко в проекте и боялся, что это может быть слишком большим для изменения.

Любые идеи помогут!

Если он может быть выведен для пользователя, вы должны запретить потенциально вредоносному пользователю включать HTML-теги в свой код. Например, если в этой статье я мог бы добавить тег script , который может быть очень опасным для любого пользователя, читающего мой пост. Чтобы предотвратить это, вы хотите использовать htmlentities :

 $clean_data = htmlentities($_POST['data']); 

Таким образом, <script> будет переведен как &lt;script&gt; поэтому он не повредит пользователям при отображении их браузерами.

Теперь, если вы хотите сохранить мой пост в своей базе данных, вы должны остерегаться SQL-инъекций. Предположим, вы сохраняете мой пост с этим запросом (да, вы не должны использовать функции mysql_* поскольку они устарели, но это просто для объяснения идеи):

 mysql_query($db, "INSERT INTO posts(data) values('$clean_data');"); 

Звучит хорошо ? Ну, если я противный, я постараюсь включить этот пост:

 test'); DELETE FROM posts; SELECT * FROM posts WHERE data = ' 

То, что получает ваш MySQL,

 INSERT INTO posts(data) values('test'); DELETE FROM posts; SELECT * FROM posts WHERE data = ''); 

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

 $really_clean_data = mysql_real_escape_string($db, $clean_data); mysql_query($db, "INSERT INTO posts(data) values('$really_clean_data');"); 

Итак, с вышеупомянутой злонамеренной почтой MySQL теперь получит

 INSERT INTO posts(data) values('test\'); DELETE FROM posts; SELECT * FROM posts WHERE data = \''); 

Теперь, для MySQL, все значения INSERT INTO posts(data) values('test'); DELETE FROM posts; SELECT * FROM posts WHERE data = ''); INSERT INTO posts(data) values('test'); DELETE FROM posts; SELECT * FROM posts WHERE data = ''); part – это правильная строка, поэтому происходит то, что вы хотите.

В принципе, это все, что вам нужно почти во всех случаях. Просто помните, что когда вы подаете пользовательские данные в интерпретатор (это может быть веб-браузер, механизм SQL или многое другое), вы должны очистить эти данные, и лучший способ сделать это – использовать специальные функции, которые должны Приходите с библиотекой, которую используете.

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

 $really_clean_data = mysql_real_escape_string($db, $clean_data); $query = "UPDATE posts SET post = '".$really_clean_data."' WHERE id = '".(int)$_POST['id']."'"; 

Все представленные данные, в том числе идентификационный номер сообщения, который вы хотите обновить, так же подозрительны и так же открыты для вредоносного ворчания, как текстовая или текстовая вводная запись. Когда вы знаете, что это должно быть целое число (число), вы можете использовать его как таковое. Если он не является числовым, то (int) будет использовать его как 0. Вы не можете обновить строку 0, поэтому запрос SQL завершится с ошибкой.

Чтобы проверить этот отказ перед выполнением запроса, вы можете проверить опубликованные данные, чтобы узнать, является ли это числом, используя функцию is_numeric ().

 if(!is_numeric($_POST['id'])){ die("Post id is not a number."); } 

Для полей ввода, в первую очередь полей имени пользователя и пароля, вы можете установить максимальную длину и проверку. Например,

 if(strlen($_POST['username']) > 24){ $error = "username is too long"; } 

Если вы можете проявить творческий подход к этому, предотвращение инъекции SQl на самом деле весело! Имейте в виду, что через год все на этой странице может быть полностью устаревшим и неуместным. Безопасность – это процесс, а не шаг, поэтому держитесь за него.