Майкл Ховард и Кит Браун
В этой статье предполагается, что вы знакомы с C++, C# и SQL.
Резюме: Когда дело доходит до проблем безопасности, существует множество ситуаций, которые могут привести к проблемам. Вероятно, вы доверяете всему коду, выполняющемуся в вашей сети, предоставляете всем пользователям доступ к важным файлам и никогда не удосужились проверить, не изменился ли код на ваших машинах. У вас также может не быть установлено антивирусное программное обеспечение, вы не можете защитить свой собственный код и предоставить слишком большому количеству учетных записей слишком много разрешений. Вы можете даже неосторожно использовать ряд встроенных функций, допускающих злонамеренные вторжения, и можете оставить порты сервера открытыми без какого-либо контроля. Разумеется, мы можем привести еще много примеров. Каковы действительно важные проблемы (т. е. наиболее опасные ошибки, на которые следует обратить немедленное внимание, чтобы не поставить под угрозу ваши данные и системы)? Эксперты по безопасности Майкл Ховард и Кейт Браун предлагают вам десять советов.
-------------------------------------------------- ----------------------------------
Вопросы безопасности включают в себя множество аспектов. Угрозы безопасности могут прийти откуда угодно. Возможно, вы написали неэффективный код обработки ошибок или слишком щедро предоставили разрешения. Возможно, вы забыли, какие службы работают на вашем сервере. Вы можете принять все вводимые пользователем данные. И так далее. Чтобы дать вам преимущество в защите вашего компьютера, сети и кода, вот десять советов, которым вы можете следовать, чтобы разработать более безопасную сетевую стратегию.
1. Доверие к пользовательским данным подвергает вас риску.
Даже если вы не читаете остальное, помните следующее: «Не доверяйте пользовательским данным». Проблема возникает, если вы всегда предполагаете, что данные действительны и не являются вредоносными. Большинство уязвимостей безопасности связаны с передачей злоумышленниками вредоносно записанных данных на серверы.
Доверие к правильности ввода может привести к переполнению буфера, атакам с использованием межсайтовых сценариев, атакам с вставкой кода SQL и многому другому.
Давайте обсудим эти потенциальные векторы атак подробно.
2. Предотвратите переполнение буфера.
Когда злоумышленник предоставляет длину данных, превышающую ожидаемую приложением, происходит переполнение буфера, и данные переполняются во внутреннюю память. Переполнение буфера — это, прежде всего, проблема C/C++. Они представляют угрозу, но обычно их легко исправить. Мы видели только два переполнения буфера, которые не были очевидны и которые трудно исправить. Разработчик не ожидал, что предоставленные извне данные будут больше, чем внутренний буфер. Переполнение приводит к повреждению других структур данных в памяти, что часто используется злоумышленниками для запуска вредоносного кода. Ошибки индекса массива также могут вызывать опустошение и переполнение буфера, но это случается реже.
Взгляните на следующий фрагмент кода C++:
void DoSomething(char *cBuffSrc, DWORD cbBuffSrc) {
символ cBuffDest[32];
memcpy(cBuffDest, cBuffSrc, cbBuffSrc);
}
В чем проблема? На самом деле в этом коде нет ничего плохого, если cBuffSrc и cbBuffSrc взяты из надежного источника (например, кода, который не доверяет данным и поэтому проверяет их достоверность и размер). Однако если данные получены из ненадежного источника и не были проверены, злоумышленник (ненадежный источник) может легко сделать cBuffSrc больше, чем cBuffDest, а также установить cbBuffSrc больше, чем cBuffDest. Когда memcpy копирует данные в cBuffDest, адрес возврата из DoSomething изменяется, а поскольку cBuffDest находится рядом с адресом возврата в кадре стека функции, злоумышленник может выполнить некоторые вредоносные операции через код.
Способ компенсации — не доверять вводу пользователя и не доверять никаким данным, содержащимся в cBuffSrc и cbBuffSrc:
void DoSomething(char *cBuffSrc, DWORD cbBuffSrc) {
const DWORD cbBuffDest = 32;
символ cBuffDest[cbBuffDest];
#ifdef _DEBUG
memset (cBuffDest, 0x33, cbBuffSrc);
#endif
memcpy(cBuffDest, cBuffSrc, min(cbBuffDest, cbBuffSrc));
}
Эта функция демонстрирует три свойства правильно написанной функции, которые могут уменьшить переполнение буфера. Во-первых, он требует, чтобы вызывающая сторона предоставила длину буфера. Конечно, слепо доверять этому значению нельзя! Затем в отладочной сборке код определяет, достаточно ли велик буфер для хранения исходного буфера. В противном случае может возникнуть нарушение прав доступа и код может быть загружен в отладчик. При отладке вы удивитесь, сколько ошибок вы обнаружите. Наконец, что наиболее важно, вызовы memcpy являются защитными, поскольку они не копируют больше данных, чем может вместить целевой буфер.
В рамках программы Windows® Security Push в Microsoft мы создали список безопасных функций обработки строк для программистов на языке C. Вы можете найти их в Strsafe.h: Safer String Handling in C (англ.).
3. Предотвратите использование межсайтовых сценариев.
Атаки с использованием межсайтовых сценариев являются уникальной проблемой Интернета. Они могут нанести вред клиентским данным через скрытую уязвимость на одной веб-странице. Представьте себе последствия следующего фрагмента кода ASP.NET:
Сколько человек видели подобный код? Но на удивление у него есть проблемы! Обычно пользователи получают доступ к этому коду, используя URL-адрес, аналогичный следующему:
http://explorationair.com/welcome.aspx?name=Michael
Код C# предполагает, что данные всегда действительны и содержат только имя. Однако злоумышленник может злоупотребить этим кодом, указав в качестве имен сценарий и HTML-код. Если вы введете следующий URL-адрес
http://northwindtraders.com/welcome.aspx?name=
Вы получите веб-страницу с диалоговым окном с надписью «Привет!» Вы можете спросить: «Ну и что?» Представьте, что злоумышленник может обманом заставить пользователя щелкнуть такую ссылку, но строка запроса содержит действительно опасный скрипт и HTML, тем самым получив файл cookie пользователя и отправив его на веб-сайт, принадлежащий злоумышленник теперь имеет доступ к вашей личной информации о файлах cookie или того хуже;
Чтобы избежать этого, есть два способа. Первый — не доверять вводимым данным и строго ограничивать содержание имени пользователя. Например, вы можете использовать регулярные выражения, чтобы проверить, что имя содержит только общий подмножество символов и не слишком велико. Следующий фрагмент кода C# показывает, как выполнить этот шаг:
Regex r = new Regex(@"^[w]{1,40}$");
if (r.Match(strName).Success) {
// хороший! Строка в порядке
} еще {
// не хорошо! Неверная строка
}
Этот код использует регулярные выражения для проверки того, что строка содержит от 1 до 40 букв или цифр. Это единственный безопасный способ определить правильность значения.
HTML или скрипт не смогут обмануть это регулярное выражение! Не используйте регулярные выражения для поиска недопустимых символов и отклоняйте запросы, если такие недопустимые символы обнаружены, поскольку можно что-то пропустить.
Вторая мера предосторожности — HTML-кодирование всех входных данных в качестве выходных. Это уменьшает количество опасных HTML-тегов до более безопасных escape-символов. Вы можете использовать HttpServerUtility.HtmlEncode в ASP.NET или Server.HTMLEncode в ASP, чтобы экранировать любые потенциально проблемные строки.
4. Не запрашивайте разрешения sa
Последняя атака с доверием к входным данным, которую мы обсудим, — это вставка кода SQL. Многие разработчики пишут код, который принимает входные данные и использует их для создания SQL-запросов, которые взаимодействуют с серверным хранилищем данных, например Microsoft® SQL Server™ или Oracle.
Взгляните на следующий фрагмент кода:
void DoQuery(string Id) {
SqlConnection sql=new SqlConnection(@"data source=localhost;" +
"идентификатор пользователя=sa;пароль=пароль;");
sql.Открыть();
sqlstring="SELECT отправлен" +
" ИЗ доставки ГДЕ id='" + Id + "'";
SqlCommand cmd = новый SqlCommand(sqlstring,sql);
•••
Этот код имеет три серьезных недостатка. Сначала он устанавливает соединение веб-службы с SQL Server под учетной записью системного администратора sa. Вскоре вы увидите подводные камни этого. Во-вторых, обратите внимание на разумную практику использования «пароля» в качестве пароля для учетной записи sa!
Но реальная проблема заключается в конкатенации строк, которая создает операторы SQL. Если пользователь вводит 1001 в качестве идентификатора, вы получаете следующий оператор SQL, который является полностью допустимым.
SELECT доставлен из FROM доставки WHERE id = '1001'
Но злоумышленники действуют гораздо более изобретательно. Они введут в качестве идентификатора «1001» DROP table Shipping --», что приведет к выполнению такого запроса:
ВЫБЕРИТЕ отправлено ИЗ
доставка ГДЕ id = '1001'
Доставка таблицы DROP -- ';
Это меняет способ работы запроса. Этот код не только пытается определить, было ли что-то отправлено, но также удаляет (удаляет) таблицу доставки! Оператор — это оператор комментария в SQL, который облегчает злоумышленникам создание серии допустимых, но опасных операторов SQL!
В настоящее время вы можете задаться вопросом, как любой пользователь может удалить таблицу в базе данных SQL Server. Конечно вы правы, такую работу могут выполнить только администраторы. Но здесь вы подключаетесь к базе данных как sa, а sa может делать с базой данных SQL Server все, что захочет. Никогда не подключайтесь к SQL Server как sa из какого-либо приложения; правильный подход — использовать встроенную проверку подлинности Windows, если это необходимо, или подключаться как предопределенную учетную запись с соответствующими разрешениями.
Исправить проблемы с кодом вставки SQL легко. Используя хранимые процедуры и параметры SQL, следующий код показывает, как создать такой запрос и как использовать регулярные выражения для подтверждения правильности входных данных, поскольку наша транзакция указывает, что идентификатор доставки может состоять только из 4–10 цифр:
Regex r = new Regex(@"^d{4,10}$");
если (!r.Match(Id).Успех)
выдать новое исключение («Неверный идентификатор»
SqlConnection sqlConn = new SqlConnection (strConn);
string str="sp_HasShipped";
SqlCommand cmd = новый SqlCommand(str,sqlConn);
cmd.ТипКоманды = ТипКоманды.СохраненнаяПроцедура;
cmd.Parameters.Add("@ID",Id);
Переполнение буфера, межсайтовый скриптинг и атаки с использованием кода SQL — все это примеры проблем с доверенным вводом. Все эти атаки смягчаются механизмом, который считает все вводимые данные вредоносными, если не доказано обратное.
5. Обратите внимание на код шифрования!
Давайте посмотрим на то, что может нас удивить. Я обнаружил, что более тридцати процентов проверенного нами кода безопасности имели уязвимости. Возможно, самой распространенной уязвимостью является ваш собственный код шифрования, который, скорее всего, окажется уязвимым. Никогда не создавайте свой собственный код шифрования, это бесполезная затея. Не думайте, что только потому, что у вас есть собственный алгоритм шифрования, другие не смогут его взломать. Злоумышленники имеют доступ к отладчикам, а также у них есть время и знания, чтобы определить, как работают системы, часто ломая их в течение нескольких часов. Вам следует использовать Win32® CryptoAPI, пространство имен System.Security.Cryptography предоставляет ряд отличных и проверенных алгоритмов шифрования.
6. Уменьшите вероятность подвергнуться атаке.
Если более 90% пользователей не запрашивают эту функцию, функция не должна устанавливаться по умолчанию. Internet Information Services (IIS) 6.0 следует этой рекомендации по установке, о которой вы можете прочитать в статье Уэйна Берри «Инновации в Internet Information Services позволяют надежно защитить данные и серверные процессы», выпущенной в этом месяце. Идея этой стратегии установки заключается в том, что вы не будете обращать внимание на службы, которые вы не используете, и если эти службы работают, они могут быть использованы другими. Если функция установлена по умолчанию, она должна работать по принципу наименьшей авторизации. То есть не разрешайте приложениям запускаться с правами администратора без необходимости. Лучше всего последовать этому совету.
7. Используйте принцип наименьшей авторизации.
Операционные системы и общеязыковые среды выполнения имеют политику безопасности по нескольким причинам. Многие люди предполагают, что основная причина существования этой политики безопасности состоит в том, чтобы предотвратить намеренное причинение пользователями вреда: доступ к файлам, к которым у них нет доступа, перенастройку сети в соответствии с их потребностями и другое вопиющее поведение. Да, этот тип внутренней атаки распространен и от него необходимо защищаться, но есть еще одна причина придерживаться этой стратегии безопасности. То есть выстраивание защитных барьеров вокруг кода, чтобы пользователи не могли сеять хаос в сети преднамеренными или (как это часто бывает) непреднамеренными действиями. Например, вложение, загруженное по электронной почте, при выполнении на компьютере Алисы ограничивается ресурсами, к которым Алиса может получить доступ. Если вложение содержит троянского коня, хорошей стратегией безопасности будет ограничение ущерба, который он может нанести.
Когда вы проектируете, создаете и развертываете серверные приложения, вы не можете предполагать, что все запросы исходят от законных пользователей. Если злоумышленник отправляет вам вредоносный запрос (надеюсь, что нет), а ваш код ведет себя плохо, вы хотите, чтобы в вашем приложении были все возможные средства защиты, чтобы ограничить ущерб. Поэтому мы считаем, что ваша компания внедряет политику безопасности не только потому, что не доверяет вам или вашему коду, но и для защиты от вредоносного внешнего кода.
Принцип наименьшей авторизации гласит, что минимальные разрешения, требуемые кодом, должны быть предоставлены за наименьшее время. Тем не менее, всегда возводите как можно больше защитных стен вокруг вашего кода. Когда случается что-то плохое – как гарантирует закон Мерфи – вы будете рады, что эти защитные стены на месте. Поэтому вот несколько конкретных методов запуска кода с использованием принципа наименьшей авторизации.
Выберите безопасную среду для вашего серверного кода, которая предоставляет ему доступ только к тем ресурсам, которые необходимы для выполнения его работы. Если некоторые части вашего кода требуют высоких разрешений, рассмотрите возможность изолировать эту часть кода и запустить ее отдельно с более высокими разрешениями. Чтобы безопасно отделить этот код, который выполняется с другой информацией аутентификации операционной системы, лучше всего запустить этот код в отдельном процессе (работающем в безопасной среде с более высокими привилегиями). Это означает, что вам понадобится межпроцессное взаимодействие (например, удаленное взаимодействие COM или Microsoft .NET), и вам нужно будет спроектировать интерфейс для этого кода, чтобы минимизировать двусторонние обходы.
Если вы разделяете код на сборки в среде .NET Framework, рассмотрите уровни разрешений, необходимые для каждого фрагмента кода. Вы обнаружите, что это простой процесс: отделите код, требующий более высоких привилегий, в отдельную сборку, которая предоставит ему больше привилегий, оставив при этом большинство оставшихся сборок работающими с более низкими привилегиями, чтобы вы могли добавить больше средств защиты вокруг вашего кода. При этом не забывайте, что из-за стека Code Access Security (CAS) вы ограничиваете разрешения не только своей собственной сборки, но и любой сборки, которую вы вызываете.
Многие люди создают свои собственные приложения, чтобы новые компоненты можно было подключать к их продуктам после того, как они протестированы и станут доступны клиентам. Обеспечить безопасность такого типа приложений очень сложно, поскольку вы не можете протестировать все возможные пути кода, чтобы найти ошибки и дыры в безопасности. Однако если ваше приложение размещено на хосте, CLR предоставляет отличную функцию, которую можно использовать для закрытия этих точек расширения. Объявляя объект разрешения или набор разрешений и вызывая PermitOnly или Deny, вы добавляете в свой стек метку, которая будет блокировать предоставление разрешений любому вызываемому вами коду. Сделав это перед вызовом плагина, вы можете ограничить задачи, которые плагин может выполнять. Например, плагин для расчета рассрочки не требует никакого доступа к файловой системе. Это еще один пример наименьших привилегий, когда вы заранее защищаете себя. Обязательно обратите внимание на эти ограничения и имейте в виду, что плагины с более высоким уровнем привилегий могут использовать операторы Assert, чтобы обойти эти ограничения.
8. Осознавайте модели неудач
и принимайте их. Другие ненавидят писать код обработки ошибок так же, как и вы. Существует очень много причин, по которым код может дать сбой, и просто думать о них может быть неприятно. Большинство программистов, включая нас, предпочитают сосредоточиться на обычном пути выполнения. Вот где работа действительно выполняется. Давайте выполним обработку ошибок как можно быстрее и безболезненнее, а затем перейдем к следующей строке реального кода.
К сожалению, эта эмоция небезопасна. Вместо этого нам нужно уделять больше внимания шаблонам сбоев в нашем коде. Этот код часто пишется с небольшим вниманием и часто не тестируется полностью. Помните, когда в последний раз вы были абсолютно уверены, что отладили каждую строку кода функции, включая каждый крохотный обработчик ошибок в ней?
Непроверенный код часто приводит к уязвимостям безопасности. Есть три вещи, которые могут помочь вам смягчить эту проблему. Во-первых, уделите этим крошечным обработчикам ошибок то же внимание, что и обычному коду. Учитывайте состояние системы при выполнении кода обработки ошибок. Находится ли система в эффективном и безопасном состоянии? Во-вторых, после того, как вы написали функцию, несколько раз выполните ее и тщательно отладьте, обязательно проверив каждый обработчик ошибок. Обратите внимание, что даже при использовании таких методов очень тонкие ошибки синхронизации могут быть не обнаружены. Возможно, вам придется передать параметр ошибки в вашу функцию или каким-либо образом скорректировать состояние системы, чтобы позволить вашему обработчику ошибок выполниться. Потратив время на пошаговое выполнение кода, вы сможете замедлить работу и иметь достаточно времени, чтобы увидеть свой код и состояние вашей системы во время его работы. Внимательно просматривая код в отладчике, мы обнаружили множество ошибок в логике нашего программирования. Это проверенная технология. Пожалуйста, используйте эту технику. Наконец, убедитесь, что ваш набор тестов приводит к сбою вашей функции. Постарайтесь создать набор тестов, который проверит каждую строку кода функции. Это может помочь вам выявить шаблоны, особенно при автоматизации тестов и их запуске каждый раз при создании кода.
О режимах отказа следует сказать одну очень важную вещь. Убедитесь, что ваша система находится в максимально безопасном состоянии в случае сбоя кода. Некоторые проблемные коды показаны ниже:
bool accessGranted = true // Слишком оптимистично!
пытаться {
// Проверяем, можем ли мы получить доступ к c:test.txt
новый FileStream (@"c:test.txt",
FileMode.Открыть,
FileAccess.Read).Close();
}
поймать (SecurityException x) {
// Доступ запрещен
доступGranted = ложь;
}
ловить (...) {
// Произошло что-то еще
}
Несмотря на то, что мы используем CLR, нам по-прежнему разрешен доступ к файлу. В этом случае SecurityException не создается. Но что, если, например, список управления доступом к файлу (DACL) не разрешает нам доступ? В это время будет создано исключение другого типа. Но из-за оптимистичных предположений в первой строке кода мы этого никогда не узнаем.
Лучше писать этот код с осторожностью:
bool accessGranted = false // Будьте осторожны!
пытаться {
// Проверяем, можем ли мы получить доступ к c:test.txt
новый FileStream (@"c:test.txt",
FileMode.Открыть,
FileAccess.Read).Close();
// Если мы все еще здесь, отлично!
доступGranted = правда;
}
catch (...) {}
Это будет более стабильно, потому что независимо от того, как мы потерпим неудачу, мы всегда будем возвращаться в самый безопасный режим.
9. Олицетворение очень уязвимо.
При написании серверных приложений вы часто будете использовать, прямо или косвенно, удобную функцию Windows, называемую олицетворением. Олицетворение позволяет каждому потоку процесса работать в другой среде безопасности, обычно в среде клиента. Например, когда перенаправитель файловой системы получает запрос файла по сети, он аутентифицирует удаленного клиента, проверяет, не нарушает ли запрос клиента DACL на общем ресурсе, а затем прикрепляет флаг клиента к потоку, обрабатывающему запрос. . для имитации клиента. Затем этот поток может получить доступ к локальной файловой системе на сервере, используя среду безопасности клиента. Это удобно, поскольку локальная файловая система уже защищена. Он выполняет проверку доступа с учетом типа запрошенного доступа, DACL файла и флага олицетворения в потоке. Если проверка доступа не удалась, локальная файловая система сообщает об этом перенаправителю файловой системы, который затем отправляет ошибку удаленному клиенту. Это, несомненно, удобно для перенаправителя файловой системы, поскольку он просто передает запрос локальной файловой системе и позволяет ей выполнять собственные проверки доступа, как если бы клиент был локальным.
Это все хорошо для простого шлюза, такого как перенаправитель файлов. Но моделирование часто используется и в других, более сложных приложениях. Возьмем в качестве примера веб-приложение. Если вы пишете классическую неуправляемую программу ASP, расширение ISAPI или приложение ASP.NET и имеете следующую спецификацию в файле Web.config
то ваша рабочая среда будет иметь две разные среды безопасности: у вас будет тег процесса и тег потока. Вообще говоря, тег потока будет использоваться для проверки доступа (см. рисунок 3). Предполагая, что вы пишете приложение ISAPI, которое выполняется в процессе веб-сервера, и предполагая, что большинство запросов не аутентифицируются, ваш тег потока может быть IUSR_MACHINE, но ваш тег процесса — СИСТЕМА! Предположим, злоумышленник может использовать ваш код через переполнение буфера. Как вы думаете, его устроит просто работа под именем IUSR_MACHINE? Конечно, нет. Его код атаки, скорее всего, вызывает RevertToSelf, чтобы удалить флаг олицетворения в надежде повысить уровень его привилегий. В этом случае он легко добьется успеха. Он также может вызвать CreateProcess. Он копирует тег нового процесса не из тега олицетворения, а из тега процесса, чтобы новый процесс мог работать как СИСТЕМА.
Так как же решить эту маленькую проблему? Помимо обеспечения отсутствия переполнения буфера, помните о принципе наименьшей авторизации. Если ваш код не требует таких больших привилегий, как СИСТЕМА, не настраивайте свое веб-приложение для запуска в процессе веб-сервера. Если вы просто настроите свое веб-приложение для работы в среде со средней или высокой степенью изоляции, вашим тегом процесса будет IWAM_MACHINE. На самом деле у вас нет никаких разрешений, поэтому эта атака практически не имеет эффекта. Обратите внимание, что в IIS 6.0 (который вскоре станет компонентом Windows .NET Server) написанный пользователем код по умолчанию не будет выполняться как СИСТЕМА. Учитывая понимание того, что разработчики допускают ошибки, любая помощь, которую веб-сервер может оказать в уменьшении разрешений, предоставляемых коду, полезна в случае, если в коде есть проблемы с безопасностью.
Вот еще одна ловушка, с которой могут столкнуться COM-программисты. COM имеет плохую тенденцию игнорировать потоки. Если вы вызываете внутрипроцессный COM-сервер и его модель потока не соответствует модели вызывающего потока, COM выполняет вызов в другом потоке. COM не распространяет флаг олицетворения в вызывающем потоке, поэтому в результате вызов выполняется в контексте безопасности процесса, а не в контексте безопасности вызывающего потока. Какой сюрприз!
Вот еще один пример ловушек моделирования. Предположим, что ваш сервер принимает запросы, отправленные через именованные каналы, DCOM или RPC. Вы аутентифицируете клиентов и олицетворяете их, открывая объекты ядра от их имени посредством олицетворения. И вы забыли закрыть один из объектов (например, файл) при отключении клиента. Когда приходит следующий клиент, вы аутентифицируете его и выдаете себя за него, и угадайте, что происходит? Вы по-прежнему можете получить доступ к файлам, которые были «пропущены» предыдущим клиентом, даже если новый клиент не получил доступа к файлу. Из соображений производительности ядро выполняет проверку доступа к объекту только при его первом открытии. Вы по-прежнему сможете получить доступ к этому файлу, даже если позже измените среду безопасности, поскольку выдаете себя за другого пользователя.
Все упомянутые выше ситуации напоминают вам, что моделирование обеспечивает удобство разработчикам серверов, но это удобство таит в себе большие скрытые опасности. Когда вы запускаете программу с макетным флагом, обязательно обратите пристальное внимание на свой код.
10. Пишите приложения, которые смогут использовать пользователи, не являющиеся администраторами.
На самом деле это следствие принципа наименьшего количества авторизации. Если программисты продолжат разрабатывать код, который требует наличия администратора для правильной работы в Windows, мы не можем рассчитывать на улучшение безопасности системы. Windows имеет очень солидный набор функций безопасности, но пользователи не смогут ими воспользоваться, если для их работы необходимо быть администратором.
Как вы можете улучшиться? Для начала попробуйте сами, не запуская от имени администратора. Вскоре вы почувствуете боль от использования программы, которая не была разработана с учетом требований безопасности. Однажды я (Кит) установил программное обеспечение, предоставленное производителем моего портативного устройства, которое синхронизировало данные между моим настольным компьютером и моим портативным устройством. Как обычно, я вышел из своей обычной учетной записи пользователя, снова вошел в систему, используя встроенную учетную запись администратора, установил программное обеспечение, затем снова вошел в свою обычную учетную запись и попытался запустить программное обеспечение. В результате приложение выдает диалоговое окно о том, что к требуемому файлу данных нет доступа, а затем выдает сообщение о нарушении прав доступа. Друзья, это программный продукт крупного производителя карманных устройств. Есть ли оправдание этой ошибке?
Запустив FILEMON с http://sysinternals.com (на английском языке), я быстро обнаружил, что приложение пытается открыть файл данных для доступа на запись, который был установлен в том же каталоге, что и исполняемый файл приложения. Когда приложения устанавливаются в каталог Program Files, как и ожидалось, они не должны пытаться записывать данные в этот каталог. Program Files имеет такую ограничительную политику контроля доступа не просто так. Мы не хотим, чтобы пользователи записывали данные в эти каталоги, так как это облегчит задачу одному пользователю передать троян для выполнения другому пользователю. Фактически, это соглашение является одним из основных требований к подписи Windows XP (см. http://www.microsoft.com/winlogo [англ.]).
Мы слышим, как слишком много программистов оправдываются, почему они предпочитают работать от имени администратора при разработке кода. Если мы продолжим игнорировать эту проблему, мы только усугубим ситуацию. Друзья, для редактирования текстового файла вам не нужны права администратора. Права администратора также не требуются для редактирования или отладки программы. Если вам нужны права администратора, используйте функцию запуска от имени операционной системы для запуска 玎com.asp?TARGET=/winlogo/">http://www.microsoft.com/winlogo [английский]).
Мы слишком часто это слышим, программисты оправдываются. почему они предпочитают работать от имени администратора при разработке кода. Если мы продолжим игнорировать эту проблему, это только ухудшит ситуацию. Редактирование текстового файла не требует прав администратора. Или отладка программы не требует прав администратора. Если вы пишете инструменты для разработчиков, на вас лежит дополнительная ответственность за эту группу. остановить этот порочный круг написания кода, который можно запускать только от имени администратора. Цель должна измениться фундаментально.
Для получения дополнительной информации о том, как разработчики могут легко работать без прав администратора, посетите веб-сайт Кита по адресу http://www.develop. com/kbrown (на английском языке) Ознакомьтесь с книгой Майкла «Написание безопасного кода» (Microsoft Press, 2001), в которой содержатся советы о том, как писать приложения, которые хорошо работают в среде без администратора.