tag:blogger.com,1999:blog-84029924931348077012024-03-13T07:35:48.329-07:00Вокруг Delphi и SQLПро Delphi и SQL, про сказочную жизнь вокруг, и решения практических задач.Anonymoushttp://www.blogger.com/profile/16850789349107365825noreply@blogger.comBlogger3125tag:blogger.com,1999:blog-8402992493134807701.post-13466832557341945112014-10-16T23:28:00.001-07:002014-10-16T23:29:09.206-07:00Коротко. Баг в BCP.<div dir="ltr" style="text-align: left;" trbidi="on">
Вкратце, утилита BCP версии 11.0.2100.60, устанавливаемая вместе с SQL Server 2012, при экспорте из базы данных в файл, и использовании форматного файла, выполняет запрос к данным ДВАЖДЫ, что может привести к неожиданным результатам, если запрос производит сторонние действия. Подробности и способ воспроизведения бага <a href="http://www.sql.ru/forum/1119049/dvoynoy-vyzov-procedury-iz-bcp-s-formatnym-faylom">в моей теме на форуме</a>.</div>
Anonymoushttp://www.blogger.com/profile/16850789349107365825noreply@blogger.com0tag:blogger.com,1999:blog-8402992493134807701.post-49508843802519049672014-09-25T01:54:00.000-07:002014-09-25T01:57:34.148-07:00Брутфорсы и SQL<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
</div>
<h3 style="text-align: left;">
Предыстория.</h3>
Так случилось, что бизнесу потребовалось вывести базу данных со своей территории. Спрятать её, исключить физический и информационный доступ всем потенциально заинтересованным лицам, и при этом сохранить возможность полноценно, (и совершенно секретно), работать с ней из центрального офиса.<br />Требование есть требование. Раз оно поставлено, нужно его выполнить.<br />Оборотистые наши админы нашли и арендовали забугорный хостинг с SQL Server, настроили подключение к нему через интернет, развернули свежую архивную копию, и... отдали базу в распоряжение программиста, (пишущего эти строки).<br />Нужно заметить, что и сама база, и самописная клиентская часть, (на Delphi), за свою толи 15-ти, толи 20-летнюю историю пережила несколько поколений поддерживающих и развивающих её программистов, разного уровня квалификации, и различных взглядов на философию программирования. Стоит ли удивляться, что немалая часть функциональности программы, написанной в предположении, что база данных всегда располагается в локальной сети, после переезда за границу конторы стала тормозить, и местами просто безбожно. Загрузка двухсотстрочного документа в таблицу, перемежаемая уточняющими запросами к базе по каждой строке, из 15-секундной операции превратилась в 2-минутную. Впрочем, мой рассказ сегодня не об этом, (как следует из заголовка).<br />Казалось бы, задача, поставленная руководством, была решена. База "жила", пользователи "пользовались". Однако, выполнение требования полностью спрятать информацию и факт её существования от чужих глаз, вдруг оказалось под угрозой...<br /><br /><br />
<div style="text-align: left;">
</div>
<h3 style="text-align: left;">
Появление проблемы.</h3>
Спустя некоторое время после переезда базы, просматривая журнал ошибок SQL Server, я обнаружил подозрительные записи о неуспешных подключениях. Подозрительными они казались потому, что следовали друг за другом, с периодом в секунду или чаще.<br />
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-2cjfYBhin8Q/VCPXWbV4bAI/AAAAAAAAACQ/9uEJ1E4D-cs/s1600/ErrorLog3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-2cjfYBhin8Q/VCPXWbV4bAI/AAAAAAAAACQ/9uEJ1E4D-cs/s1600/ErrorLog3.jpg" height="257" width="640" /></a></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Небольшое расследование прояснило, что IP-адреса, упоминаемые в поле Message, не принадлежали нашему офису, и были разбросаны по всему миру. Большая часть находилась в Азии, некоторые в Канаде, России, США... География и периодичность запросов навели на страшную догадку: мы стали жертвой хакерских атак! К нашему SQL Server-у пытаются подобрать пароль! И мы, как оказалось, не могли этому воспрепятствовать. Всезнающие наши админы заявили, что, в принципе, запретить все IP-адреса, кроме нескольких "легальных", возможно, при этом, не перекрывая обычный HTTP-траффик, (он был нужен для работы), но, как это реализовать практически, "они сейчас не знают". Так и возникла передо мной задача, как сервер от брутфорсов защитить.</div>
<div style="text-align: left;">
<br /></div>
<h3 style="text-align: left;">
Решение - часть 1.</h3>
Я не админ, обычный программист. Правильные методы решения админских задач мне неизвестны, и потому описывать я буду то решение, которое придумал сам. Всё, что мне пришло тогда в голову, можно вкратце описать алгоритмом:<br />1. Каким-то образом своевременно получать уведомления о начале хакерской атаки, с указанием вредоносного IP-адреса.<br />2. И совершенно неизвестным пока способом блокировать этот адрес на сервере, где установлен SQL.<br />С решения первого вопроса и начнём. Единственным доступным мне источником входящей информации, (о неудачных логонах), оказался сам журнал ошибок SQL Server. Достаточно было его просто прочитать, и выделить нужные строки. Мне повезло: в арсенале предусмотрительной Microsoft нашлась недокументированная процедура <b>xp_readerrorlog</b> для чтения журнала, а в интернетах - достаточно полное описание её синтаксиса и параметров. Процедура возвращает содержимое журнала в виде набора данных из трёх полей, отфильтрованного по дате-времени и тексту ошибки. Так удалось воспроизвести историю неудачных логонов, с точностью до десятых долей секунды.<br />
<div style="text-align: left;">
<br /><span style="background-color: cyan;">exec xp_readerrorlog 0, 1, 'Login failed for user', 'provided'</span></div>
<div style="text-align: left;">
<a href="http://4.bp.blogspot.com/-cAzWjoXahoY/VCPVRpXnJeI/AAAAAAAAAB4/0mCMQptUm-4/s1600/ErrorLog1.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-cAzWjoXahoY/VCPVRpXnJeI/AAAAAAAAAB4/0mCMQptUm-4/s1600/ErrorLog1.jpg" height="199" width="640" /></a><br /> После некоторых преобразований, нетрудно получить табличку вида [Время], [IP].</div>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-bmiCnB6Auhc/VCPWjI92GwI/AAAAAAAAACA/tmb3WbujvWI/s1600/ErrorLog2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-bmiCnB6Auhc/VCPWjI92GwI/AAAAAAAAACA/tmb3WbujvWI/s1600/ErrorLog2.jpg" /></a></div>
<div style="text-align: left;">
<br />Всё, что осталось сделать - решить, какие IP-адреса из этого списка являются "зловредными". Идею, на качественном уровне, можно выразить так: нежелательным считается такой IP-адрес, который: а) довольно часто, и б) в больших количествах появляется в указанном списке. Было придумано несколько эвристических правил, опирающихся как на разницу во времени между "соседними" событиями с одним и тем же IP-адресом, так и на количество таких событий в определённые интервалы времени. В процессе экспериментов были подобраны числовые параметры для упомянутой эвристики, и реализован SQL-запрос, возвращающий хакерские IP-адреса. Создав несложный джоб в службе SQL Server Agent, раз в несколько минут проверявший журнал ошибок, я стал регулярно получать на почту списки хакерских IP-адресов. Таким образом, первую часть задачи можно было считать решённой.</div>
<br />
<h3>
Решение - часть 2.</h3>
<div style="text-align: left;">
А вот со второй частью задачи, ограничением сетевого трафика по списку IP-адресов, пришлось повозиться. Помимо того, что она относилась к малоизвестной мне области - администрированию Windows, оказалось, что почти нигде в интернетах не присутствует описания программных способов это реализовать. Большинство "руководств" рассказывало, какие кнопки в каком файрволе нужно жать, чтобы получить требуемый эффект.<br />Для начала, удалось обнаружить, что в составе ОС Windows есть инструментарий "Политики IP-безопасности", имеющий графический интерфейс, и позволяющий блокировать сетевой трафик для списков IP-адресов, в чём я не преминул убедиться собственноручно.<br /> </div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-O32Caq9zZKU/VCPX9H2xo2I/AAAAAAAAACc/cgg6Rf3PZg8/s1600/ipsec1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-O32Caq9zZKU/VCPX9H2xo2I/AAAAAAAAACc/cgg6Rf3PZg8/s1600/ipsec1.png" height="333" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: left;">
Убедившись в этом, я стал искать способ делать то же самое программно, без непосредственного участия пользователя. Как я рассуждал: "Если есть одна программа, которая что-то делает, значит можно написать другую программу, которая будет делать тоже самое, используя те же внутренние механизмы, что и первая. И, вероятнее всего, эти механизмы присутствуют в WinAPI". </div>
<div style="text-align: left;">
Как же я ошибся! Такого WinAPI нет. Вообще. Совсем. Осторожная Microsoft не создала такого API, (либо не опубликовала).<br />И всё, что у нас есть - это утилита командной строки netsh.exe, работающая в контексте ipsec, (Прим.: в новых версиях Windows рекомендуется использовать контекст advfirewall). Достаточно программно создать этот процесс с нужными параметрами в строке запуска, и он внесёт необходимые изменения в политику безопасности сервера. Что я и реализовал в программе-роботе, периодически проверяющем журнал ошибок SQL Server на предмет появления хакерских атак, и в случае нахождения таковых, добавляющем вредные IP-адреса к блокирующему фильтру политики безопасности сервера.</div>
</div>
Anonymoushttp://www.blogger.com/profile/16850789349107365825noreply@blogger.com0tag:blogger.com,1999:blog-8402992493134807701.post-34353666088101866252014-09-23T23:29:00.000-07:002014-09-24T01:16:54.030-07:00"В потоке" (лирично)<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Во взгляде - смысл, моноширинно-чистый,</i></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Наушники - глотатели шумов.</i></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Не отвлекайте тленом программиста,</i></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>В плену абстракций, в символизме слов.</i></span><br />
<span style="font-size: large;"><span style="font-family: Trebuchet MS, sans-serif;"><i><br /></i></span>
<span style="font-family: Trebuchet MS, sans-serif;"><i>"Стратегия", "Команда", "Одиночка", -</i></span></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Построились паттерны по струне.</i></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Архитектура точно будет прочной,</i></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Изящной, расширяемой вполне.</i></span><br />
<span style="font-size: large;"><span style="font-family: Trebuchet MS, sans-serif;"><i><br /></i></span>
<span style="font-family: Trebuchet MS, sans-serif;"><i>Неоднозначно. Имя переменной - </i></span></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Метафора, значение и суть.</i></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>К двоично-однобитовой вселенной</i></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Как третье состояние примкнуть?</i></span><br />
<span style="font-size: large;"><span style="font-family: Trebuchet MS, sans-serif;"><i><br /></i></span>
<span style="font-family: Trebuchet MS, sans-serif;"><i>Begin и end - четверостиший скобки,</i></span></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Ступени отступов, перила try-except,</i></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Константы, расположенные в стопку,</i></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Использует дженериков адепт.</i></span><br />
<span style="font-size: large;"><span style="font-family: Trebuchet MS, sans-serif;"><i><br /></i></span>
<span style="font-family: Trebuchet MS, sans-serif;"><i>Спешат минуты, незаметно-быстро,</i></span></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Сверкает мысль в императиве строк.</i></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Не отвлекайте чушью программиста,</i></span><br />
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;"><i>Не прерывайте творческий поток.</i></span><br />
<div>
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/16850789349107365825noreply@blogger.com0