quitar - restaurar java
¿Cuál es el riesgo de seguridad de la reflexión de objetos? (5)
1 - La reflexión (como concepto) es de hecho ortogonal a la seguridad.
Hubo un gran énfasis en el diseño de Java para convertirlo en una plataforma segura, con escritura estática , administrador de seguridad , uso disciplinado del cargador de clases y no hay forma de atornillar los punteros / memoria . Puedes leer la entrevista de James Gosling en Masterminds of programación , lo cual es interesante al respecto.
Pero cuanto más poder reflexivo tenga, más difícil será asegurarse de que las cosas estén seguras como deberían. La reflexión derrota notablemente la escritura estática y puede llevar a errores en tiempo de ejecución.
Pero también pueden pasar cosas más sutiles. Por ejemplo, los cargadores de clases, que pueden considerarse como un gancho reflexivo en el sistema, no se diseñaron correctamente en la versión anterior de Java, lo que lleva a un posible reemplazo de tipos. El artículo Carga dinámica de clases en la JVM, por Gilad Bracha, es perspicaz sobre estos temas.
La reflexión no se puede desactivar por completo; Siempre es posible reflexionar sobre sus propios campos / métodos públicos. Sin embargo, la reflexión sobre estructuras privadas con AccessibleObject.setAccessible
se puede deshabilitar, porque rompe la encapsulación . Con acceso a campos privados, etc. es posible la inspección y modificación de datos internos. Puede conducir a varias explotaciones maliciosas , por ejemplo,
-
strings
ya no son inmutables y se pueden cambiar (consulte esta question ) - Puede revelar información sensible de objetos que no posee
- ... otras hazañas ...
Finalmente, hay otro mecanismo que pone en peligro la seguridad, especialmente sun.misc.Unsafe
que proporciona acceso directo a la memoria: los punteros están de vuelta.
2 - Ahora, la pregunta es si la reflexión (en la práctica) lleva a tantos riesgos.
He leído el enlace apuntado por @dbyrne pero se trata principalmente de .net. Además, no sé exactamente qué está deshabilitado para la aplicación de Google. ¿Es solo el ReflectPermission
u otro permiso del administrador de seguridad? Un peligro es claramente tener acceso al sistema de archivos y perder el tiempo.
El problema del acceso a datos privados y la ruptura de la encapsulación se puede argumentar en la práctica. Escribir un código de seguridad es extremadamente difícil, e incluso sin cambiar el modificador de acceso, puede subclasificar las clases de manera inapropiada, a menos que sean final
, o incluso mejor, selladas, y pasarlas. Esto es, por ejemplo, contra lo que intenta protegerse la copia defensiva .
De todos modos, la seguridad de tipo también se ve amenazada por un error en el tiempo de ejecución debido a una caída, por lo que este punto también se puede argumentar.
En un entorno compartido / alojado, la seguridad es relativa . En el nivel de idioma, por ejemplo, puede evitar que un módulo no consuma el 100% de la CPU o que consuma toda la memoria hasta una OutOfMemoryException
. Dichas inquietudes deben abordarse por otros medios, generalmente a nivel del sistema operativo, con virtualización y cuotas.
Entonces, mi respuesta personal sería: la reflexión es un riesgo para la seguridad, pero no tan grande en la práctica si se compara con otros posibles vectores de ataque.
Entonces, después de algunas horas de solución a la limitación de la reflexión actualmente deshabilitada en el motor de aplicaciones de Google, me preguntaba si alguien podría ayudarme a entender por qué la reflexión de objetos puede ser una amenaza. ¿Es porque puedo inspeccionar las variables privadas de una clase o existen otras razones más profundas?
En primer lugar, si no ha instalado un SecurityManager
entonces no está seguro de todos modos.
En segundo lugar, la reflexión no abre agujeros significativos a menos que se setAccessible()
, y eso en sí mismo está sujeto a una verificación de seguridad (gobernada por el permiso de reflexión setAccessChecks
). Sin eso, aunque pueda saber que el campo o método privado existe (aunque eso sí requiere el permiso de tiempo de ejecución accessDeclaredMembers
), no puede hacer mucho con ese conocimiento. Su mejor apuesta para atacar podría ser trabajar con objetos serializados, pero esa es una bola de cera.
Tenga en cuenta también que escribir un administrador de seguridad seguro y un cargador de clases no es trivial. Es mejor dejarlos a otros si no estás aspirando a un mega-guru-dom (o, lo más probable, niveles de fracaso vergonzosos).
GAE es un entorno de alojamiento compartido y aloja archivos WAR de varios usuarios. Es muy probable que múltiples archivos WAR estén alojados en la misma JVM, porque generar un proceso por WAR es simplemente ridículo. Por lo tanto, la única forma de proteger cada archivo WAR es a través de un cargador de clases personalizado para cada archivo WAR.
Ahora, supongamos que se permitió la reflexión. A continuación, puede recorrer la jerarquía del cargador de clases y enumerar las clases / métodos de los archivos WAR que pertenecen a diferentes usuarios. Obviamente, esa es una gran preocupación.
Una aplicación puede utilizar las API de reflexión de Java para acceder y actualizar campos, y ejecutar métodos que están prohibidos por las reglas normales de acceso / visibilidad de Java. Con un poco de ingenio, esto es suficiente para:
- acceder a la información que se supone que está oculta,
- subvierta el entorno limitado de seguridad de Java para que pueda interferir con otras cosas que se ejecutan en la JVM, acceder a los archivos en la máquina local, etc.
Bajo ciertas circunstancias, incluso podría permitir la inyección de código nativo malicioso.
Una teoría mía es que Google está tratando de ocultar algo. Al deshabilitar Reflection Google podría ocultar nombres de variables, llamadas a funciones y hasta una API completa. Si Google está ocultando algo como una API, entonces la certeza no te lo dirá.
Sé a ciencia cierta que Reflection juega un papel muy importante en las pruebas de seguridad. Por ejemplo, puedes generar automáticamente pruebas de Fuzz usando la reflexión. AxMan utiliza TypeLib para identificar todas las clases y sus llamadas de método que conforman un objeto COM. Usando esta información, AxMan creará una instancia de cada clase y llamará a cada método con permutaciones de cadenas largas y números grandes. SOAP Fuzzers realiza pruebas similares usando el archivo WSDL para la reflexión.