В начале руководства мы говорили, что фильтрация данных — краеугольный камень безопасности WEB-приложений на любом языке и на любой платформе. Это включает в себя проверку ввода данных в приложение и из приложения, а хороший дизайн программного обеспечения может помочь разработчикам:
гарантировать, что фильтрацию данных невозможно обойти,
гарантировать, что незаконная информация не влияет на юридическую информацию, и
определить источник данных.
Существуют различные взгляды на то, как обеспечить невозможность обхода фильтрации данных, и два из них являются более общими, чем другие, и обеспечивают более высокий уровень уверенности.
Метод планирования. Этот метод планируется с помощью одного PHP-скрипта (через URL-адрес). Любые другие операции включаются с помощью include или require, когда это необходимо. Этот подход обычно требует, чтобы каждому URL-адресу для отправки передавалась отдельная переменная GET. Эту переменную GET можно рассматривать как более упрощенную конструкцию, заменяющую имя сценария. Например:
http://example.org/dispatch.php?task=print_formdispatch.php — единственный корневой файл (корень документа). Это позволяет разработчикам сделать две очень важные вещи:
вначале реализовать некоторую глобальную обработку безопасности в send.php и гарантировать, что эту обработку невозможно обойти.
Легко определить, где необходима фильтрация данных, особенно для некоторых специальных операций потока управления.
См. следующий пример для дальнейшего обсуждения сценария диспетчеризации.php:
<?php/* Глобальная обработка безопасности*/switch ($_GET['task']){case 'print_form':include '/inc/presentation/form.inc '; перерыв;case 'process_form':$form_valid = false;include '/inc/logic/process.inc';if ($form_valid){include '/inc/presentation/end.inc';}else{include '/ inc/presentation/form.inc';}break;default:include '/inc/presentation/index.inc';break;}?>Если это единственный общедоступный PHP-скрипт, вы можете быть уверены, что эта программа Дизайн гарантирует, что начальную глобальную обработку безопасности невозможно обойти. Это также позволяет разработчикам видеть поток управления конкретными задачами. Например, это легко узнать, не просматривая весь код: когда $form_valid имеет значение true, пользователю отображается только end.inc; поскольку он происходит до включения процесса.inc и только что был инициализирован значением false, он отображается как false; можно определить, что внутренняя логика процесса.inc установит для него значение true, в противном случае форма будет отображена снова (возможно, с соответствующим сообщением об ошибке).
Обратите внимание: если вы используете файл директив каталога, такой как index.php (вместо диспетчеризации.php), вы можете использовать URL-адрес следующим образом: http://example.org/?task=print_form .
Вы также можете использовать перенаправление ApacheForceType или mod_rewrite для настройки URL-адреса: http://example.org/app/print-form .
Другой способ включения методов — использовать один модуль, отвечающий за всю обработку безопасности. Этот модуль включен в начало (или в самое начало) всех общедоступных PHP-скриптов. Обратитесь к следующему сценарию security.inc
<?phpswitch ($_POST['form']){case 'login':$allowed = array();$allowed[] = 'form';$allowed[] = 'username' ; $allowed[] = 'пароль';$sent = array_keys($_POST);if ($allowed == $sent){include '/inc/logic/process.inc';}break;}?>В этом случае Считается, что каждая отправленная форма содержит уникальное проверочное значение формы, и Security.inc самостоятельно обрабатывает данные в форме, которые необходимо фильтровать. HTML-форма, реализующая это требование, выглядит следующим образом:
<form action="/receive.php" метод="POST"><input type="hidden" name="form" value="login" /><p>Имя пользователя. : <input type="text" name="username" /></p><p>Пароль:<input type="password" name="password" /></p><input type="submit" / > </form>Массив $allowed используется для проверки того, какие переменные формы разрешены. Этот список должен быть согласован перед обработкой формы. Управление процессом решает, что выполнять, а именно в Process.inc поступают фактически отфильтрованные данные.
Обратите внимание: лучший способ гарантировать, что файл Security.inc всегда будет включен в начало каждого сценария, — это использовать параметр auto_prepend_file.
Пример фильтрации Создание белого списка очень важно для фильтрации данных. Поскольку невозможно привести примеры для всех данных формы, с которыми вы можете столкнуться, некоторые примеры помогут вам получить общее представление.
Следующий код проверяет адрес электронной почты:
<?php$clean = array();$email_pattern = '/^[^@s<&>]+@([-a-z0-9]+.) +[ az]{2,}$/i';if (preg_match($email_pattern, $_POST['email'])){$clean['email'] = $_POST['email'];}?> ниже кода гарантирует, что содержимое $_POST['color'] будет красным, зеленым или синим:
<?php$clean = array();switch ($_POST['color']){case 'red':case 'green ' :case 'blue':$clean['color'] = $_POST['color'];break;}?>Следующий код гарантирует, что $_POST['num'] является целым числом:
<?php$ clean = array ();if ($_POST['num'] == strval(intval($_POST['num']))){$clean['num'] = $_POST['num'];} >Следующее? код гарантирует, что $_POST['num'] является числом с плавающей запятой:
<?php$clean = array();if ($_POST['num'] == strval(floatval($_POST['num ']))){ $clean['num'] = $_POST['num'];}?> В каждом примере перед преобразованием имени используется массив $clean. Это хорошая практика для разработчиков, позволяющая определить, потенциально ли их данные скомпрометированы. Никогда не сохраняйте данные в $_POST или $_GET после их проверки. Как разработчик, вы всегда должны с подозрением относиться к данным, сохраненным в суперглобальных массивах.
Следует добавить, что использование $clean может помочь подумать о том, что не было отфильтровано, что больше похоже на роль белого списка. Может повысить уровень безопасности.
Если вы храните в $clean только проверенные данные, единственный риск при проверке данных заключается в том, что элемент массива, на который вы ссылаетесь, не существует, а не нефильтрованные опасные данные.
Время. Когда PHP-скрипт начинает выполняться, это означает, что все HTTP-запросы завершены. На этом этапе у пользователя нет возможности отправить данные в скрипт. Поэтому в скрипт нельзя вводить никакие данные (даже если включен Register_globals). Вот почему инициализация переменных — очень хорошая практика.