¿Hay casos de la vida real, donde el uso de la palabra clave final en Java aumenta la seguridad del sistema?

6

Encontré esa pregunta en StackOverflow: enlace

Se hace la reclamación, que según Wikipedia:

  

Una clase final no puede ser subclasificada. Esto se hace por razones de   seguridad y eficiencia.

y el OP preguntó, cómo se logra la seguridad con la palabra clave final.

Lo que me sorprendió fue que la mayoría de las respuestas afirmaban que la palabra clave final aumentaría considerablemente la seguridad, ya que el atacante no podrá anular sus clases ni llamar a sus métodos protegidos, etc. Se basan principalmente en el artículo de Oracle Pautas de codificación seguras

For example, making a class final prevents a malicious subclass from adding
finalizers, cloning, and overriding random methods

Sin embargo, a mi entender, si el atacante obtiene la posibilidad de ejecutar código Java arbitrario en el sistema de destino (y si se considera que él está anulando sus clases, se espera que lo sea), entonces ya puede hacer todo lo que su código es capaz de hacerlo, por lo tanto, es completamente irrelevante desde el punto de vista de la seguridad, si sus métodos son definitivos o no, o incluso si los campos son privados y no están expuestos o no (puede serializar su clase y leer todos los campos, etc.).

Pero en el otro lado, ¿es posible encontrar un escenario de la vida real, cuando el atacante no lograría sus objetivos mediante la ejecución de código arbitrario, y solo tendría éxito (o tal ataque sería mucho más fácil) por 'maliciosamente ¿Anulando sus clases, como se describe en el artículo de Oracle? Por ejemplo, si el servidor de aplicaciones está compartido por varias aplicaciones Java.

    
pregunta Danubian Sailor 12.09.2013 - 19:31
fuente

2 respuestas

7

Esta característica de Java tiene sentido, desde el punto de vista de la seguridad, en el modelo de applet : un contexto donde, de hecho, el el atacante ejecuta su código en su máquina y, sin embargo, ese código potencialmente hostil todavía está contenido. Esto fue pensado inicialmente para navegadores web, no para servidores.

Toda la contención de un applet de Java se realiza llamada por llamada, de manera muy precisa. Existe un marco complejo de permisos que codifica lo que puede hacer el applet y lo que no puede hacer. En particular, un applet básico no puede realizar una serialización arbitraria de código, o reflexión para inspeccionar y / o modificar instancias de su propio paquete, o llamar a código nativo. La palabra clave final también tiene sentido en ese contexto: dado que String es final , las clases estándar pueden asumir que cuando reciben como argumento un String , es el objeto genuino, no un EvilString , que extiende String pero actúa de manera inesperada cuando se invoca su método Substring() .

Resultó que mantener la seguridad en estas condiciones era un problema difícil, más difícil de lo que Sun creía inicialmente. Hay cientos, si no miles, de clases de biblioteca estándar que deben hacerse "conscientes de los permisos" y, para cada una de ellas, el código debe tener cuidado de hacer cumplir los permisos apropiados. Era inevitable que la gente de Sun, por muy competentes que fueran, se olviden de algunos casos de esquina, lo que lleva a vulnerabilidades explotables. Durante los últimos años, ha habido un flujo constante de "vulnerabilidades del applet de Java" que permiten que un sitio web malvado tome el control de cualquier navegador web que lo visite, siempre que ese navegador use un complemento de Java que no haya sido arreglado.

Nada de esto afecta a Java como lenguaje de programación, ya que se usa a menudo en servidores o en aplicaciones de escritorio grandes; en estas situaciones, de hecho, no hay ningún código hostil ejecutándose localmente.

La palabra clave final todavía puede servir como documentación aplicada por el compilador (por lo tanto, no contra los atacantes , sino como un recordatorio para los programadores descuidados); también ayuda a la optimización (cuando la JVM ve una llamada a un método final , o a cualquier método en una clase final , entonces sabe que puede optimizar la llamada en un salto directo al código del método, ya que hay de ninguna manera ese método podría ser anulado).

    
respondido por el Tom Leek 12.09.2013 - 20:14
fuente
1

También hay seguridad de diseño :

Marcando clases y métodos como final ; el equipo de desarrollo poda la cantidad de mutación futura en el código sensible *. Esto guía al equipo de desarrollo (que puede ser distribuido) y a los futuros mantenedores de código o proyectos de mejora sobre dónde se produce y debería ocurrir el comportamiento sensible, concentrando el riesgo de diseño en un área más pequeña.

Si recuerdo correctamente, las clases de BouncyCastle que no están destinadas al consumo público de la API se bloquean de esta manera para desalentar el comportamiento polimórfico inesperado y el diseño de cripto-primativos caseros de BouncyCastle. Si bien final no impide que nadie modifique el código fuente y vuelva a compilar como mejor le parezca, para cualquier proyecto con un buen diseño, final ofrece un indicador de advertencia decente para los nuevos desarrolladores de que la mutación del método puede tener efectos secundarios inesperados. Integridad del marco interno. Y por lo tanto sobre la seguridad.

* Para la gran inconveniencia de los desarrolladores de POO entrenados clásicamente, podría agregar.

    
respondido por el LateralFractal 13.09.2013 - 00:56
fuente

Lea otras preguntas en las etiquetas