Как успешно запустить Perl-скрипт с setuid() при использовании в качестве cgi-bin?

У меня есть Perl-скрипт, который вызывается либо через Apache, либо из командной строки.

В целях тестирования я передаю ему имя пользователя, с которым должен работать Perl-скрипт, и использую POSIX::setuid для установки uid.

Если я запускаю скрипт из командной строки, то uid устанавливается правильно:

use CGI::Pretty qw/:standard/;
use POSIX qw(setuid getuid);

...
my ($pwName, $pwCode, $pwUid, $pwGid, $pwQuota, $pwComment, 
    $pwGcos, $pwHome, $pwLogprog) = getpwnam($username);

if ((defined $pwUid) && (getuid() == $pwUid)) {
    setuid($pwUid);
    print header;
    print Dumper $<;
}
else {
    print header(-status => 401);
    print "Could not setuid to correct uid (currently: )".getuid()."\n";
}

Вывод командной строки показывает правильный uid указанного $username вместо uid тестовой учетной записи, которая запустила скрипт.

Если я вызываю скрипт через Apache, то uid остается равным идентификатору пользователя apache и никогда не меняется.

Я не верю, что могу использовать здесь suExec, потому что после прочтения документации:

  1. Я не могу поместить копию этого скрипта в http://www.example.com/~username для каждого $username. Сценарий должен запускаться из одного места, и мне нужно указать uid внутри сценария.

  2. Мне нужно, чтобы сценарий запускался как указанное имя пользователя во время выполнения, а не как одно имя пользователя, указанное один раз в директиве виртуального хоста в файле конфигурации Apache. Изменение этого файла конфигурации и перезапуск Apache каждый раз, когда новый пользователь запускает этот скрипт, нереально.

Как заставить Perl-скрипт, работающий как cgi-bin, правильно изменить uid при использовании setuid()?


person Alex Reynolds    schedule 14.02.2011    source источник
comment
У вашего пользователя командной строки, вероятно, есть права на изменение своего UID, а у вашего пользователя веб-сервера, вероятно, нет?   -  person Konerak    schedule 14.02.2011


Ответы (1)


Единственный способ, которым вы можете setuid перейти к произвольному uid, — запустить от имени пользователя root.[1]

Не знаю, как вам, но идея CGI-программы, работающей от имени пользователя root, вызывает у меня кошмары.

Что должен делать этот код после смены uid? Возможно, есть способ сделать это без необходимости setuid?

[1] В зависимости от вашего кода и его модели безопасности вы можете получить пароль пользователя и использовать su/sudo[2] для запуска отдельной программы командной строки для выполнения реальных операций за пределами среды веб-сервера, но su/sudo могут сделать это, потому что они являются суперпользователями, и это все равно вызовет большинство/все проблемы, связанные с запуском CGI-кода от имени root. Даже если вы отфильтруете root как недопустимое имя пользователя, возможность маскироваться под любого произвольного пользователя открывает множество возможностей для злоупотреблений.

[2] sudo можно даже настроить так, чтобы разрешить это без запроса пароля, но на этом пути есть драконы. Убедитесь, что вы знаете, что делаете, если попытаетесь это сделать, иначе вы дадите своим пользователям полную свободу действий, чтобы выдавать себя за другого по своему желанию.

person Dave Sherohman    schedule 14.02.2011
comment
Этот cgi-bin используется с вызовом Ajax. Сценарий должен запускаться от имени указанного пользователя, чтобы ограничить доступ этого пользователя к списку его или ее файлов в файловой системе, доступной для веб-сервера. - person Alex Reynolds; 14.02.2011
comment
Я думаю, что мне придется разделить код, который я использую, чтобы предоставить список каталогов, а затем отфильтровать результаты на основе uid предоставленного имени пользователя. - person Alex Reynolds; 14.02.2011
comment
@Alex - последнее (иметь CGI-фильтрацию результатов на основе идентификатора пользователя) на самом деле является лучшим решением этой проблемы. - person DVK; 15.02.2011