Привет! В первой части мы поговорим о взломе
сервера. Не о всех ошибках, а только о тех, где входной параметр это имя файла. Это значит, что когда ты в строке
браузера видишь что-то вроде:

www.target.ru/cgi-bin/auth.pl?file=data.db?user=xakep

то это именно тот случай. Приступим к вскрытию 🙂
Я надеюсь тебе известно, что PERL был всегда
не обделен вниманием со стороны хакеров. А все потому, что если автор скрипта не полностью
(или вообще) не  отфильтровал входные параметры, то с сайтом можно было творить удивительные вещи
🙂 Давайте рассмотрим простой пример: 

$location = '/users/data/file.dat'; 
open(FILE, "$location"); 

эта конструкция открывает файл. Допустим что $location (имя файла) не указано в
самом коде, а выдирается с входной строки. Тогда этот код примет такой вид: 

$location = $ENV{'QUERY_STRING'}; 
open(FILE, "$location"); 

Пусть потом этот файл выводится нам в браузер следующим образом: 

@data = <FILE>; 
close(FILE); 
print @data; 

В следствии чего мы можем в входном параметре указать например /etc/passwd и
наивный скрипт выведет его на экран. Неплохо... но теперь это почти не катит.
Ладно, пусть кодер защитил себя установив четко базовую директорию: 

$location = '/users/data/'; 
(undef, $location) .= split(/?/, $ENV{'QUERY_STRING'}); 
open(File, "$location"); 

Но теперь если мы введем ../../etc/passwd, то получим
тот же результат 🙂 Берем  такой вариант, что скрипт обрезает
последовательность "../" следующим образом: 

$location = '/users/data/'; 
(undef, $location) .= split(/?/, $ENV{'QUERY_STRING'}); 
$location = s/\.\.\///g; 
open(File, "$location"); 

Думаете этот код защищен? Неееа! В никсах можно использовать место конструкции
"../../etc/passwd" следующую ".\./.\./etc/passwd", и снова на экране нужный
файл :). Потому что "../" фильтр не обнаружит а мы используем
".\./", что имеет идентичные функции.
Хорошо, посмотрим дальше: 

$location = '/users/data/'; 
(undef, $location) .= split(/?/, $ENV{'QUERY_STRING'}); 
$location =s~\\~~g; 
$location=s~\.\./~~g; 
open(File, "$location"); 

или 

$location = '/users/data/'; 
(undef, $location) .= split(/?/, $ENV{'QUERY_STRING'}); 
$location =s/\\//g; 
$location=s/\.\.\///g; 
open(File, "$location"); 

Этот фильтр обрезает "../" и "\" со строки. Неплохо правда? Давайте посмотрим
на примере... Если передать строку "fi../le" или "fi\le" то получится "file".
Хммм.... А если ввести ".../...//" то что получится? Первую точку он пропустит,
удалит "../", точку пропустит, "../" удалит, "/" пропустит. Так что мы имеем? А
имеем мы строку "../" - то, что нам и надо. Значит теперь мы пропишем в строке
браузера место реального имени файла что-то вроде
".../...//.../...//etc/passwd". Результат тот же, что и в первых случаях.
Каждый профессионал иногда допускается ошибки при фильтрации метасимволов
(&;`'\"|*?~<>^()[]{}$\n\r). Вот еще один пример: 

$location =~ s/([\&;\`'\|\"*\?\~\^\(\)\[\]\{\}\$\n\r])/\\$1/g; 
$location =~ s/\0//g; 
unless (open(FILE, $location)) 

Если вы заметили, то они не фильтруют "\". Теперь если мы введем такое имя файла
"cat file.dat\|" то после фильтрации получим "cat file.dat\\|". Символ "\"
используется для того, чтобы не сработал мета символ "|". Эта ошибка очень
распространенная.... Если вы не поняли вот еще один пример. Пусть мы ввели
"/bin/echo "all ok" > file.dat|" - после фильтрации мы получим "/bin/echo "all
ok" > file.dat\|", и это не сработает. А если ввести "/bin/echo "all ok" >
file.dat\|", то получим строку "/bin/echo "all ok" > file.dat\\|". А этот код
уже сработает! 

Ну как еще не умер со скуки? А если тебе надо хороший фильтр то можешь вставить
перед открытием файла такую строчку: 

if($location =~ /[\&;\`'\|\"*\?\~\^\(\)\[\]\{\}\$]/) {&ErrorPageAndLog('Урод,
даже не старайся сломать мой сервак');} 

Ну вот на этом первая часть окончена... И помните ЭТО только
начало 8)

Оставить мнение