Проект Web Reflectionобъявляет
конкурс на несколько должностей.
Первая категория: разработчики ASP .NET, имеющие опыт разработки более-менее
серьезных приложений. Работа удаленная, т.е. вы можете находиться где угодно,
в любом городе и любой стране. Оплата сдельная (оплачивается полностью
разработка проекта). Проекты, которые мы разрабатываем – в основном системы по
автоматизации бизнеса, а также решения в области электронной коммерции.
Требований к образованию, официальному
трудовому стажу и т.п. нет. Необходим опыт разработки на ASP .NET (на C# или VB), SQL Server. Не помешают знания в области
проектирования архитектуры ПО.
Вторая категория: разработчики ASP .NET, возможно с малым опытом разработки, но
желанием учиться. Сейчас у нас в разработке большой проект (типовое решение мультиязычного
информационного портала с более 20-ти разделов), вы сможете получить реальный
опыт работы в команде и разработки крупных сайтов. Работа в процессе разработки
оплачиваться не будет, но вы сможете повысить свою квалификацию, работая
бок-о-бок с нашими специалистами, а также получить вознаграждение после
окончания проекта.
По всем вопросам пишите на cdm@webreflection.ruили на ICQ: 326066673
. Для профессиональных разработчиков желательно указать в письме список ранее
реализованных на ASP .NET проектов, а
также примерную стоимость вашего труда в расчете на час работы и сколько вы
можете времени в неделю выделять на работу с нами. Для тех, кто заинтересовался
разработкой портала, также неплохо указать информацию о выполненных проектах,
чтобы я мог иметь представление о вашей квалификации, и сколько вы времени в
неделю можете выделять на разработку.
Защита БД
Создавая приложения, работающие с базами
данных, ни в коем случае нельзя забывать о безопасности. Дыры, оставленные в
безопасности кода, работающего с БД, могут дорого стоить. Представьте, что
будет, если злоумышленник оформит в интернет-магазине заказ, не заплатив ни
копейки? Или удалит документы из системы электронного документооборота фирмы? Вероятность
взлома можно существенно снизить, если при разработке ПО учитывать требования к
безопасности, и помнить несколько нехитрых правил.
На мой взгляд самый распространенный и самый
опасный способ взлома базы данных - это SQL Injection -
внедрение в обычные SQL-запросы, с которыми регулярно
работает приложение, своих вредоносных запросов. Эта проблема происходит как
правило когда данные, полученые от пользователя бездумно помещают в SQL запрос методом конкатенации (пример близкий по тексту тому что
демонстрировал Сергей Байдачный на Dev Days):
Dim CommandText AsString="SELECT
COUNT(*) FROM Users WHERE UserName='"+ UserName.Text +"'
AND Password='"+ Password.Text +"'" DimCommandAsNew SqlCommand(CommandText,
Connection)
IfCInt(Command.ExecuteScalar) = 1 Then ' Логин
и пароль верны Else '
Неверный логин или парль EndIf
Очевидно что при вводе логина и пароля Brand/123 мы в результате конкатенации получим следующий запрос:
SELECTCOUNT(*) FROM Users WHERE UserName='Brand'AND Password='123'
Тем не менее ввести в
текстовые поля мы можем и другие данные, например в поле логина ввести Viktor' --, а в поле пароляк примеру тот же 123. Таким образом в БД у нас отправится запрос:
SELECTCOUNT(*) FROM Users WHERE UserName='Viktor'--' AND Password='123'
Поскольку SQLServer считает все
что идет после символов "--" коментарием, то мы фактически получаем
возможность выполнить вход в систему от имени другого пользователя не зная его
пароль.
Таким же методом можно
отправить в БД 2 запроса, разделенных символом ";":
SELECTCOUNT(*) FROM Users WHERE UserName='Viktor'; DROPTABLE Users --' AND Password='123'
Результат предсказуем -
вся наша база пользователей будет уничтожена.
Комбинируя различные
варианты запросов можно даже потихоньку вытянуть из базы данных интерисующие
нас данные, из совершенно любой таблицы - если интересно как это сделать,
можешь поискать статьи по теме на ресурсах, посвященных безопасности - я видел
неплохую статью на sequritylabs.
Избавиться от этого очень
просто - можно во входных строках позаменять все символы одинарной кавычки на
символ двойной кавычки - это сделает невозможным инъекцию. Но это мягко говоря
совсем не решение проблемы - гораздо правильнее изначально не использовать
конкатенацию, а использовать параметризированые запросы:
Dim CommandText AsString="SELECT
COUNT(*) FROM Users WHERE UserName = @UserName AND Password =
Password" DimCommandAsNew SqlCommand(CommandText,
Connection) Command.Parameters.Add("@UserName", SqlDbType.NVarChar,
256).Value = UserName.Text Command.Parameters.Add("@Password", SqlDbType.NVarChar,
256).Value = Password.Text
IfCInt(Command.ExecuteScalar) = 1 Then ' Логин
и пароль верны Else '
Неверный логин или парль EndIf
Во-первых, в этот запрос
уже в принципе невозможно пробиться через SQLInjection, во-вторых, такие запросы будут выполняться
быстрее (я, правда, не уверен что разница будет сколько-нибудь ощутимой, но все
равно приятно). Также это упрощает работу с рядом типом данных, которые методом
конкатенации не совсем просто отправить в БД (даты, бинарные данные, GUID'ы) - в случае
же параметризированых запросов все очень просто - у каждого параметра
указывается тип и значение, остальное берут на себя классы SqlClient и SQLServer.
На сегодняшний день, если
приходится работать с базами данных, то я бы рекомендовал использовать только
параметризированые запросы.
Как видите, защититься от SQL-инъекций
совсем несложно, у "правильных" разрабочтиков эта защита есть по
умолчанию. Тем не менее интернет просто кишит сайтами с SQLI-дырками :)
На самом деле данный
пример имеет еще одну проблему, о которой Сергей (наверняка из-за отсутствия
времени) не упомянул - в нашей таблице пароль - эта строка, а SQLServer сравнивает
строки без учета регистра, поэтому мы сможем зайти в базу с паролем "helloworld",
"HelloWORLD" и
"HeLlOWoRlD" - для
проверки я выполняю приведение данных к бинарному типу (этот метод я подсмотрел
в одной из статей MSDN):
SELECTCOUNT(*) FROM Users WHERE UserName = @UserName
ANDCONVERT(varbinary, Password)=CONVERT(varbinary, @Password)
Еще более правильно -
хранить пароль в зашифрованом виде или только хэш пароля (оба эти метода, наряду
с хранением пароля в открытом виде поддерживаются в инфраструктуре MembershipASP .NET 2.0) - даже
если кто-то пробьется в базу данных, ничего интересного он там не найдет.
Если SQLInjection скорее
можно отнести к атакам "извне", и ликвидируется он программно,то наряду с
ними атаковать могут и свои люди, такие атаки нужно блокировать уже средствами
безопасности сервера баз данных.
Например, если у сервера
баз данных, или даже у одной базы данных много пользователей, то рано или
поздно возникает необходимость ограничить некоторые данные от любопытных глаз.
К примеру списки партнеров/клиентов, истории финансовых операций и т.п. - в
этом случае необходимо распределение уровней доступа к различным объектам для
различных пользователей. Классически рекомендуется выдавать пользователям
минимум привелегий, разделять доступ на уровнях баз данных и таблиц.
Очень хорошей практикой
считается ограничение пользователям доступа к таблицам, вместо этого -
предоставление им хранимых процедур - таким образом гораздо проще управлять
уровнями полномочий которые имеют пользователи.
Ксожалению
уровень моих знаний и опыт не позволяет более подробно рассмотреть эту тему,
так как с базами данных такого уровня я пока не имел дела.
Разумеется, к вопросам
защиты сервер баз данных можно применить и некоторые советы, применимые вообще
к защите серверов и информационных систем - испольозвать надежные пароли,
периодически их менять, мониторировать попытки неавторизованого доступа по
протоколам сервера. Также стоит переименовать, удалить или заблокировать
стандартную учетную запись sa, а также установить на нее надежный пароль -
возможны попытки бутфорса пароля.
К примеру у меня на
сервере уже месяцев 6 круглосуточно с разных IP ломятся по логинам sa, admin и root (???), увы логин sa заблокирован, а admin и root вообще не существуют!
Также хотелось обратить
внимание еще на одну уязвимость - она не имеет прямого отношения к безопасности
самого сервера баз данных, тем не менее предоставляет для него большую угрозу.
Эта проблема в большей степени относится к так называемым shared-хостингам,
когда на одной Windwos-машине держат несколько сотен сайтов.
Как организовывается их
хранение и работа?
В каталоге, скажем, d:\Home\ для каждого
сайта создается отдельная директория, в IIS для него создается веб-узел, ссылающийся на эту
директорию, для узла указывают hostheaders, соответствующий доменам этого сайта. FTP-доступ
организовывается не встроеным в IISFTP-сервером, а каким-то сторонним, в учетной системе этого FTP-сервера для
каждого клиента заводится логин/парль и он ассоциируется с соответствующей
директорией в d:\Home\. Разумеется каждый пользователь может обратиться
только к своей директории, в чужие его FTP не пустит.
Но теперь посмотрим что происходит в IIS - все веб-сайты настроены на запуск в контексте NETWORK SERVICE. Это удобно по той причине, что все веб-сайты можно будет запустить в
одном (или нескольких) пулах, и для этого потребуется меньше ресурсов чем на
запуск каждого веб-сайта в контексте отдельного Windows-акаунта
и соответственно отдельного пула.
Но поскольку все сайты выполняются под NETWORK
SERVICE, то для этого акаунта открыт полный доступ ко всей
директории d:\Home\ (иногда как на
чтение, так и на запись!). Но поскольку код моего веб-сайта выполняется под NETWORK
SERVICE, а NETWORK SERVICE имеет
неограниченый доступ к директории d:\Home\, то я могу обратиться к файловой системе и фактически получить
неограниченый доступ к содержимому всей директории - включая директории всех
сайтов, которые находятся на этом сервере. Таким образом я могу без проблем
получить на руки исходные коды, какие-то документы, не предназначеные для чужих
глах, разумеется, к конфигурационным файлам, в которых у нас хранятся логин и
пароль от базы данных , причем как правило логин - это db_owner, также может храниться логин/пароль от SMTP. Не исключе кстати, что NETWORK SERVICE сможет
безпрепятственно пройти на системный диск, и даже записать/перезаписать/удалить
на нем что-нибудь.Последствия от таких
"путешествий" по файловой системе могут быть катастрофическими для
клиентов хостинг-провайдера и для самого хостинг-провайдера.
Выход из ситуации, который мне кажется
оптимальным - это не идти к таким хостинг-провайдерам, это касается очень
дешевых тарифных планов. Для безопасной работы нескольких сайтов параллельно
для каждого клиента нужно завести отдельный Windows-акаунт,
настроить ACL таким образом, чтоб каждый клиент имел
доступ только к своей директории, настроить работу веб-узлов таким образом,
чтоб каждый выполнялся от имени Windows-акаунта, которому
он принадлежит.
Также я видел советы шифровать пароли в web.config, но если честно я не уверен что это может
как-то помочь - в любом случае где-то нужно хранить ключ которым эти данные
расшифровываются - его злоумышленник сможет легко достать аналогичным образом.
Вот, прошу прощения что так много написал и
заранее приношу извинения за возможные неточности и заблуждения с моей стороны.
Спасибо Артему за подробный рассказ. Могу внести
лишь одно дополнение. Артем говорит, что «Таким же
методом можно отправить в БД 2 запроса, разделенных символом ";"».
Так вот, прочитав это вы можете решить, что нужно фильтровать в запросе символ “;”,
и тогда всё будет в порядке. Ничего подобного! Символ “;” не является
обязательным, и если его убрать, то все равно оба запроса (свой и вражеский)
будут выполнены.
Вообще иногда можно видеть как для защиты от SQLI
предлагают фильтровать некоторые ключевые слова в запросе (тот же
DROP, TRUNCATE, DELETE и др.). Это может немного помочь, но лишь немного. И, с другой стороны,
может посчитать вредоносным и самый безобидный запрос. Такие меры не смогут
обеспечить 100-процентную защиту.
И еще один момент. Можно предположить, что с
помощью SQLI злоумышленник сможет навредить только базе
данных. Если вы тоже так считаете, то вы плохо знакомы с SQL Server. Это достаточно мощная система, и она может многое, в т.ч.с помощью T-SQL можно получить доступ к файловой системе. И,
насколько я помню, даже можно выключить сервер. Если конечно у пользователя, в
контексте которого выполняет запросы злоумышленник, есть права на это.
Ну и в завершение рекомендую приобрести и
прочесть книгу «Защищенный код». Замечательная книга, одна из немногих, которые
всегда лежат у меня на столе (наряду с «Архитектурой корпоративных программных
приложений» Мартина Фаулера и некоторых других). Must read для всех разработчиков без исключения!