Злоупотребление включением
1. Причина уязвимости:
Include — наиболее часто используемая функция при написании веб-сайтов PHP, поддерживающая относительные пути. Существует множество PHP-скриптов, которые напрямую используют входную переменную в качестве параметра Include, что приводит к возникновению таких уязвимостей, как произвольная ссылка на скрипт и утечка абсолютного пути. Посмотрите на следующий код:
...
$includepage=$_GET["includepage"];
включить ($ включить страницу);
...
Очевидно, что нам нужно только отправить разные переменные Includepage, чтобы получить нужную страницу. Если вы отправите страницу, которая не существует, вы можете вызвать ошибку PHP-скрипта и утечку фактического абсолютного пути (решение этой проблемы описано в следующей статье).
2. Разрешение уязвимостей:
Решение этой уязвимости очень простое: сначала определить, существует ли страница, а затем включить ее. Или, точнее, используйте массив для указания файлов, которые можно включить. Посмотрите на следующий код:
$pagelist=array("test1.php","test2.php","test3.php"); //Указывает файлы, которые можно включить.
if(isset($_GET["includepage"])) //Определяем, есть ли $includepage
{
$includepage=$_GET["includepage"];
foreach($pagelist как $prepage)
{
if($includepage==$prepage) //Проверяем, находится ли файл в списке разрешенных
{
включить($препейдж);
$checkfind=истина;
перерыв;
}
}
if($checkfind==true){unset($checkfind });
else{ die("Неверная справочная страница!");
}
Это очень хорошо решит проблему.
Совет: К функциям с этой проблемой относятся: require(), require_once(), include_once(), readfile() и т. д. Также следует быть внимательными при написании.
Входные переменные не фильтруются
1. Причина уязвимости:
Эта уязвимость уже давно появилась в ASP, вызывая на тот момент бесчисленное количество уязвимостей для внедрения. Но поскольку в то время PHP имел небольшое влияние, немногие могли обратить на это внимание. Для PHP влияние этой уязвимости больше, чем для ASP, поскольку больше скриптов PHP используют текстовые базы данных. Конечно, существует также проблема внедрения операторов SQL. Чтобы дать более классический пример, первым является база данных:
$id=$_GET["id"];
$query="SELECT * FROM my_table, где id='".$id."'" //Очень классическая уязвимость SQL-инъекции
$result=mysql_query($query);
Здесь очевидно, что мы можем использовать инъекцию для получения другого содержимого базы данных. Я не буду описывать это здесь подробно. Как и в случае с инъекцией ASP, вы можете взглянуть на предыдущие черные защиты. Затем мы рассмотрим проблему текстовых баз данных:
$text1=$_POST["text1"];
$text2=$_POST["text2"];
$text3=$_POST["text3"];
$fd=fopen("test.php","a");
fwrite($fd,"rn$text1&line;$text2&line;$text3");
fclose($fd);
Уязвимость текста, возможно, еще более серьезна. Если мы вставим небольшой фрагмент PHP-кода в отправленную переменную, мы сможем превратить эту текстовую базу данных test.php в бэкдор PHP. Даже вставка кода загрузки позволяет нам загрузить полный бэкдор PHP. Затем повысьте привилегии и сервер ваш.
2. Разрешение уязвимостей:
Решение этой уязвимости на самом деле очень простое: строго фильтровать все представленные переменные. Замените некоторые чувствительные символы. Мы можем заменить содержимое HTML с помощью функции htmlspecialchars(), предоставляемой PHP. Вот пример:
//Создаем функцию фильтра www.knowsky.com
функция flt_tags($text)
{
$badwords=array("Fuck you","fuck"); //Список фильтров слов
$text=rtrim($text);
foreach($badwords as $badword) //Здесь фильтруем словарный запас
{
if(stristr($text,$badword)==true){ die("Ошибка: отправленный вами контент содержит деликатные слова, не отправляйте конфиденциальный контент.");
}
$text=htmlspecialchars($text); //замена HTML;
//Эти две строки заменяют возврат каретки на
$text=str_replace("r","
",$текст);
$text=str_replace("n","",$text);
$text=str_replace("&line;","│",$text); //Замените текстовый разделитель базы данных "&line;" на полноразмерный "│"
$text=preg_replace("/s{ 2 }/"," ",$text); //замена пробела;
$text=preg_replace("/t/"," ",$text // Все еще заменяем пробелы;
if(get_magic_quotes_gpc()){ $text=stripslashes($text } //Если Magic_quotes включен, замените '
вернуть $текст;
}
$text1=$_POST["text1"];
$text2=$_POST["text2"];
$text3=$_POST["text3"]
//Фильтрация всего ввода
$text1=flt_tags($text1);
$text2=flt_tags($text2);
$text3=flt_tags($text3);
$fd=fopen("test.php","a");
fwrite($fd,"rn$text1&line;$text2&line;$text3");
fclose($fd);
После некоторой замены и фильтрации можно смело записывать данные в текст или базу данных.
Решение администратора неполное.
1. Причина уязвимости:
Мы используем PHP для написания сценариев, для чего обычно требуются права администратора. Некоторые сценарии выносят только решение «да» в отношении разрешений администратора, но часто игнорируют решение «нет». Когда в файле конфигурации PHP включен Register_globals (в версиях после 4.2.0 он отключен по умолчанию, но многие включают его для удобства, что является крайне опасным поведением), возникнут ситуации, когда переменные передаются для олицетворения. администраторы. Давайте посмотрим на пример кода:
$cookiesign="admincookiesign"; //Определить, является ли переменная cookie администратора
$adminsign=$_COOKIE["sign"] //Получаем переменную cookie пользователя
if($adminsign==$cookiesign)
{
$админ=истина;
}
if($admin){ echo "Теперь вы администратор." };
Это выглядит очень безопасно, хаха. Теперь мы предполагаем, что в файле конфигурации PHP включена функция Register_globals. Мы отправили такой адрес «test.php?admin=true», вы видели результат? Хотя у нас нет нужного файла cookie, поскольку включена функция Register_globals, переданная нами переменная администратора автоматически регистрируется как истинная. Более того, в скрипте отсутствует решение «нет», что позволяет нам успешно получать права администратора через admin=true. Эта проблема существует на большинстве сайтов и форумов.
2. Разрешение уязвимостей:
Чтобы решить эту проблему, нам нужно всего лишь добавить в скрипт решение администратору «нет». Мы по-прежнему предполагаем, что в файле конфигурации PHP включена функция Register_globals. Взгляните на код:
$cookiesign="admincookiesign"; //Определить, является ли переменная cookie администратора
$adminsign=$_COOKIE["sign"] //Получаем переменную cookie пользователя
if($adminsign==$cookiesign)
{
$админ=истина;
}
еще
{
$админ=ложь;
}
if($admin){ echo "Теперь вы администратор." };
Таким образом, даже если злоумышленник отправит переменную admin=true без правильного файла cookie, в будущих решениях сценарий установит для $admin значение False. Это решает часть проблемы. Однако, поскольку $admin является переменной, если в будущем в других ссылках на скрипт появится лазейка и $admin будет переназначен, произойдет новый кризис. Поэтому мы должны использовать константы для хранения определения прав администратора. Используйте оператор Define(), чтобы определить константу администратора для записи прав администратора. Если после этого она будет переназначена, произойдет ошибка, достигающая цели защиты. Посмотрите на следующий код:
$cookiesign="admincookiesign"; //Определить, является ли переменная cookie администратора
$adminsign=$_COOKIE["sign"] //Получаем переменную cookie пользователя
if($adminsign==$cookiesign)
{
определить (администратор, правда);
}
еще
{
определить (администратор, ложь);
}
if(admin){ echo "Теперь вы находитесь в статусе администратора." };
Стоит отметить, что мы используем оператор Define, поэтому при вызове константы Admin не добавляйте по привычке символ переменной $ впереди, а используйте Admin и !admin.
Текстовая база данных открыта
1. Причина уязвимости:
Как упоминалось ранее, благодаря большой гибкости текстовых баз данных внешняя поддержка не требуется. Кроме того, PHP обладает очень мощными возможностями обработки файлов, поэтому текстовые базы данных широко используются в сценариях PHP. Есть даже несколько хороших форумных программ, использующих текстовые базы данных. Но есть выигрыши и потери, а безопасность текстовых баз данных ниже, чем у других баз данных.
2. Разрешение уязвимостей:
Текстовая база данных действует как обычный файл, который можно скачать, как и MDB. Поэтому нам необходимо защищать текстовые базы данных так же, как и MDB. Измените суффиксное имя текстовой базы данных на .PHP. и присоединитесь к первой строке базы данных. Таким образом, текстовая база данных будет рассматриваться как файл PHP, и выполнение завершится на первой строке. То есть пустая страница возвращается для достижения цели защиты текстовой базы данных.
Утек неправильный путь
1. Причина уязвимости:
Когда PHP обнаруживает ошибку, он сообщает местоположение, номер строки и причину ошибки сценария, например:
Примечание. Использование неопределенного константного теста — предполагается «тест» в D:interpubbigflytest.php в строке 3.
Многие говорят, что это не имеет большого значения. Но последствия утечки фактического пути невообразимы. Для некоторых злоумышленников эта информация очень важна. На самом деле сейчас на многих серверах есть такая проблема.
Некоторые сетевые администраторы просто устанавливают для параметра display_errors в файле конфигурации PHP значение Off, чтобы решить проблему, но я думаю, что этот метод слишком негативен. Иногда нам действительно нужно, чтобы PHP возвращал информацию об ошибках для отладки. А когда что-то пойдет не так, вам также может потребоваться дать пользователю объяснение или даже перейти на другую страницу.
2. Разрешение уязвимостей:
PHP предоставляет специальную функцию обработки ошибок set_error_handler() начиная с версии 4.1.0, но немногие авторы сценариев знают об этом. Среди множества PHP-форумов я видел только несколько, которые справились с этой ситуацией. Использование set_error_handler выглядит следующим образом:
строка set_error_handler (обратный вызов error_handler [, int error_types])
Теперь мы используем специальную обработку ошибок для фильтрации фактических путей.
//Admin — это определение личности администратора, true — администратор.
//Пользовательская функция обработки ошибок должна иметь эти четыре входные переменные $errno, $errstr, $errfile, $errline, иначе она будет недействительной.
функция my_error_handler($errno,$errstr,$errfile,$errline)
{
//Если вы не администратор, отфильтруйте фактический путь
если(!админ)
{
$errfile=str_replace(getcwd(),"",$errfile);
$errstr=str_replace(getcwd(),"",$errstr);
}
переключатель ($ ошибка)
{
случай E_ERROR:
echo "ОШИБКА: [ID $errno] $errstr (строка: $errline из $errfile)
н";
echo "Программа остановлена, обратитесь к администратору.";
//Выходим из скрипта при обнаружении ошибки уровня Error
Выход;
перерыв;
случай E_WARNING:
echo "ВНИМАНИЕ: [ID $errno] $errstr (строка: $errline из $errfile)
н";
перерыв
по умолчанию:
//Не отображать ошибки уровня уведомления
перерыв;
}
}
//Устанавливаем обработку ошибок для функции my_error_handler
set_error_handler("my_error_handler");
…
Таким образом, противоречие между безопасностью и удобством отладки может быть хорошо разрешено. Вы также можете подумать о том, чтобы сделать сообщение об ошибке более красивым, чтобы оно соответствовало стилю веб-сайта. Но обратите внимание на два момента:
(1) E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR и E_COMPILE_WARNING не будут обрабатываться этим дескриптором, то есть будут отображаться самым оригинальным образом. Однако эти ошибки вызваны ошибками компиляции или ядра PHP и не возникают при нормальных обстоятельствах.
(2) После использования set_error_handler() error_reporting() будет недействителен. То есть все ошибки (кроме вышеперечисленных) будут переданы на обработку пользовательской функции.
Дополнительную информацию о set_error_handler() можно найти в официальном руководстве PHP.
POST-уязвимость
1. Причина уязвимости:
Как упоминалось ранее, полагаться на Register_globals для регистрации переменных — плохая привычка. В некоторых гостевых книгах и программах-форумах тем более необходима строгая проверка способа получения страниц и временного интервала между подачами. Чтобы предотвратить спам-сообщения и внешние материалы. Давайте посмотрим на следующий код программы гостевой книги:
...
$text1=flt_tags($text1);
$text2=flt_tags($text2);
$text3=flt_tags($text3);
$fd=fopen("data.php","a");
fwrite($fd,"rn$text1&line;$text2&line;$text3");
fclose($fd);
...
Очевидно, если мы отправим URL-адрес «post.php?text1=testhaha&text2=testhaha&text3=testhaha». Данные будут записаны в файл обычным способом. Эта программа не определяет источник переменных и способ получения страницы браузером. Если мы отправим несколько материалов на эту страницу, это приведет к наводнению. Есть также некоторые программы, которые используют эту уязвимость для размещения рекламы на форумах или в гостевых книгах, что является постыдным поведением (гостевая книга моего друга была заполнена более чем 10 страницами за одну неделю, что было беспомощно).
2. Разрешение уязвимостей:
Прежде чем обрабатывать и сохранять данные, сначала определите, как браузер получает страницу. Используйте переменную $_SERVER["REQUEST_METHOD"] для получения метода браузера получения страницы. Проверьте, является ли это «POST». Используйте сеанс в сценарии, чтобы записать, отправляет ли пользователь данные через обычные каналы (то есть страницу, на которой заполняется содержимое отправки). Или используйте $_SERVER["HTTP_REFERER"] для обнаружения этого, но это не рекомендуется. Поскольку некоторые браузеры не устанавливают REFERER, некоторые брандмауэры также блокируют REFERER. Кроме того, нам также необходимо проверить отправленный контент на наличие дублированного контента в базе данных. Возьмем, к примеру, гостевую книгу, для принятия решения используйте Session:
На странице, где вы заполняете контент просмотра, мы добавляем в начале:
$_SESSION["allowgbookpost"]=time(); //Время заполнения регистрации. На странице, где принимаются и сохраняются данные сообщения, мы также используем Session для выполнения следующей обработки перед обработкой данных:
if(strtoupper($_SERVER["REQUEST_METHOD"])!="POST"){ die("Ошибка: не отправлять извне."); //Проверяем, является ли метод получения страницы POST.
if(!isset($_SESSION["allowgbookpost"]) or (time()-$_SESSION["allowgbookpost"] < 10)){ die("Ошибка: не отправлять извне."); //Проверяем сообщение Время при заполнении
if(isset($_SESSION["gbookposttime"]) and (time()-$_SESSION["gbookposttime"] < 120)){ die("Ошибка: интервал между двумя отправками сообщений не должен быть меньше 2 минут. "); } //Проверяем интервал сообщений
unset($_SESSION["allowgbookpost"]); //Отменяем регистрацию переменнойallowgbookpost, чтобы предотвратить одновременное попадание нескольких сообщений на страницу заполнения
$_SESSION["gbookposttime"]=time(); //Зарегистрируйте время отправки сообщений для предотвращения спама или вредоносных атак.
...
Обработка и хранение данных
...
После таких многочисленных проверок ваша программа станет намного безопаснее.