Как запустить команды оболочки в CGI-программе от имени пользователя nobody? - PullRequest
1 голос
/ 28 апреля 2011

Я хочу запускать команды оболочки в CGI-программе (написанной на Perl). Моя программа не имеет прав root. Это работает как никто. Я хочу использовать этот код:

use strict;
system <<'EEE';
awk '{a[$1]+=$2;b[$1]+=$3}END{for(i in a)print i, a[i], b[i]|"sort -nk 3"}' s.txt
EEE

Я могу успешно запустить свой код с помощью perl из командной строки, но не как CGI-программа.

Ответы [ 5 ]

1 голос
/ 26 февраля 2013

Исходя из кода в вашем вопросе, есть как минимум четыре варианта сбоя.

  1. У пользователя nobody нет разрешения на выполнение вашей программы.
  2. Код Perlв вашем вопросе нет строки shebang (#!).Вы пытаетесь запустить awk, поэтому я предполагаю, что вы работаете в какой-то форме Unix.Если в вашем коде отсутствует эта строка, то ваша операционная система не знает, как запустить вашу программу.
  3. Файл s.txt либо не находится в рабочем каталоге исполняемой программы, либо он не доступен для чтения никем.пользователь.
  4. По какой-либо причине awk недоступен через PATH среды вашей исполняемой программы.

Чтобы быстро диагностировать такие проблемы низкого уровня, попробуйте устранить все ошибки.вывод, чтобы показать в браузере.Один из способов сделать это - добавить следующую строку сразу после строки shebang в вашем коде.

BEGIN {
    print "Content-type: text/plain\n\n";
    open STDERR, ">&", \*STDOUT or print "$0: dup: $!";
}

Вывод будет отображаться как обычный текст, а не как HTML, но это временная мера для просмотра вывода вашей программы.Оборачивая его в блок BEGIN, код выполняется сразу после его анализа.Перенаправление STDERR означает, что ваш браузер также получает что-либо записанное в стандартный вывод.

Другой способ сделать это - с помощью модуля CGI :: Carp .

use CGI::Carp 'fatalsToBrowser';

Таким образом, ошибки попадают в браузер, а также в журнал ошибок веб-сервера.

Если вы все еще видите ошибки 500-серии с вашего сервера, проблема происходит на более низком уровне: возможно, произошел сбой при запускеperl.Зайдите в журнал ошибок вашего сервера.После выполнения вашей программы вы можете удалить это временное перенаправление вывода ошибок.

Наконец, я рекомендую изменить вашу программу на

#! /usr/bin/perl -T

BEGIN { print "Content-type: text/plain\n\n"; }

use strict;
use warnings;

$ENV{PATH} = "/bin:/usr/bin";

my $input = "/path/to/your/s.txt";

my $buckets = <<'EOProgram'
{ a[$1] += $2; b[$1] += $3 }

END { for (i in a) print i, a[i], b[i] }
EOProgram

open STDIN, "-|", "awk", $buckets, $input or die "$0: open: $!";
exec "sort", "-nk", 3                     or die "$0: exec: $!";

Переключатель -T включает анализ потока данных безопасности, называемый taint mode , который запрещает вам использовать неанизированный ввод для системных операций, таких как open, exec и т. Д., Которые злоумышленник (или обычный пользователь, предоставляющий неожиданный ввод) может использовать для нанесения вреда вашей системе.Вы всегда должны добавлять -T в CGI-программы и любой другой код, который запускается от имени другого пользователя.

Учитывая характер вашей awk-программы, тип содержимого text / plain кажется разумным.Выведите его как можно скорее.

При включенном режиме taint укажите значение переменной окружения PATH.Если вместо этого вы придерживаетесь того ненадежного PATH, который унаследует ваша программа, попытка запуска внешних программ завершится неудачей.

Зафиксируйте полный путь ввода.Это исключит неожиданности.

Использование форм с несколькими аргументами open и exec устраняет оболочку и ее синтаксический анализ.(Для полноты system также имеет аналогичную форму с несколькими аргументами.) Да, если написать это таким образом, это может означать, что будет немного более преднамеренным (например, разбив аргументы и настроив конвейер самостоятельно), но это также позволяет избежать неприятных сюрпризов.

0 голосов
/ 28 апреля 2011

Вы можете просто сделать это встроенным без необходимости раскошелиться на другой процесс ...

if ( open my $fh, '<', 's.txt' ) {
    my %data;
    while (<$fh>) {
        my ($c1,$c2,$c3) = split;
        $data{a}{$c1} += $c2;
        $data{b}{$c1} += $c3;
    }
    foreach ( sort { $data{b}{$a} <=> $data{b}{$b} } keys %{ $data{b} } ) {
        print "$_ $data{a}{$_} $data{b}{$_}\n";
    }

} else {
    warn "Unable to open s.txt: $!\n";
}
0 голосов
/ 28 апреля 2011

Я бы предложил выяснить полный путь к awk и указать его напрямую.Вероятно, никто из тех, кто запустил httpd, не имеет минимального пути в $ ENV {PATH}.Отображение $ ENV {PATH}, я думаю, покажет это.

Это хорошо, я бы не стал изменять путь, а просто указал путь / usr / bin / awk или что нет.

Если у вас есть доступ к оболочке, и он работает, наберите 'which awk', чтобы узнать это.

0 голосов
/ 28 апреля 2011

я могу успешно запускать свои коды в perl-файле, но не в cgi-файле.

На каком веб-сервере вы работаете?Например, apache требует печати заголовка CGI, т.е. print "Content-type: text/plain; charset=utf-8\n\n" или

use CGI;
my $q = CGI->new();
print $q->header('text/html');

(см. CGI )

Apache будет подтверждать в журнале (error.log) о "преждевременном завершении заголовков сценариев", ЕСЛИ то, что я сказал, имеет место.

0 голосов
/ 28 апреля 2011

Я уверен, что nobody разрешено запускать команды оболочки. Проблема в том, что nobody не имеет разрешения на открытие файла s.txt. Добавьте разрешение на чтение для всех в s.txt и добавьте разрешение на выполнение для всех в каждом каталоге до s.txt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...