Каков риск внесения IP-адресов в белый список PHP скриптов, используемых для Cronjobs, перед их запуском? - PullRequest
2 голосов
/ 08 мая 2020

У меня есть несколько PHP скриптов на моем сервере, которые я использую для периодических c заданий cron (например, для ежедневных контактов и обновления списков лидеров).

Чтобы запретить посторонним запускать эти скрипты вручную ( запуск http://url/script.php в браузере, например) Я включил следующий код для проверки IP-адреса перед запуском самого скрипта. Где XX.XX.XX.XX представляет собой IP-адрес моей собственной сети.

    $remote = isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '127.0.0.1';
    $whitelist = array('XX.XX.XX.XX', '127.0.0.1');

    if (!in_array($remote, $whitelist))
    {
        exit;
    } 

Итак, теперь у меня есть следующие вопросы:

  • Насколько это безопасно?
  • Какие риски?
  • Как я могу сделать это более безопасным?
  • Есть ли другие (лучшие) решения?

PS. Мои предыдущие вопросы были закрыты, потому что кто-то подумал, что этот вопрос дублирует PHP белый список IP-адресов с подстановочными знаками . Но у меня это не так! Этот вопрос касается использования подстановочных знаков в белых списках, а этот вопрос касается безопасности и рисков этого решения.

Ответы [ 2 ]

1 голос
/ 09 мая 2020

Насколько это безопасно?

На самом деле это довольно безопасно, если вы контролируете адрес (127.0.0.1 в порядке, XXX.XXX.XXX.XXX может быть нет). Под довольно безопасно я имею в виду, что существует небольшая вероятность того, что кто-то может злоупотребить этой системой и не будет иметь гораздо больших шансов злоупотребить остальной частью веб-приложения .

Что есть риски?

Кто-то мог бы вызвать ваш скрипт извне, если бы у него был способ каким-то образом принять IP-адрес XXX.XXX.XXX.XXX или обмануть систему, заставив поверить, что они есть.

Как я могу сделать это более безопасным?

Вы можете включить секрет в исходный вызов и сравнить его с ha sh из тот же секрет. Секрет не раскрывается, даже если кто-то может прочитать сценарий.

if (!array_key_exists('key', $_GET)) {
    die('Access denied');
}
if (sha1($_GET['key']) !== '713dca7cf928f23a2347cae828d98879629e1e80') {
    die('Access denied');
}

Вы также можете разместить сценарий вне сети root и вызвать его с помощью оператора require . Таким образом, либо подсистема PHP работает, и сценарий не может быть прочитан, либо он не работает, и все, что обнаруживается, - это имя недоступного каталога. Вы даже можете объединить два подхода:

if (sha1($_GET['key']) !== '713dca7cf928f23a2347cae828d98879629e1e80') {
    die('Access denied');
}
$realScript = $_GET['key'];
require $realScript;

Теперь единственный скрипт, который может быть включен, - это тот, имя которого имеет это c SHA1 ha sh, и никаких других (риск коллизий практически ничтожен: вам понадобится коллизия с допустимым именем файла и средствами создания такого имени файла ). Итак, вы знаете , что сценарий действителен, но если имя не указано в вызове, вся конструкция не будет работать, и злоумышленник даже не скажет почему .

curl http://yoursite.internal.address/cron/cron.php?key=../scripts7ab9ceef/mycron.php

Есть ли другие (лучшие) решения?

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

С другой стороны, он требует установки интерфейса командной строки, что может создать другие проблемы с безопасностью, и даже если тот же пользователь и домашний каталог при использовании, два интерфейса могут по-прежнему вести себя немного по-разному (или не так тонко: у вас может есть веб-модуль PHP7 .3 и установка PHP5 .2 CLI, или наоборот, что приведет к сценарий с коротким синтаксисом массива (или с такими конструкциями, как if(empty(some_function($_GET['x']))) даже не загружать в тот или иной интерфейс.

В общем, вызов crontab для curl или lynx вероятно более удобен в обслуживании и прост в использовании, даже если он несомненно менее эффективен.

1 голос
/ 09 мая 2020

Представленный метод не является полностью безопасным.

PHP действует как текстовый препроцессор, что означает, что в случае ошибки шлюза веб-сервера содержимое скрипта может быть отправлено с mime-type text / html, что может привести к раскрытию конфиденциальных данных, таких как пароли к базе данных SQL или учетных записей ftp.

Административные сценарии, также помещенные в publi c несут риск их несанкционированного выполнения, если IP-адрес, контролируемый в сценарии, был совместно используемым (или динамически передаваемым) адресом. Скрипты Cron выполняются с использованием php -cli, поэтому шлюз веб-сервера ни для чего не нужен, и анализ IP в скрипте становится ненужным, если он находится за пределами каталога publi c.

Удаленное выполнение с использованием, например, curl может быть единственной причиной для размещения административных скриптов в пространстве publi c www server.. Обычно это слабое решение, потому что тогда скрипт выполняет интерпретатор php (а не php -cli) с другими настройками , обычно с резко ограниченным временем выполнения. Однако, если это по какой-то причине необходимо, он должен находиться в отдельном каталоге, доступ к которому ограничен указанными c IP-адресами с использованием .htaccess (и / или .iptables) и с назначенным именем пользователя и паролем с помощью htpasswd (Basi c Auth).

Идеальная ситуация, когда каталог publi c в www server (далее именуемый publi c) содержит только содержимое stati c (img, css , js ... файлов) и триггер приложения, расположенный в родительском каталоге. Пример структура:

/home/username/domainname/(apps,crons,public,tmp)

Каталог приложений должен содержать все файлы и каталоги приложений. Каталог publi c должен содержать только содержимое stati c (для порядка в некоторых подкаталогах) и символьную c ссылку на главный файл приложения, которую можно получить с помощью команды:

ln -s ../apps/app.php index.php

Некоторые конфигурации сервера не позволяют использовать символические ссылки. Затем вы можете использовать файл index. php, содержащий:

<?php
include('/home/username/domainname/apps/app.php');

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

Представленный анализ IP может использоваться для отображения части содержимого для авторизованных адресов, при условии, что сам файл php находится за пределами веб-сервера publi c. Однако, если это целые веб-сайты, я бы предпочел использовать iptables или .htaccess для управления доступом к ним.

...