На мой взгляд самый распространенный и самый опасный способ взлома базы данных - это SQL Injection - внедрение в обычные SQL-запросы, с которыми регулярно работает приложение, своих вредоносных запросов. Эта проблема происходит как правило когда данные, полученые от пользователя бездумно помещают в SQL запрос методом конкатенации (пример близкий по тексту тому что демонстрировал Сергей Байдачный на Dev Days):
Dim CommandText As String = "SELECT COUNT(*) FROM Users WHERE UserName='" + UserName.Text + "' AND Password='" + Password.Text + "'"
Dim Command As New SqlCommand(CommandText, Connection)
If CInt(Command.ExecuteScalar) = 1 Then
' Логин и пароль верны
Else
' Неверный логин или парль
End If
Очевидно что при вводе логина и пароля Brand/123 мы в результате конкатенации получим следующий запрос:
SELECT COUNT(*) FROM Users WHERE UserName='Brand' AND Password='123'
Тем не менее ввести в текстовые поля мы можем и другие данные, например в поле логина ввести Viktor' --, а в поле пароля к примеру тот же 123. Таким образом в БД у нас отправится запрос:
SELECT COUNT(*) FROM Users WHERE UserName='Viktor' --' AND Password='123'
Поскольку SQL Server считает все что идет после символов "--" коментарием, то мы фактически получаем возможность выполнить вход в систему от имени другого пользователя не зная его пароль.
Таким же методом можно отправить в БД 2 запроса, разделенных символом ";":
SELECT COUNT(*) FROM Users WHERE UserName='Viktor'; DROP TABLE Users --' AND Password='123'
Результат предсказуем - вся наша база пользователей будет уничтожена
.
Комбинируя различные варианты запросов можно даже потихоньку вытянуть из базы данных интерисующие нас данные, из совершенно любой таблицы - если интересно как это сделать, можешь поискать статьи по теме на ресурсах, посвященных безопасности - я видел неплохую статью на sequritylabs.
Избавиться от этого очень просто - можно во входных строках позаменять все символы одинарной кавычки на символ двойной кавычки - это сделает невозможным инъекцию. Но это мягко говоря совсем не решение проблемы - гораздо правильнее изначально не использовать конкатенацию, а использовать параметризированые запросы:
Dim CommandText As String = "SELECT COUNT(*) FROM Users WHERE UserName = @UserName AND Password = @Password"
Dim Command As New SqlCommand(CommandText, Connection)
Command.Parameters.Add("@UserName", SqlDbType.NVarChar, 256).Value = UserName.Text
Command.Parameters.Add("@Password", SqlDbType.NVarChar, 256).Value = Password.Text
If CInt(Command.ExecuteScalar) = 1 Then
' Логин и пароль верны
Else
' Неверный логин или парль
End If
Во-первых, в этот запрос уже в принципе невозможно пробиться через SQL Injection, во-вторых, такие запросы будут выполняться быстрее (я, правда, не уверен что разница будет сколько-нибудь ощутимой, но все равно приятно). Также это упрощает работу с рядом типом данных, которые методом конкатенации не совсем просто отправить в БД (даты, бинарные данные, GUID'ы) - в случае же параметризированых запросов все очень просто - у каждого параметра указывается тип и значение, остальное берут на себя классы SqlClient и SQL Server.
На сегодняшний день, если приходится работать с базами данных, то я бы рекомендовал использовать только параметризированые запросы.
Как видите, защититься от SQL-инъекций совсем несложно, у "правильных" разрабочтиков эта защита есть по умолчанию. Тем не менее интернет просто кишит сайтами с SQLI-дырками 
На самом деле данный пример имеет еще одну проблему, о которой Сергей (наверняка из-за отсутствия времени) не упомянул - в нашей таблице пароль - эта строка, а SQL Server сравнивает строки без учета регистра, поэтому мы сможем зайти в базу с паролем "hello world", "Hello WORLD" и "HeLlO WoRlD" - для проверки я выполняю приведение данных к бинарному типу (этот метод я подсмотрел в одной из статей MSDN):
SELECT COUNT(*) FROM Users WHERE UserName = @UserName AND CONVERT(varbinary, Password)=CONVERT(varbinary, @Password)
Еще более правильно - хранить пароль в зашифрованом виде или только хэш пароля (оба эти метода, наряду с хранением пароля в открытом виде поддерживаются в инфраструктуре Membership ASP .NET 2.0) - даже если кто-то пробьется в базу данных, ничего интересного он там не найдет.
Если SQL Injection скорее можно отнести к атакам "извне", и ликвидируется он программно, то наряду с ними атаковать могут и свои люди, такие атаки нужно блокировать уже средствами безопасности сервера баз данных.
Например, если у сервера баз данных, или даже у одной базы данных много пользователей, то рано или поздно возникает необходимость ограничить некоторые данные от любопытных глаз. К примеру списки партнеров/клиентов, истории финансовых операций и т.п. - в этом случае необходимо распределение уровней доступа к различным объектам для различных пользователей. Классически рекомендуется выдавать пользователям минимум привелегий, разделять доступ на уровнях баз данных и таблиц.
Очень хорошей практикой считается ограничение пользователям доступа к таблицам, вместо этого - предоставление им хранимых процедур - таким образом гораздо проще управлять уровнями полномочий которые имеют пользователи.
К сожалению уровень моих знаний и опыт не позволяет более подробно рассмотреть эту тему, так как с базами данных такого уровня я пока не имел дела.
Разумеется, к вопросам защиты сервер баз данных можно применить и некоторые советы, применимые вообще к защите серверов и информационных систем - испольозвать надежные пароли, периодически их менять, мониторировать попытки неавторизованого доступа по протоколам сервера. Также стоит переименовать, удалить или заблокировать стандартную учетную запись sa, а также установить на нее надежный пароль - возможны попытки бутфорса пароля.
К примеру у меня на сервере уже месяцев 6 круглосуточно с разных IP ломятся по логинам sa, admin и root (???), увы логин sa заблокирован, а admin и root вообще не существуют 
Также хотелось обратить внимание еще на одну уязвимость - она не имеет прямого отношения к безопасности самого сервера баз данных, тем не менее предоставляет для него большую угрозу. Эта проблема в большей степени относится к так называемым shared-хостингам, когда на одной Windwos-машине держат несколько сотен сайтов.
Как организовывается их хранение и работа?
В каталоге, скажем, d:\Home\ для каждого сайта создается отдельная директория, в IIS для него создается веб-узел, ссылающийся на эту директорию, для узла указывают host headers, соответствующий доменам этого сайта. FTP-доступ организовывается не встроеным в IIS FTP-сервером, а каким-то сторонним, в учетной системе этого 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, но если честно я не уверен что это может как-то помочь - в любом случае где-то нужно хранить ключ которым эти данные расшифровываются - его злоумышленник сможет легко достать аналогичным образом.
Вот, прошу прощения что так много написал и заранее приношу извинения за возможные неточности и заблуждения с моей стороны.
Artyom Krivokrisenko
Web Reflection, Development Department