Как успешно запустить Perl-скрипт с setuid () при использовании в качестве cgi-bin? - PullRequest
3 голосов
/ 14 февраля 2011

У меня есть 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()?

1 Ответ

4 голосов
/ 14 февраля 2011

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

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

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

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

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

...