Запуск CGI-скриптов в Apache при помощи SuExec на сервере Ubuntu

Apache – самый популярный веб-сервер в мире. Он обслуживает статический и динамический контент сайтов в различных контекстах.

Один из самых распространённых способов генерирования динамического контента – это использование интерфейса CGI (Common Gateway Interface, общий шлюзовой интерфейс), который позволяет выполнять генерирующие веб-контент скрипты, написанные на разных языках программирования.

Однако запуск любого исполняемого кода в веб-пространстве всегда влечёт за собой определенный риск.

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

Требования

Поддержка CGI

В Ubuntu веб-сервер Apache поддерживает  отдельный каталог CGI-скриптов, который пуст по умолчанию.

В целом, CGI-скрипт – это любая программа, способная возвращать HTML и любые другие объекты или форматы, которые можно визуализировать в браузере.

Если открыть каталог настроек Apache и просмотреть включенные модули в каталоге mods-enabled, можно найти файл, отвечающий за поддержку CGI:

less /etc/apache2/mods-enabled/cgi.load
LoadModule cgi_module /usr/lib/apache2/modules/mod_cgi.so

Этот файл содержит директиву, которая включает модуль CGI.

Модуль уже загружен, но пока что он не обслуживает скрипты; для этого его нужно включить в определенной среде.

Откройте стандартный файл виртуального хоста:

sudo nano /etc/apache2/sites-enabled/000-default

Сначала в нем нужно указать ServerName:

<VirutalHost *:80>
ServerName домен_или_IP_адрес_сервера
ServerAdmin email_адрес
. . .

Немного ниже в файле находится раздел, который отвечает за поддержку скриптов CGI:

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>

Рассмотрим его подробнее.

Директива ScriptAlias указывает каталог, из которого Apache может запускать скрипты. В данном случае это каталог /usr/lib/cgi-bin. Второй аргумент задаёт путь к каталогу скриптов, а первый (/cgi-bin/) – это URL.

Это значит, что скрипт по имени script.pl, хранящийся в каталоге /usr/lib/cgi-bin, будет запускаться по ссылке:

your_domain.com/cgi-bin/script.pl

Его вывод вернётся в браузер и будет визуализирован на этой странице.

Раздел Directory содержит правила работы каталога /usr/lib/cgi-bin. Обратите внимание на:

Options +ExecCGI ...

Эта опция на самом деле не нужна, поскольку все настройки предназначены для каталога скриптов CGI, указанного в ScriptAlias. Однако она не повредит конфигурацию, потому её можно оставить.

Чтобы иметь возможность размещать CGI-скрипты вне каталога ScriptAlias, нужно добавить в раздел Directory следующие опции:

Options +ExecCGI
AddHandler cgi-script .pl .rb [extensions to be treated as CGI scripts]

Сохраните и закройте файл. Если вы внесли в него какие-либо поправки, перезапустите веб-сервер:

sudo service apache2 restart

Тестовый CGI-скрипт

Теперь попробуйте создать тестовый CGI-скрипт.

Как указано в настройках, для хранения скриптов CGI предназначен отдельный каталог /usr/lib/cgi-bin. Пользователи без прав root не имеют права на запись в этом каталоге, потому нужно открыть следующий файл с sudo:

sudo nano /usr/lib/cgi-bin/test.pl

Этот файл имеет расширение .pl, потому что это Perl-скрипт; Apache будет запускать все файлы в этом каталоге и передавать их соответствующим программам.

Укажите, что этот файл нужно выполнять в Perl, добавив в начало скрипта:

#!/usr/bin/perl

После этого необходимо указать тип генерируемого контента. Это нужно для того, что веб-браузер понимал, как отображать полученный вывод. К примеру, данный скрипт будет выводить контент HTML (text/html) при помощи стандартной функции Perl.

print "Content-type: text/html\n\n";

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

Добавьте к первым двум обязательным строкам следующий набор компонентов. В результате получится такой скрипт:

#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "<html><head><title>Hello There...</title></head>";
print "<body>";
print "<h1>Hello, World.</h1><hr>";
print "<p>This is some regular text.</p>";
print "<p>The possibilities are great.</p>";
print "</body></html>";

Сохраните и закройте файл.

Сделайте его исполняемым:

sudo chmod 755 /usr/lib/cgi-bin/test.pl

Если теперь открыть в браузере домен и каталог CGI, а затем добавить имя скрипта, на экране появится вывод данного скрипта.

your_domain.com/cgi-bin/test.pl
Hello, World.
This is some regular text.
The possibilities are great.

Как видите, эта простейшая страница правильно отображается.

При попытке просмотреть исходник страницы на экране появятся только аргументы для отображения, без типа контента:

<html><head><title>Hello There...</title></head>
<body><h1>Hello, World.</h1><hr><p>This is some regular text.</p>
<p>The possibilities are great.</p></body></html>

Включение модуля SuExec

Создавая скрипт, который может выполнить любой пользователь, вы подвергаете безопасность сервера некоторому риску. В идеале, право на запуск скриптов должно быть только у одного заблокированного пользователя. Для этого и предназначен модуль suexec.

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

sudo apt-get install apache2-suexec-custom

Включите модуль:

sudo a2enmod suexec

Создайте нового пользователя, которому будут принадлежать все права на файлы скрипта. Если сервер обслуживает несколько сайтов, создайте отдельного пользователя для каждого из них.

sudo adduser script_user

Можно пропустить все запросы данных (включая запрос на установку пароля).

Создайте каталог скриптов в домашнем каталоге нового пользователя:

sudo mkdir /home/script_user/scripts

Модуль suexec требует очень строгого контроля над правами на запись в каталоге. Передайте права на каталог пользователю script_user и измените права доступа, чтобы никто не мог писать в нем:

sudo chown script_user:script_user /home/script_user/scripts
sudo chmod 755 /home/script_user/scripts

Теперь создайте скрипт-файл, а затем скопируйте и вставьте в него созданный ранее скрипт:

sudo -u script_user nano /home/script_user/scripts/attempt.pl
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "<html><head><title>Hello There...</title></head>";
print "<body>";
print "<h1>Hello, World.</h1><hr>";
print "<p>This is some regular text.</p>";
print "<p>The possibilities are great.</p>";
print "</body></html>";

Сделайте файл исполняемым. Все права на файл должны быть только у пользователя script_user; их можно настроить при помощи модуля suexec:

sudo chmod 700 /home/script_user/scripts/attempt.pl

После этого отредактируйте настройки виртуального хоста Apache, чтобы новый пользователь мог запускать скрипт.

sudo nano /etc/apache2/sites-enabled/000-default

Сначала настройте каталог CGI; вместо директивы ScriptAlias используйте директиву Alias в комбинации с опцией ExecCGI и директивой SetHandler.

Добавьте в файл:

Alias /scripts/ /home/script_user/scripts/
<Directory "/home/script_user/scripts">
Options +ExecCGI
SetHandler cgi-script
</Directory>

Теперь можно получить доступ к скриптам, перейдя в подкаталог /scripts. Чтобы включить эти функции suexec, добавьте следующую строку вне раздела Directory, но в рамках раздела VirtualHost.

SuexecUserGroup script_user script_user

Сохраните и закройте файл.

Теперь нужно задать каталоги, которые модуль suexec будет считать валидными (это та функция, которая отсутствует в стандартной версии модуля). Откройте конфигурационный файл suexec.

sudo nano /etc/apache2/suexec/www-data

В начале файла нужно указать путь к каталогу scripts.

/home/script_user/scripts/

Сохраните и закройте файл.

Теперь перезапустите веб-сервер.

sudo service apache2 restart

Откройте в браузере ссылку:

your_domain.com/scripts/attempt.pl

И на экране появится:

Hello, World.
This is some regular text.
The possibilities are great.

Обратите внимание: после настройки модуля suexec обычный каталог CGI не работает; такое поведение предназначено для контроля привилегий скриптов.

Заключение

Теперь вы можете создавать сценарии CGI и запускать их относительно безопасным способом. Скрипты CGI очень полезны, так как позволяют быстро добавить на сайт динамический контент. А при помощи модуля suexec можно защитить эти скрипты.

Однако будьте предельно внимательны при работе с модулем suexec! Неправильная настройка модуля может создать дополнительные уязвимости безопасности. Чтобы выяснить потенциальные уязвимости suexec, изучите конфигурацию модуля.

Tags: , , ,

Добавить комментарий