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). В примерах ниже продемонстрированы некоторые из таких безопасных конструкций.
 
   Примечание. Во всех примерах информация о параметрах соединения не хранится в тексте программы; мы вызываем специальные функции, которые считывают данные из пространства приложения.

Искупление греха в С#

   public string Query(string Id) {
   string ccnum;
   string sqlstring = "";
   // пропускаем только корректные ID (от 1 до 8 цифр)
   Regex r = new Regex(@"^\d{1,8}$");
   if (!r.Match(Id).Success)
   throw new Exception("Неверный ID. Попробуйте еще раз.");
   try {
   SqlConnection sqlConn = new SqlConnection(GetConnection);
   string str = "sp_GetCreditCard";
   cmd = new SqlCommand(str, sqlConn);
   cmd.CommandType = CommandType.StoredProcedure;
   cmd.Parameters.Add("@ID", Id);
   cmd.Connection.Open();
   SqlDataReader read = myCommand.ExecuteReader();
   ccnum = read.GetString(0);
   }
   catch (SqlException se) {
   throw new Exception("Ошибка – попробуйте еще раз.");
   }
   }

Искупление греха в PHP 5.0 и MySQL версии 4.1 и старше

   <?php
   $db = mysqli_connect(getServer(), getUid(), getPwd());
   $stmt = mysqli_prepare($link, "SELECT ccnum FROM cust WHERE id=?");
   $id = $HTTP_GET_VARS["id"];
   // пропускаем только корректные ID (от 1 до 8 цифр)
   if (preg_match('\d{1,8}$/',$id);
   mysqli_stmt_bind_param($stmt, "s", $id);
   mysqli_stmt_execute($stmt);
   mysqli_stmt_bind_result($stmt, $result);
   mysqli_stmt_fetch($stmt);
   if (empty($name)) {
   echo "Результата нет!";
   } else {
   echo $result;
   }
   else {
   echo "Неверный ID. Попробуйте еще раз.");
   }
   ?>
   Версии PHP ниже 5.0 не поддерживают связывания параметров с помощью показанной выше функции mysqli_prepare. Однако если для работы с базами данных вы пользуетесь архивом расширений PHP PEAR (PHP Extensions and Applications Repository, http://pear.php.net), то там есть функции DB_common::prepare() и DB_common::query() для подготовки параметризованных запросов.

Искупление греха в Perl/CGI

   #!/usr/bin/perl
   use DBI;
   use CGI;
   print CGI::header();
   $cgi = new CGI;
   $id = $cgi->param('id');
   // пропускаем только корректные ID (от 1 до 8 цифр)
   exit unless ($id =~ /^[\d]{1,8}$);
   print "<html><body>";
   // Параметры соединения получаем извне
   $dbh = DBI->connect(conn(),
                             conn_name(),
                             conn_pwd())
   or print "Ошибка connect";
                             # детальная информация об ошибке в $DBI::errstr
   $sql = "SELECT ccnum FROM cust WHERE id = ?";
   $sth = $dbh->prepare($sql)
   or print "Ошибка prepare";
 
   $sth->bind_param(1,$id);
   $sth->execute()
   or print "Ошибка execute";
 
   # Вывести данные
   while (@row = $sth->fetchrow_array ) {
   print "@row<br>";
   }
   $dbh->disconnect;
   print "</body></html>";
 
   exit;

Искупление греха в Java с использованием JDBC

   public static boolean doQuery(String Id) {
   // пропускаем только корректные ID (от 1 до 8 цифр)
   Pattern p = Pattern.compile("^\\d{1,8}$");
   if (!p.matcher(arg).find())
   return false;
   Connection con = null;
   try
   {
   Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
   con = DriverManager.getConnection("jdbc:microsoft:sqlserver: " +
                                                 "//localhost:1433", "sa", "$3cre+");
   PreparedStatement st = con.prepareStatement(
   "exec pubs..sp_GetCreditCard ?");
   st.setString(1, arg);
   ResultSet rs = st.executeQuery();
   while (rx.next()) {
      // Получить данные из rs.getString(1)
   }
   rs.close();
   st.close();
   }
   catch (SQLException e)
   {
   System.out.println("Ошибка SQL");
   return false;
   }
   catch (ClassNotFoundException e)
   {
   System.out.println("Ошибка во время исполнения");
   return false;
   }
   finally
   {
   try
   {
   con.close();
   } catch(SQLException e) {}
   }
   return true;
   }

Искупление греха в ColdFusion

   При работе с ColdFusion используйте cfqueryparam в теге <cfquery>, чтобы обезопасить запрос с параметрами.

Искупление греха в SQL

   Не следует исполнять в хранимой процедуре строку, полученную из не заслуживающего доверия источника, как процедуру. В качестве одного из механизмов глубоко эшелонированной обороны можно воспользоваться некоторыми функциями для проверки корректности строкового параметра. В примере ниже проверяется, что входной параметр содержит ровно четыре цифры. Заметим, что длина параметра заметно уменьшена, чтобы усложнить передачу любой другой входной информации.
   CREATE PROCEDURE dbo.doQuery(@id nchar(4))
   AS
   DECLARE @query nchar(64)
   IF RTRIM(@id) LIKE '[0-9][0-9][0-9][0-9]'
   BEGIN
   SELECT @query = 'select ccnum from cust where id = ''' + @id + ''''
   EXEC @query
   END
   RETURN
   Или еще лучше – потребуйте, чтобы параметр был целым числом:
   CREATE PROCEDURE dbo.doQuery(@id smallint)
   В Oracle lOg, как и в Microsoft SQL Server 2005, добавлены совместимые со стандартом POSIX регулярные выражения. Поддержка регулярных выражений реализована также для DB2 и Microsoft SQL Server 2000. В MySQL регулярные выражения поддерживаются с помощью оператора REGEXP. Ссылки на все эти решения вы найдете в разделе «Другие ресурсы».
   
Конец бесплатного ознакомительного фрагмента