Здесь, на Smashing Редакция команды, мы всегда стараемся соответствовать ожиданиям наших читателей.
Мы делаем все возможное, чтобы избежать недоразумений, и мы стараемся распространять knowedge и представить только лучшие методы проектирования и разработки методов.Тем не менее, иногда мы делаем ошибки.И когда мы это сделаем, мы приносим свои извинения и делаем все возможное, чтобы исправить то, что we’ ве done.
В ноябре 2008 года мы опубликовали статью 10 Advanced PHP советов для улучшения вашей Programming.Видимо, в соответствии с отрицательными комментариями к этой должности, он содержит некоторые ошибки, и некоторые заявления, которые являются просто неправильно. Мы приносим извинения за наши mistake, и мы действительно извинения за причиненные неудобства мы его причиной.Тем не менее, эта простая извинений не достаточно хорошо.Чтобы решить эту проблему, мы попросили Криса Shiflett и Шон Коутс, два PHP гуру, чтобы поближе взглянуть на статьи, объяснить свои ошибки и сделать его совершенно ясно, что на самом деле правильно и неправильно в теории и практике.Эта статья представляет собой профессиональный ответ на нашу статью, опубликованную пару месяцев ago.
10 Полезные советы PHP Revisited
Крис Shiflett и Шон Coates
Эта статья является опровержение 10 Advanced PHP советов для улучшения вашей Programming — далее именуемый предыдущей статье — опубликованном в ноябре прошлого года здесь, на Smashing Magazine.Введение звучит интригующе:
Ниже приведены 10 отличных приемов, PHP-разработчики должны изучить и использовать каждый раз, когда они program.
К сожалению, интриги превратится в разочарование.Мы не согласны с многими советами, и даже когда мы этого не сделать, сопровождающего объяснения слабой или вводящими в заблуждение.В этой статье мы проходим каждый наконечник из предыдущей статьи и предоставлять свои собственные комментарии и доказательства, либо для проверки и уточнения отзыв, или опровергнуть ее.Мы надеемся, что вы не просто принять наше мнение, а скорее узнать достаточно, чтобы сформировать свое own.
1.Использование SQL-инъекция Чит Sheet
Этот конкретный совет только ссылки на полезные ресурсы без обсуждения о том, как его использовать.Изучая различные перестановки одной конкретной атаки может быть полезной, но ваше лучше потратить это время научиться защищать против него.Кроме того, есть намного больше к обеспечению безопасности веб-приложений, чем инъекции SQL. XSS (Cross-Site Scripting) и CSRF (Cross-Site запрос подделки) , например, по меньшей мере, так же часто, и, по крайней мере dangerous.
Мы можем предоставить некоторые столь необходимого контекста, а потому, что мы не хотим, чтобы сосредоточиться слишком много на одну атаку, we’ буду первый шагназад.Каждый разработчик должен быть знаком с хорошей практики безопасности, и приложения должны быть разработаны с учетом этих практик в виду.Основное правило: никогда не доверять данным, вы получите от где-то в другом месте.Еще одно правило, это попытка уйти данных, прежде чем отправить его в другое место.В совокупности эти правила могут быть упрощены, чтобы составить основной принцип безопасности: входной фильтр, выход продукции (FIEO)
.
Причины инъекции SQL является неспособность избежать выхода.Более конкретно, это когда различие между форматом SQL запросов и данных, используемых в SQL-запросе не обязательно сохранить.Это часто встречается в программах PHP, что строить запросы следующим образом:
<?php $query = "SELECT * FROM users WHERE name = '{$_GET['name']}'"; ?>
В этом случае значение переменной $ _GET ['имя'] обеспечивается другого источника, пользователю, но это ни фильтруется, ни escaped.
Побег сохраняет данные в новый контекст.Акцент на побег выходом является напоминанием, что данные, используемые за пределами вашего веб-приложения должны быть экранированы, иначе она может быть неправильно истолковано.В отличие от этого, фильтрация гарантирует, что данные действительны перед использованием.Акцент на фильтрацию входного является напоминанием, что данные, поступающие за пределами вашего веб-приложения должны быть отфильтрованы, потому что этого не может быть trusted.
Предполагая, что мы используем MySQL, уязвимости SQL Injection может быть уменьшен путем побега имя с mysql_real_escape_string () .Если имя также фильтруется, есть дополнительный уровень безопасности.(Реализация нескольких уровней безопасности называют "глубокой защиты", и это очень хорошая практика безопасности). Следующий пример демонстрирует фильтрацию входного и выходного побега, с именования используются для ясности кода:
<?php // Initialize arrays for filtered and escaped data, respectively. $clean = array(); $sql = array(); // Filter the name. (For simplicity, we require alphabetic names.) if (ctype_alpha($_GET['name'])) { $clean['name'] = $_GET['name']; } else { // The name is invalid. Do something here. } // Escape the name. $sql['name'] = mysql_real_escape_string($clean['name']); // Construct the query. $query = "SELECT * FROM users WHERE name = '{$sql['name']}'"; ?>
Хотя использование именования может помочь вам идти в ногу с тем, что имеет, и не фильтруется, а также то, что имеет, и не бежал, гораздо лучше было бы использовать подготовленные заявления.К счастью, с PDO, PHP разработчиков есть универсальный API для доступа к данным, который поддерживает подготовленные заявления, даже если основная база данных делает not.
Помните, уязвимости SQL инъекции существовать, когда различия между форматом SQL запросов и данных, используемых в SQL запросе не обязательно сохранить.С подготовленные заявления, вы можете нажать эту ответственность в базе данных путем предоставления запроса формата и данных в различных шагов:
<?php // Provide the query format. $query = $db->prepare('SELECT * FROM users WHERE name = :name'); // Provide the query data and execute the query. $query->execute(array('name' => $clean['name'])); ?>
PDO руководство page предоставляет более подробную информацию и примеры.Подготовленные заявления предлагают самые сильные защиты от SQL injection.
2.Знать разницу между Сравнение Operators
Это хороший совет, но он отсутствует практический пример, который демонстрирует, когда нестрогое сравнение может привести к problems.
Если Вы используете strpos () определить, является ли подстрока существует в строку (она возвращает FALSE, если подстрока не найдена), результаты могут вводить в заблуждение:
<?php $authors = 'Chris & Sean'; if (strpos($authors, 'Chris')) { echo 'Chris is an author.'; } else { echo 'Chris is not an author.'; } ?>
Потому что подстрокаChris происходит в самом начале Chris & Sean, strpos () корректно возвращает 0, указывая на первую позицию в строке.Потому что условный оператор рассматривает это как логическое, он оценивает в FALSE, а условие не выполняется.Другими словами, похоже, что Крис не автор, но он
Это можно исправить с помощью строгого сравнения:
<?php if (strpos($authors, 'Chris') !== FALSE) { echo 'Chris is an author.'; } else { echo 'Chris is not an author.'; } ?>
3.Ярлык else
Этот совет случайно натыкается на полезную практику, которая всегда инициализировать переменные перед их использованием.Рассмотрим условный оператор, который определяет пользователь является администратором на основе имени пользователя:
<?php if (auth($username) == 'admin') { $admin = TRUE; } else { $admin = FALSE; } ?>
Это кажется достаточно безопасным, потому что это легко понять с первого взгляда.Представьте себе, чуть более сложный пример, который устанавливает переменные имя и электронную почту, а также, для удобства:
<?php if (auth($username) == 'admin') { $name = 'Administrator'; $email = 'admin@example.org'; $admin = TRUE; } else { /* Get the name and email from the database. */ $query = $db->prepare('SELECT name, email FROM users WHERE username = :username'); $query->execute(array('username' => $clean['username'])); $result = $query->fetch(PDO::FETCH_ASSOC); $name = $result['name']; $email = $result['email']; $admin = FALSE; } ?>
Потому $ admin по-прежнему всегда четко установлен либо TRUE или FALSE, все хорошо, но если разработчик позже добавляет elseif, есть возможность забыть:
<?php if (auth($username) == 'admin') { $name = 'Administrator'; $email = 'admin@example.org'; $admin = TRUE; } elseif (auth($username) == 'mod') { $name = 'Moderator'; $email = 'mod@example.org'; $moderator = TRUE; } else { /* Get the name and email. */ $query = $db->prepare('SELECT name, email FROM users WHERE username = :username'); $query->execute(array('username' => $clean['username'])); $result = $query->fetch(PDO::FETCH_ASSOC); $name = $result['name']; $email = $result['email']; $admin = FALSE; $moderator = FALSE; } ?>
Если пользователь предоставляет имя пользователя, который запускает elseif условии, $ admin не инициализирован.Это может привести к нежелательным поведением, или еще хуже, уязвимость системы безопасности.Кроме того, подобная ситуация существует в настоящее время за $ moderator, которые не инициализируется в первый condition.
По первой инициализации $ admin и $ moderator, можно легко избежать этого сценария в целом:
<?php $admin = FALSE; $moderator = FALSE; if (auth($username) == 'admin') { $name = 'Administrator'; $email = 'admin@example.org'; $admin = TRUE; } elseif (auth($username) == 'mod') { $name = 'Moderator'; $email = 'mod@example.org'; $moderator = TRUE; } else { /* Get the name and email. */ $query = $db->prepare('SELECT name, email FROM users WHERE username = :username'); $query->execute(array('username' => $clean['username'])); $result = $query->fetch(PDO::FETCH_ASSOC); $name = $result['name']; $email = $result['email']; } ?>
Независимо от того, что остальная часть кода делает, это теперь ясно, что $ admin является FALSE, если она не установлена явно в чем-то другом, и то же самое верно и для $ moderator.Это также намекает на еще один хороший способ обеспечения безопасности, которая является на провал безопасно.Самое худшее, что может произойти в результате не изменяя $ admin или $ moderator в любом из условий является то, что человек, который является администратором или модератором не рассматривается как one.
Если вы хотите, чтобы сократить и то, и вы чувствуете себя немного разочарован, что наш пример включает в себя else, у нас есть бонус наконечник которые могут вас заинтересовать.Мы не уверены, что это можно рассматривать как ярлык, но мы надеемся, что это полезно nonetheless.
Рассмотрим функцию, которая определяет, может ли пользователь право на просмотр определенной страницы:
<?php function authorized($username, $page) { if (!isBlacklisted($username)) { if (isAdmin($username)) { return TRUE; } elseif (isAllowed($username, $page)) { return TRUE; } else { return FALSE; } } else { return FALSE; } } ?>
Этот пример является на самом деле довольно просто, потому что есть только три правила, чтобы рассмотреть: администраторы всегда разрешен доступ, те, кто находятся в черном списке никогда не разрешен доступ, и IsAllowed () определяет, будет ли кто-либо имеет доступ.(Особый случай возникает, когда администратор занесен в черный список, но это вряд возможности, поэтому мы игнорируем его здесь.) Мы используем функции для правителей, чтобы сохранить код простой и сосредоточиться на логическом structure.
Есть множество способов, этот пример может б ...
Если вы хотите прочитать полностью статью, посетите сайт наших спонсоров