Внедрение SQL-кода

Поделись знанием:
Перейти к: навигация, поиск

Внедрение SQL-кода (англ. SQL injection) — один из распространённых способов взлома сайтов и программ, работающих с базами данных, основанный на внедрении в запрос произвольного SQL-кода.

Внедрение SQL, в зависимости от типа используемой СУБД и условий внедрения, может дать возможность атакующему выполнить произвольный запрос к базе данных (например, прочитать содержимое любых таблиц, удалить, изменить или добавить данные), получить возможность чтения и/или записи локальных файлов и выполнения произвольных команд на атакуемом сервере.

Атака типа внедрения SQL может быть возможна из-за некорректной обработки входных данных, используемых в SQL-запросах.

Разработчик прикладных программ, работающих с базами данных, должен знать о таких уязвимостях и принимать меры противодействия внедрению SQL.





Принцип атаки внедрения SQL

Допустим, серверное ПО, получив входной параметр id, использует его для создания SQL-запроса. Рассмотрим следующий PHP-скрипт:

# Предыдущий код скрипта...
$id = $_REQUEST['id'];
$res = mysql_query("SELECT * FROM news WHERE id_news =".$id);
# Следующий код скрипта...

Если на сервер передан параметр id, равный 5 (например так: example.org/script.php?id=5), то выполнится следующий SQL-запрос:

SELECT * FROM news WHERE id_news = 5

Но если злоумышленник передаст в качестве параметра id строку -1 OR 1=1 (например, так: example.org/script.php?id=-1+OR+1=1), то выполнится запрос:

SELECT * FROM news WHERE id_news = -1 OR 1=1

Таким образом, изменение входных параметров путём добавления в них конструкций языка SQL вызывает изменение в логике выполнения SQL-запроса (в данном примере вместо новости с заданным идентификатором будут выбраны все имеющиеся в базе новости, поскольку выражение 1=1 всегда истинно — [en.wikipedia.org/wiki/Short-circuit_evaluation вычисления происходят по кратчайшему контуру в схеме]).

Внедрение в строковые параметры

Предположим, серверное ПО, получив запрос на поиск данных в новостях параметром search_text, использует его в следующем SQL-запросе (здесь параметры экранируются кавычками):

$search_text = $_REQUEST['search_text'];
$res = mysql_query("SELECT id_news, news_date, news_caption, news_text, news_id_author
                      FROM news WHERE news_caption LIKE('%$search_text%')");

Сделав запрос вида example.org/script.php?search_text=Test мы получим выполнение следующего SQL-запроса:

SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news 
  WHERE news_caption LIKE('%Test%')

Но, внедрив в параметр search_text символ кавычки (который используется в запросе), мы можем кардинально изменить поведение SQL-запроса. Например, передав в качестве параметра search_text значение ')+and+(news_id_author='1, мы вызовем к выполнению запрос:

SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news 
  WHERE news_caption LIKE('%') and (news_id_author='1%')

Использование UNION

Язык SQL позволяет объединять результаты нескольких запросов при помощи оператора [www.sql.ru/docs/sql/u_sql/ch14.shtml UNION]. Это предоставляет злоумышленнику возможность получить несанкционированный доступ к данным.

Рассмотрим скрипт отображения новости (идентификатор новости, которую необходимо отобразить, передается в параметре id):

$res = mysql_query("SELECT id_news, header, body, author FROM news WHERE id_news = " . $_REQUEST['id']);

Если злоумышленник передаст в качестве параметра id конструкцию -1 UNION SELECT 1,username, password,1 FROM admin, это вызовет выполнение SQL-запроса

SELECT id_news, header, body, author FROM news WHERE id_news = -1 UNION SELECT 1,username,password,1 FROM admin

Так как новости с идентификатором −1 заведомо не существует, из таблицы news не будет выбрано ни одной записи, однако в результат попадут записи, несанкционированно отобранные из таблицы admin в результате инъекции SQL.

Использование UNION + group_concat()

В некоторых случаях хакер может провести атаку, но не может видеть более одной колонки. В случае MySQL взломщик может воспользоваться функцией:
group_concat(col, symbol, col)
которая объединяет несколько колонок в одну. Например, для примера данного выше вызов функции будет таким:
-1 UNION SELECT group_concat(username, 0x3a, password) FROM admin

Экранирование хвоста запроса

Зачастую, SQL-запрос, подверженный данной уязвимости, имеет структуру, усложняющую или препятствующую использованию union. Например скрипт

$res = mysql_query("SELECT author FROM news WHERE id=" . $_REQUEST['id'] ." AND author LIKE ('a%')");

отображает имя автора новости по передаваемому идентификатору id только при условии, что имя начинается с буквы а, и внедрение кода с использованием оператора UNION затруднительно.

В таких случаях, злоумышленниками используется метод экранирования части запроса при помощи символов комментария(/* или -- в зависимости от типа СУБД).

В данном примере, злоумышленник может передать в скрипт параметр id со значением -1 UNION SELECT password FROM admin/*, выполнив таким образом запрос

SELECT author FROM news WHERE id=-1 UNION SELECT password FROM admin/* AND author LIKE ('a%')

в котором часть запроса ( AND author LIKE ('a%')) помечена как комментарий и не влияет на выполнение.

Расщепление SQL-запроса

Для разделения команд в языке SQL используется символ ; (точка с запятой), внедряя этот символ в запрос, злоумышленник получает возможность выполнить несколько команд в одном запросе, однако не все диалекты SQL поддерживают такую возможность.

Например, если в параметры скрипта

$id = $_REQUEST['id'];
$res = mysql_query("SELECT * FROM news WHERE id_news = $id");

злоумышленником передается конструкция, содержащая точку с запятой, например 12;INSERT INTO admin (username, password) VALUES ('HaCkEr', 'foo'); то в одном запросе будут выполнены 2 команды

SELECT * FROM news WHERE id_news = 12;
INSERT INTO admin (username, password) VALUES ('HaCkEr', 'foo');

и в таблицу admin будет несанкционированно добавлена запись HaCkEr.

Методика атак типа внедрение SQL-кода

Поиск скриптов, уязвимых для атаки

На данном этапе злоумышленник изучает поведение скриптов сервера при манипуляции входными параметрами с целью обнаружения их аномального поведения. Манипуляция происходит всеми возможными параметрами:

  • Данными, передаваемыми через методы POST и GET
  • Значениями [HTTP-Cookie]
  • HTTP_REFERER (для скриптов)
  • AUTH_USER и AUTH_PASSWORD (при использовании аутентификации)

Как правило, манипуляция сводится к подстановке в параметры символа одинарной (реже двойной или обратной) кавычки.

Аномальным поведением считается любое поведение, при котором страницы, получаемые до и после подстановки кавычек, различаются (и при этом не выведена страница о неверном формате параметров).

Наиболее частые примеры аномального поведения:

  • выводится сообщение о различных ошибках;
  • при запросе данных (например, новости или списка продукции) запрашиваемые данные не выводятся вообще, хотя страница отображается

и т. д. Следует учитывать, что известны случаи, когда сообщения об ошибках, в силу специфики разметки страницы, не видны в браузере, хотя и присутствуют в её HTML-коде.

Конструкция Комментирование остатка строки Получение версии Конкатенация строк
MySQL -- ... или /* ... version() concat (string1string2)
MS SQL -- ... @@version string1 + string2
Oracle -- ... или /* ... select banner
from v$version
string1 || string2
или concat (string1string2)
MS Access Внедрение в запрос NULL‑байта: %00...
PostgreSQL -- ... version() string1 || string2
Sybase -- ... @@version string1 + string2
IBM DB2 -- ... select versionnumber from sysibm.sysversions string1 || string2 или string1 concat string2
Ingres -- ... dbmsinfo('_version') string1 || string2

Защита от атак типа внедрение SQL-кода

Для защиты от данного типа атак необходимо тщательно фильтровать входные параметры, значения которых будут использованы для построения SQL-запроса.

Фильтрация строковых параметров

Предположим, что код, генерирующий запрос (на языке программирования Паскаль), выглядит так:

statement := 'SELECT * FROM users WHERE name = "' + userName + '";';

Чтобы внедрение кода (закрытие строки, начинающейся с кавычки, другой кавычкой до её завершения текущей закрывающей кавычкой для разделения запроса на две части) было невозможно, для некоторых СУБД, в том числе, для MySQL, требуется брать в кавычки все строковые параметры. В само́м параметре заменяют кавычки на \", апостроф на \', обратную косую черту на \\ (это называется «экранировать спецсимволы»). Это можно делать таким кодом:

statement := 'SELECT * FROM users WHERE name = ' + QuoteParam(userName) + ';';
function QuoteParam(s : string) : string;
{ на входе — строка; на выходе — строка в кавычках и с заменёнными спецсимволами }
var
  i : integer;
  Dest : string;
begin
  Dest := '"';
  for i:=1 to length(s) do
    case s[i] of
      '''' : Dest := Dest + '\''';
      '"' : Dest := Dest + '\"';
      '\' : Dest := Dest + '\\';
    else Dest := Dest + s[i];
    end; 
  QuoteParam := Dest + '"';
end;

Для PHP фильтрация может быть такой:

<?
$query = "SELECT * FROM users WHERE user='".mysql_real_escape_string($user)."';";
?>

Фильтрация целочисленных параметров

Возьмём другой запрос:

statement := 'SELECT * FROM users WHERE id = ' + id + ';';

В данном случае поле id имеет числовой тип, и его чаще всего не берут в кавычки. Поэтому «закавычивание» и замена спецсимволов на escape-последовательности не проходит. В таком случае помогает проверка типа; если переменная id не является числом, запрос вообще не должен выполняться.

Например, на Delphi для противодействия таким инъекциям помогает код:

if TryStrToInt(id, id_int) then
  statement := Format('SELECT * FROM users WHERE id =%0:d;', [id_int]);

Для PHP этот метод будет выглядеть так:

 $query = 'SELECT * FROM users WHERE id = ' . (int)$id;

Усечение входных параметров

Для внесения изменений в логику выполнения SQL-запроса требуется внедрение достаточно длинных строк. Так, минимальная длина внедряемой строки в вышеприведённых примерах составляет 8 символов («1 OR 1=1»). Если максимальная длина корректного значения параметра невелика, то одним из методов защиты может быть максимальное усечение значений входных параметров.

Например, если известно, что поле id в вышеприведённых примерах может принимать значения не более 9999, можно «отрезать лишние» символы, оставив не более четырёх:

statement := 'SELECT * FROM users WHERE id = ' + LeftStr(id, 4) + ';';

Функция по автоматическому определению зарезервированных SQL слов в тексте и занесению IP в бан лист

Пример функции на PHP, которая подсчитывает количество зарезервированных SQL слов в тексте и далее при превышении этого количества заданного значения, IP заносится в «бан лист», функция возвращает TRUE, далее прекращается работа скрипта. Один раз попавшись за SQL инъекцией этот IP будет заблокирован навсегда. Хотя при желании можно блокировать работу скрипта, только в момент прихода зарезервированных SQL слов, для этого закомментируйте строки по проверке IP в таблице банов. Для русского языка достаточно 2-3 совпадения с зарезервированными SQL словами, для английского возможно стоит увеличить…

//return true if more $max_sql_words in text or banned before
function f_check_sql($txt_sql,$max_sql_words=3){//$max_sql_words=3 - 3 ... 4 or more - if more $max_sql_words, then ban this IP and return with TRUE
	$ip=$_SERVER['REMOTE_ADDR'];
	$is_banned=mysql_query("select ip from IP_banned where ip='".$ip."'");
	if(mysql_num_rows($is_banned)>0){echo "IP:".$ip." is banned for SQL injection<p>";return true;}
	preg_match_all("/(INFORMATION_SCHEMA|select|alter|table|update|CONCAT|from|where|schema|delete|insert|GROUP BY|UNION)/i",$txt_sql, $sqlin);
	if(count($sqlin[0])>=$max_sql_words){
		$fwords="";
		for ($i=0; $i< count($sqlin[0]); $i++) {$fwords.= $sqlin[0][$i]." ";}
		echo "Forbidden words:<p>".$fwords."<p>Your IP: ".$ip." banned for SQL injection</p>";
		@mysql_query("insert into IP_banned (ip, sql_words,dt) values('".$ip."','".mysql_real_escape_string($fwords)."',now())");//insert $ip to table or to file with banned IPs
		return true;
	}
	return false;
}
// table sample - CREATE TABLE `IP_banned` (  `ipid` int(11) NOT NULL AUTO_INCREMENT,  `ip` varchar(16) NOT NULL,  `sql_words` varchar(64) DEFAULT NULL,  `dt` date NOT NULL,  UNIQUE KEY `ip` (`ip`),  KEY `id` (`ipid`)) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

Функция вызывается так:

if(f_check_sql($_POST["query"],3)){exit("<p>exit from script");}//exit if 3 or more SQL words in text

Её нужно вызывать до обращения к базе данных с присланными из формы данными. Например проверить все присланные данные в цикле.

Использование параметризованных запросов

Многие сервера баз данных поддерживают возможность отправки параметризованных запросов(подготовленные выражения). При этом параметры внешнего происхождения отправляются на сервер отдельно от самого запроса либо автоматически экранируются клиентской библиотекой. Для этого используются

  • на Delphi — свойство TQuery.Params;
Например
var
  sql, param : string;
begin
  sql := 'select :text as value from dual';
  param := 'alpha';  
  Query1.Sql.Text := sql;
  Query1.ParamByName('text').AsString := param;
  Query1.Open;
  ShowMessage(Query1['value']);  
end;

См. также

Напишите отзыв о статье "Внедрение SQL-кода"

Ссылки

  • [www.securitylab.ru/contest/212083.php SQL инъекция в MySQL сервере]
  • [www.ptsecurity.ru/download/PT-devteev-Advanced-SQL-Injection.pdf «SQL Injection от А до Я»]
  • [rdot.org/forum/showthread.php?t=503 MySQL3 Error Based SQL injection]
  • [rdot.org/forum/showthread.php?t=24 SQL-Injection в PostgreSQL]
  • [forum.k0d.cc/showthread.php?t=5170 SQL-Injection в различных БД и утилиты]
К:Википедия:Статьи без источников (тип: не указан)

Отрывок, характеризующий Внедрение SQL-кода

В первый раз, как молодое иностранное лицо позволило себе делать ей упреки, она, гордо подняв свою красивую голову и вполуоборот повернувшись к нему, твердо сказала:
– Voila l'egoisme et la cruaute des hommes! Je ne m'attendais pas a autre chose. Za femme se sacrifie pour vous, elle souffre, et voila sa recompense. Quel droit avez vous, Monseigneur, de me demander compte de mes amities, de mes affections? C'est un homme qui a ete plus qu'un pere pour moi. [Вот эгоизм и жестокость мужчин! Я ничего лучшего и не ожидала. Женщина приносит себя в жертву вам; она страдает, и вот ей награда. Ваше высочество, какое имеете вы право требовать от меня отчета в моих привязанностях и дружеских чувствах? Это человек, бывший для меня больше чем отцом.]
Лицо хотело что то сказать. Элен перебила его.
– Eh bien, oui, – сказала она, – peut etre qu'il a pour moi d'autres sentiments que ceux d'un pere, mais ce n'est; pas une raison pour que je lui ferme ma porte. Je ne suis pas un homme pour etre ingrate. Sachez, Monseigneur, pour tout ce qui a rapport a mes sentiments intimes, je ne rends compte qu'a Dieu et a ma conscience, [Ну да, может быть, чувства, которые он питает ко мне, не совсем отеческие; но ведь из за этого не следует же мне отказывать ему от моего дома. Я не мужчина, чтобы платить неблагодарностью. Да будет известно вашему высочеству, что в моих задушевных чувствах я отдаю отчет только богу и моей совести.] – кончила она, дотрогиваясь рукой до высоко поднявшейся красивой груди и взглядывая на небо.
– Mais ecoutez moi, au nom de Dieu. [Но выслушайте меня, ради бога.]
– Epousez moi, et je serai votre esclave. [Женитесь на мне, и я буду вашею рабою.]
– Mais c'est impossible. [Но это невозможно.]
– Vous ne daignez pas descende jusqu'a moi, vous… [Вы не удостаиваете снизойти до брака со мною, вы…] – заплакав, сказала Элен.
Лицо стало утешать ее; Элен же сквозь слезы говорила (как бы забывшись), что ничто не может мешать ей выйти замуж, что есть примеры (тогда еще мало было примеров, но она назвала Наполеона и других высоких особ), что она никогда не была женою своего мужа, что она была принесена в жертву.
– Но законы, религия… – уже сдаваясь, говорило лицо.
– Законы, религия… На что бы они были выдуманы, ежели бы они не могли сделать этого! – сказала Элен.
Важное лицо было удивлено тем, что такое простое рассуждение могло не приходить ему в голову, и обратилось за советом к святым братьям Общества Иисусова, с которыми оно находилось в близких отношениях.
Через несколько дней после этого, на одном из обворожительных праздников, который давала Элен на своей даче на Каменном острову, ей был представлен немолодой, с белыми как снег волосами и черными блестящими глазами, обворожительный m r de Jobert, un jesuite a robe courte, [г н Жобер, иезуит в коротком платье,] который долго в саду, при свете иллюминации и при звуках музыки, беседовал с Элен о любви к богу, к Христу, к сердцу божьей матери и об утешениях, доставляемых в этой и в будущей жизни единою истинною католическою религией. Элен была тронута, и несколько раз у нее и у m r Jobert в глазах стояли слезы и дрожал голос. Танец, на который кавалер пришел звать Элен, расстроил ее беседу с ее будущим directeur de conscience [блюстителем совести]; но на другой день m r de Jobert пришел один вечером к Элен и с того времени часто стал бывать у нее.
В один день он сводил графиню в католический храм, где она стала на колени перед алтарем, к которому она была подведена. Немолодой обворожительный француз положил ей на голову руки, и, как она сама потом рассказывала, она почувствовала что то вроде дуновения свежего ветра, которое сошло ей в душу. Ей объяснили, что это была la grace [благодать].
Потом ей привели аббата a robe longue [в длинном платье], он исповедовал ее и отпустил ей грехи ее. На другой день ей принесли ящик, в котором было причастие, и оставили ей на дому для употребления. После нескольких дней Элен, к удовольствию своему, узнала, что она теперь вступила в истинную католическую церковь и что на днях сам папа узнает о ней и пришлет ей какую то бумагу.
Все, что делалось за это время вокруг нее и с нею, все это внимание, обращенное на нее столькими умными людьми и выражающееся в таких приятных, утонченных формах, и голубиная чистота, в которой она теперь находилась (она носила все это время белые платья с белыми лентами), – все это доставляло ей удовольствие; но из за этого удовольствия она ни на минуту не упускала своей цели. И как всегда бывает, что в деле хитрости глупый человек проводит более умных, она, поняв, что цель всех этих слов и хлопот состояла преимущественно в том, чтобы, обратив ее в католичество, взять с нее денег в пользу иезуитских учреждений {о чем ей делали намеки), Элен, прежде чем давать деньги, настаивала на том, чтобы над нею произвели те различные операции, которые бы освободили ее от мужа. В ее понятиях значение всякой религии состояло только в том, чтобы при удовлетворении человеческих желаний соблюдать известные приличия. И с этою целью она в одной из своих бесед с духовником настоятельно потребовала от него ответа на вопрос о том, в какой мере ее брак связывает ее.
Они сидели в гостиной у окна. Были сумерки. Из окна пахло цветами. Элен была в белом платье, просвечивающем на плечах и груди. Аббат, хорошо откормленный, а пухлой, гладко бритой бородой, приятным крепким ртом и белыми руками, сложенными кротко на коленях, сидел близко к Элен и с тонкой улыбкой на губах, мирно – восхищенным ее красотою взглядом смотрел изредка на ее лицо и излагал свой взгляд на занимавший их вопрос. Элен беспокойно улыбалась, глядела на его вьющиеся волоса, гладко выбритые чернеющие полные щеки и всякую минуту ждала нового оборота разговора. Но аббат, хотя, очевидно, и наслаждаясь красотой и близостью своей собеседницы, был увлечен мастерством своего дела.
Ход рассуждения руководителя совести был следующий. В неведении значения того, что вы предпринимали, вы дали обет брачной верности человеку, который, с своей стороны, вступив в брак и не веря в религиозное значение брака, совершил кощунство. Брак этот не имел двоякого значения, которое должен он иметь. Но несмотря на то, обет ваш связывал вас. Вы отступили от него. Что вы совершили этим? Peche veniel или peche mortel? [Грех простительный или грех смертный?] Peche veniel, потому что вы без дурного умысла совершили поступок. Ежели вы теперь, с целью иметь детей, вступили бы в новый брак, то грех ваш мог бы быть прощен. Но вопрос опять распадается надвое: первое…
– Но я думаю, – сказала вдруг соскучившаяся Элен с своей обворожительной улыбкой, – что я, вступив в истинную религию, не могу быть связана тем, что наложила на меня ложная религия.
Directeur de conscience [Блюститель совести] был изумлен этим постановленным перед ним с такою простотою Колумбовым яйцом. Он восхищен был неожиданной быстротой успехов своей ученицы, но не мог отказаться от своего трудами умственными построенного здания аргументов.
– Entendons nous, comtesse, [Разберем дело, графиня,] – сказал он с улыбкой и стал опровергать рассуждения своей духовной дочери.


Элен понимала, что дело было очень просто и легко с духовной точки зрения, но что ее руководители делали затруднения только потому, что они опасались, каким образом светская власть посмотрит на это дело.
И вследствие этого Элен решила, что надо было в обществе подготовить это дело. Она вызвала ревность старика вельможи и сказала ему то же, что первому искателю, то есть поставила вопрос так, что единственное средство получить права на нее состояло в том, чтобы жениться на ней. Старое важное лицо первую минуту было так же поражено этим предложением выйти замуж от живого мужа, как и первое молодое лицо; но непоколебимая уверенность Элен в том, что это так же просто и естественно, как и выход девушки замуж, подействовала и на него. Ежели бы заметны были хоть малейшие признаки колебания, стыда или скрытности в самой Элен, то дело бы ее, несомненно, было проиграно; но не только не было этих признаков скрытности и стыда, но, напротив, она с простотой и добродушной наивностью рассказывала своим близким друзьям (а это был весь Петербург), что ей сделали предложение и принц и вельможа и что она любит обоих и боится огорчить того и другого.
По Петербургу мгновенно распространился слух не о том, что Элен хочет развестись с своим мужем (ежели бы распространился этот слух, очень многие восстали бы против такого незаконного намерения), но прямо распространился слух о том, что несчастная, интересная Элен находится в недоуменье о том, за кого из двух ей выйти замуж. Вопрос уже не состоял в том, в какой степени это возможно, а только в том, какая партия выгоднее и как двор посмотрит на это. Были действительно некоторые закоснелые люди, не умевшие подняться на высоту вопроса и видевшие в этом замысле поругание таинства брака; но таких было мало, и они молчали, большинство же интересовалось вопросами о счастии, которое постигло Элен, и какой выбор лучше. О том же, хорошо ли или дурно выходить от живого мужа замуж, не говорили, потому что вопрос этот, очевидно, был уже решенный для людей поумнее нас с вами (как говорили) и усомниться в правильности решения вопроса значило рисковать выказать свою глупость и неумение жить в свете.
Одна только Марья Дмитриевна Ахросимова, приезжавшая в это лето в Петербург для свидания с одним из своих сыновей, позволила себе прямо выразить свое, противное общественному, мнение. Встретив Элен на бале, Марья Дмитриевна остановила ее посередине залы и при общем молчании своим грубым голосом сказала ей:
– У вас тут от живого мужа замуж выходить стали. Ты, может, думаешь, что ты это новенькое выдумала? Упредили, матушка. Уж давно выдумано. Во всех…… так то делают. – И с этими словами Марья Дмитриевна с привычным грозным жестом, засучивая свои широкие рукава и строго оглядываясь, прошла через комнату.
На Марью Дмитриевну, хотя и боялись ее, смотрели в Петербурге как на шутиху и потому из слов, сказанных ею, заметили только грубое слово и шепотом повторяли его друг другу, предполагая, что в этом слове заключалась вся соль сказанного.
Князь Василий, последнее время особенно часто забывавший то, что он говорил, и повторявший по сотне раз одно и то же, говорил всякий раз, когда ему случалось видеть свою дочь.
– Helene, j'ai un mot a vous dire, – говорил он ей, отводя ее в сторону и дергая вниз за руку. – J'ai eu vent de certains projets relatifs a… Vous savez. Eh bien, ma chere enfant, vous savez que mon c?ur de pere se rejouit do vous savoir… Vous avez tant souffert… Mais, chere enfant… ne consultez que votre c?ur. C'est tout ce que je vous dis. [Элен, мне надо тебе кое что сказать. Я прослышал о некоторых видах касательно… ты знаешь. Ну так, милое дитя мое, ты знаешь, что сердце отца твоего радуется тому, что ты… Ты столько терпела… Но, милое дитя… Поступай, как велит тебе сердце. Вот весь мой совет.] – И, скрывая всегда одинаковое волнение, он прижимал свою щеку к щеке дочери и отходил.
Билибин, не утративший репутации умнейшего человека и бывший бескорыстным другом Элен, одним из тех друзей, которые бывают всегда у блестящих женщин, друзей мужчин, никогда не могущих перейти в роль влюбленных, Билибин однажды в petit comite [маленьком интимном кружке] высказал своему другу Элен взгляд свой на все это дело.
– Ecoutez, Bilibine (Элен таких друзей, как Билибин, всегда называла по фамилии), – и она дотронулась своей белой в кольцах рукой до рукава его фрака. – Dites moi comme vous diriez a une s?ur, que dois je faire? Lequel des deux? [Послушайте, Билибин: скажите мне, как бы сказали вы сестре, что мне делать? Которого из двух?]
Билибин собрал кожу над бровями и с улыбкой на губах задумался.
– Vous ne me prenez pas en расплох, vous savez, – сказал он. – Comme veritable ami j'ai pense et repense a votre affaire. Voyez vous. Si vous epousez le prince (это был молодой человек), – он загнул палец, – vous perdez pour toujours la chance d'epouser l'autre, et puis vous mecontentez la Cour. (Comme vous savez, il y a une espece de parente.) Mais si vous epousez le vieux comte, vous faites le bonheur de ses derniers jours, et puis comme veuve du grand… le prince ne fait plus de mesalliance en vous epousant, [Вы меня не захватите врасплох, вы знаете. Как истинный друг, я долго обдумывал ваше дело. Вот видите: если выйти за принца, то вы навсегда лишаетесь возможности быть женою другого, и вдобавок двор будет недоволен. (Вы знаете, ведь тут замешано родство.) А если выйти за старого графа, то вы составите счастие последних дней его, и потом… принцу уже не будет унизительно жениться на вдове вельможи.] – и Билибин распустил кожу.