Шрифт:
Выявление ошибки на этапе анализа кода
Во время анализа кода на предмет возможности внедрения SQL прежде всего ищите места, где выполняются запросы к базе данных. Ясно, что программам, не обращающимся к базе данных, эта напасть не угрожает. Мы обычно ищем следующие конструкции:
Выяснив, что в программе есть обращения к базе данных [1] , нужно определить, где выполняются запросы и насколько можно доверять данным, участвующим в запросе. Самое простое – найти все места, где выполняются предложения SQL, и посмотреть, производится ли конкатенация или подстановка небезопасных данных, взятых, например, из строки Web–запроса, из Web–формы или аргумента SOAP. Вообще, любых поступающих от пользователя данных!
Тестирование
Надо признать, что реальной альтернативы добросовестному анализу кода на предмет внедрения SQL не существует. Но иногда у вас может не быть доступа к коду, или вы просто не имеет опыта чтения чужих программ. Тогда дополните анализ кода тестированием.
Прежде всего определите все точки входа в приложение, где формируются SQL–запросы. Затем создайте тестовую программу–клиент, которая будет посылать в эти точки частично некорректные данные. Например, если тестируется Web–приложение, которое строит запрос на основе одного или нескольких полей формы, попробуйте вставить в них произвольные ключевые слова языка SQL. Следующий пример на Perl показывает, как это можно сделать.
#!/usr/bin/perl
use strict;
use HTTP::Request::Common qw(POST GET);
use HTTP::Headers;
use LWP::UserAgent;
srand time;
# Приостановить исполнение, если найдена ошибка
my $pause = 1;
# Тестируемый URL
my $url = \'http://mywebserver.xyzzy123.com/cgi-bin/post.cgi\
# Максимально допустимый размер HTTP-ответа
my $max_response = 1000;
# Допустимые города
my @cities = qw(Auckland Seattle London Portland Manchester Redmond
Brisbane Ndola);while (1) {
my $city = randomSQL($cities[rand @cities]);
my $zip = randomSQL(10000 + int(rand 89999));print «Пробую [$city] и [zip]\n»;
my $ua = LWP::UserAgent->new;
my $req = POST $url,
[ City => $city,
ZipCode => $zip,
];
# Послать запрос, получить ответ и поискать в нем признаки ошибки
my $res = $ua->request($req);
$_ = $res->as_string;
die "Хост недостижим\n" if /bad hostname/ig;
if ($res->status_line != 200
|| /error/ig
|| length($_) > $max_response) {
print "\nПотенциальная возможность внедрения SQL\n";
print;
getc if $pause;
}
}# Выбрать случайное ключевое слово SQL, в 50% случаев перевести
# его в верхний регистр
sub randomSQL {
$_ = shift;return $_ if ($rand > .75);
my @sqlchars = qw(1=1 2>1 «fred=»fre" + "d" or and select union drop update insert into dbo < > = \' .. – #);
my $sql = $sqlchars[rand @sqlchars]; $sql = uc($sql) id rand > .5;
return $_ . \' \' . $sql if rand > .9;
return $sql . \' \' . $_ if rand > .9;
return $sql;
}Этот код обнаружит возможность внедрения SQL только в случае, когда приложение возвращает сообщение об ошибке. Как мы уже сказали, нет ничего лучше тщательного анализа кода. Другой способ тестирования заключается в том, чтобы воспользоваться приведенной выше Perl–программой, заранее выяснить, как выглядит нормальный ответ, а затем анализировать, на какие запросы получен ответ, отличающийся от правильного, или вообще нет никакого ответа.
Имеются также инструменты третьих фирм, например AppScan компании Sanctum (теперь Watchfire) (www.watchfire.com), Weblnspect компании SPI Dynamics (www.spidynamics.com) и ScanDo компании Kavado (www.kavado.com).
Для оценки инструмента рекомендуем создать небольшое тестовое приложение с известными ошибками, допускающими внедрение SQL, и посмотреть, какие ошибки этот инструмент сумеет найти.
Примеры из реальной жизни
Следующие примеры внедрения SQL–команд взяты из базы данных CVE .
CAN–2004–0348
Цитата из бюллетеня CVE: «Уязвимость, связанная с внедрением SQL в сценарии viewCart.asp из программного обеспечения корзины для покупок компании SpiderSales, позволяет удаленному противнику выполнить произвольный SQL–запрос, воспользовавшись параметром userld».
Многие сценарии в программах SpiderSales не проверяют параметр userld, и этим можно воспользоваться для проведения атаки с внедрением SQL. Успешная атака позволяет противнику получить доступ к интерфейсу администратора SpiderSales и прочитать любую информацию из базы данных электронного магазина.
CAN–2002–0554
Цитата из бюллетеня CVE: «Модуль IBM Informix Web DataBlade 4.12 позволяет удаленному противнику обойти контроль доступа и прочитать произвольный файл путем атаки с внедрением SQL через HTTP–запрос».
Модуль Web DataBlade для базы данных Informix SQL динамически генерирует HTML–страницу на основе данных. Уязвимость отмечена в нескольких версиях Web DataBlade. Можно внедрить SQL–команды в любой запрос, обрабатываемый этим модулем. Результатом может стать раскрытие секретной информации или повышение уровня доступа к базе данных.
Искупление греха
Простейший и наиболее безопасный способ искупления – никогда не доверять входным данным, на основе которых формируется SQL–запрос, и пользоваться подготовленными или параметризованными предложениями (prepared statements).
Проверяйте все входные данные
Займемся для начала первой рекомендацией: никогда не доверять входным данным. Следует всегда проверять, что данные, подставляемые в SQL–предложение, корректны. Если вы работаете на языке достаточно высокого уровня, то проще всего воспользоваться для этого регулярным выражением.
Никогда не применяйте конкатенацию для построения SQL–предложений
Следующая рекомендация состоит в том, чтобы никогда не строить SQL–предложения посредством конкатенации или замены подстроки. Никогда! Пользуйтесь только подготовленными или параметризованными запросами. В некоторых технологиях это называется связыванием параметров (binding). В примерах ниже продемонстрированы некоторые из таких безопасных конструкций.