Очевидное решение – никогда не запускать никаких интерпретаторов команд. Но это не всегда практично, особенно если речь идет о работе с базой данных. Можно было бы сказать иначе: если вы все–таки обращаетесь к оболочке, не передавайте ей данные, поступившие извне. Но и этот совет столь же непрактичен.
Единственная разумная рекомендация – проверять входные данные. Путь к искуплению греха часто состоит всего из двух шагов:
1) проверьте данные и убедитесь, что они корректны;
2) предпримите необходимые действия, если данные некорректны.
Контроль данных
На самом верхнем уровне у вас есть две возможности. Можно проверять все, что передается внешнему процессу, или только те данные, которые поступают из источника, не заслуживающего доверия. Оба варианта приемлемы, если вы производите проверку тщательно.
Обычно внешние данные имеет смысл проверять непосредственно перед использованием. На то есть две причины. Во–первых, таким образом гарантируется, что данные будут проверены на любом пути, ведущем к их использованию. Во–вторых, смысл данных часто проще всего понять непосредственно перед использованием. А, понимая смысл, вы сможете наилучшим образом выполнить проверку. Кроме того, такой подход позволяет защититься от непреднамеренной порчи данных после начальной проверки.
Но наилучшей является стратегия глубоко эшелонированной обороны. Разумно проверять данные и в момент поступления, чтобы избежать риска использовать непроверенные данные где–то в другом месте, особенно в ситуации, когда таких мест много.
Есть три основных способа обеспечить корректность данных:
□ подход «все кроме».Вы ищете свидетельства того, что данные некорректны, а если не находите, то принимаете их;
□ подход «только такие».Вы сравниваете данные с заведомо корректными, а все остальные отвергаете (даже если есть шанс, что ничего страшного не произойдет);
□ «закавычивание».Вы преобразуете данные таким образом, чтобы избежать всякого риска.
Всем им свойствен общий недостаток: вы можете что–то проглядеть. В случае подхода «все кроме» и «закавычивания» это, очевидно, может иметь плачевные последствия для безопасности. На самом деле, отвергая все данные, кроме тех, что кажутся корректными, вы, скорее всего, получите небезопасную программу, так как перечень символов, которые могут иметь специальный смысл, довольно велик. В некоторых системах почти все символы, кроме букв и цифр, могут оказаться специальными. «Закавычивание» часто гораздо труднее реализовать, чем кажется на первый взгляд. Например, при попытке сделать это для некоторых командных процессоров чаще всего строку с входными данными просто заключают в двойные кавычки. Но если вы не проявите осторожность, противник сможет сам включить в строку кавычки. Кроме того, для некоторых процессоров (например, командных оболочек в UNIX) есть метасимволы, которые интерпретируются даже внутри кавычек.
Чтобы убедиться в том, насколько сложна эта задача, попробуйте сами записать все метасимволы, имеющие специальный смысл для UNIX. Включите все, что может интерпретироваться как управляющие символы. Насколько длинный список у вас получится?
В наш перечень вошли все пунктуационные символы, кроме @, _, +,: и запятой. Но полной уверенности, что эти символы во всех случаях безопасны, у нас нет. Возможно, существуют интерпретаторы, для которых и они могут быть управляющими.
Быть может, вы полагаете, что некоторые из упомянутых символов никогда не имеют специального смысла. Скажем, знак минуса? Увы, если минус находится в начале слова, то может интерпретироваться как признак окончания флагов команды. А как насчет символа А? Вы не знали, что он применяется для подстановок? Ну а знак процента? Хотя при интерпретации в качестве метасимвола он, скорее всего, безопасен, но все же может быть метасимволом, поскольку используется для управления заданиями. Вместо знака тильды (~) в начале слова иногда подставляется начальный каталог пользователя, а в остальных случаях он метасимволом не является. Однако и такое использование может привести к раскрытию информации, особенно если цель противника – увидеть ту часть файловой системы, которую программа видеть не должна. Например, вы могли бы поместить свое приложение в каталог /home/blah/ и запретить во входных данных две подряд идущие точки. Тем не менее противник сможет добраться до любого файла в этом каталоге, добавив к имени файла префикс ~.
Читать дальше
Конец ознакомительного отрывка
Купить книгу