Perl скрипты
Использование каналов
Вот скрипт, написанный без всякой защиты. Он отображает заданный файл из дерева каталогов /home/httpd/:
#pipe1.cgi
my $filename= "/home/httpd/".$input{filename};
print "<BODY>File : $filename<BR>";
open(FILE,"$filename") || goto form;
print <FILE>;
Не смейтесь с этого примера! Я видел подобные скрипты.
Первое использование его очевидно:
pipe1.cgi?filename=..%2F..%2F..%2Fetc%2Fpasswd
Нужно только поднятся вверх по дереву, чтобы получить доступ к любому файлу. Однако тут есть другая более интересная возможность: выполнить команду по своему выбору. В Perl, команда open(FILE, "/bin/ls") открывает двоичный файл "/bin/ls "... однако open(FILE, "/bin/ls |") исполняет указанную команду. Добавление одного символа канала | , изменяет поведение open() .
Другая проблема возникает из-за того, что не проверяется существование файла, что позволяет нам не только выполнить любую команду, но и передать ей аргументы: pipe1.cgi?filename=..%2F..%2F..%2Fbin%2Fcat%20%2fetc%2fpasswd%20| отображает содержимое файла паролей.
Проверка на существование файла для открытия, дает меньше свободы:
#pipe2.cgi
my $filename= "/home/httpd/".$input{filename};
print "<BODY>File : $filename<BR>";
if (-e $filename) {
open(FILE,"$filename") || goto form;
print <FILE>
} else {
print "-e failed: no file\n";
}
Предыдущий пример больше не работает. Проверка "-e " не проходит, так как невозможно найти файл "../../../bin/cat /etc/passwd | ".
Попробуем сейчас команду /bin/ls . Поведение скрипта будет тем же. То есть, если мы попытаемся вывести список файлов в директрии /etc , "-e " проверит существование файла "../../../bin/ls /etc | ", однако он также не существует. Так как мы не можем задать имя нужного файла, мы не сможем получить ничего интересного :(
Однако по-прежнему есть "выход из положения", даже если наш результат не так уж хорош. Файл /bin/ls существует (на большинстве систем), однако, если open() вызвана с этим именем файла, команда не будет выполнена, а будет выведен двоичный код. Поэтому мы должны найти способ поместить канал '| ' в конец имени, но так, чтобы он не использовался при проверке "-e ". Мы уже знаем решение - нулевой байт. Если мы пошлем "../../../bin/ls\0| " в качестве имени, проверка на существование пройдет успешно, так как она касается только "../../../bin/ls ", однако open() может видеть канал и поэтому выполнит команду. Поэтому, URI, который нам даст содержимое текущей дериктории таков:
pipe2.cgi?filename=../../../bin/ls%00|
[Назад]
[Содержание]
[Вперед]
Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
|