Таким образом, после нескольких часов обходного решения ограничение Отражения, в настоящее время отключаемого на Google App Engine, я задавался вопросом, мог ли кто-то помочь мне понять, почему объектное отражение может быть угрозой. Это, потому что я могу осмотреть частные переменные класса или являюсь там какими-либо другими более глубокими причинами?
1 - Отражение (как концепция) действительно ортогонально к безопасности/безопасности.
При разработке java большое внимание уделялось тому, чтобы сделать ее безопасной платформой, с статической типизацией, менеджером безопасности, дисциплинированным использованием загрузчика классов, и отсутствием возможности портировать указатели/память. Вы можете прочитать интервью Джеймса Гослинга в Masterminds of programming, которое интересно об этом.
Но чем больше у вас рефлексивных возможностей, тем сложнее обеспечить безопасность вещей, как они должны быть. Отражение в значительной степени нарушает статическую типизацию и может привести к ошибкам во время выполнения.
Но могут произойти и более тонкие вещи. Например, загрузчики классов - которые можно рассматривать как рефлексивные крючки в системе - не были спроектированы должным образом в ранней версии Java, что привело к потенциальной замене типов. В статье Динамическая загрузка классов в JVM, написанной Гиладом Браха, содержится глубокий анализ таких вопросов.
Отражение нельзя отключить совсем; всегда можно отражать на своих собственных публичных полях/методах. Однако отражение на частных структурах с помощью AccessibleObject.setAccessible
можно отключить, поскольку это нарушает инкапсуляцию. При доступе к приватным полям и т.д. возможны проверка и модификация внутренних данных. Это может привести к различным вредоносным эксплойтам, например,
строки
больше не являются неизменяемыми и могут быть изменены (см. этот вопрос) Наконец, есть и другие механизмы, которые ставят безопасность под угрозу, в частности sun.misc.Unsafe
, который дает прямой доступ к памяти - указатели вернулись.
2 - Теперь вопрос в том, приводит ли отражение (на практике) к такому количеству рисков.
Я прочитал ссылку, на которую указал @dbyrne, но там в основном про .net. Также я не знаю, что именно отключено для Google App. Это ReflectPermission
only, или другое разрешение менеджера безопасности? Очевидно, что одна из опасностей - получить доступ к файловой системе и все испортить.
Проблема доступа к приватным данным и нарушения инкапсуляции может быть оспорена на практике. Написание безопасного кода действительно чрезвычайно сложно, и даже без изменения модификатора доступа вы можете подклассифицировать классы неподобающим образом - если они не являются final
, или, еще лучше, sealed - и передавать их по кругу. Это, например, то, от чего пытается защититься защитное копирование .
Типовая безопасность также в любом случае находится под угрозой из-за ошибок во время выполнения из-за даункаста, так что этот момент тоже можно оспорить.
В разделяемой/хостируемой среде безопасность относительна. На уровне языка вы, например, не можете запретить модулю потреблять 100% процессора или использовать всю память вплоть до OutOfMemoryException
. Такие проблемы должны решаться другими средствами, обычно на уровне ОС, с помощью виртуализации и квот.
Поэтому мой личный ответ будет таким: отражение - это риск для безопасности, но на практике он не так велик по сравнению с другими потенциальными векторами атак.
Приложение может использовать API-интерфейсы отражения Java для доступа и обновления полей, а также выполнять методы, запрещенные обычной Java. правила доступа / видимости. Приложив немного изобретательности, этого достаточно, чтобы:
При определенных обстоятельствах он может даже позволить внедрение вредоносного нативного кода.
Во-первых, если у вас не установлен SecurityManager
, то вы все равно не защищены.
Во-вторых, отражение не открывает значительных дыр, если только не включена setAccessible()
, а это само по себе подлежит проверке безопасности (регулируется setAccessChecks
разрешением на отражение). Без этого, хотя вы можете узнать, что приватное поле или метод существует (хотя для этого требуется разрешение accessDeclaredMembers
runtime), вы не сможете сделать ничего особенного с этим знанием. Лучшим вариантом для атаки может быть работа с сериализованными объектами, но это уже совсем другое дело.
Заметьте также, что написание безопасного менеджера безопасности и загрузчика классов нетривиально. Лучше оставить это другим, если вы не стремитесь к статусу мега-гуру (или, что более вероятно, к позорному уровню неудач).
GAE - это среда виртуального хостинга, и на ней размещаются WAR-файлы от нескольких пользователей. Вполне вероятно, что несколько WAR-файлов размещены в одной JVM, потому что порождать процесс для каждого WAR просто нелепо. Поэтому единственным способом песочницы для каждого WAR-файла является пользовательский загрузчик классов для каждого WAR-файла.
Теперь предположим, что отражение было разрешено. Тогда вы могли бы пройтись по иерархии загрузчика классов и перечислить классы/методы из WAR-файлов, принадлежащих разным пользователям. Очевидно, что это большая проблема.
Моя теория состоит в том, что Google пытается что-то скрыть. Отключив Отражение , Google может скрыть имена переменных, вызовы функций и даже полный API. Если Google скрывает что-то вроде API, то они точно не расскажут вам об этом.
Я точно знаю, что Reflection играет очень важную роль в тестировании безопасности. Например, вы можете автоматически генерировать тесты Fuzz, используя отражение. AxMan использует TypeLib для идентификации всех классов и их вызовов методов, составляющих COM-объект. Используя эту информацию, AxMan затем создаст экземпляр каждого класса и вызовет каждый метод с перестановками длинных строк и больших чисел. Аналогичное тестирование проводится SOAP Fuzzers с использованием файла WSDL для отражения.