2010-05-16 8 views
30

Efectivo java dice:¿Por qué el conjunto final estático público es un agujero de seguridad?

// Potential security hole!

static public final Thing [] VALUES = {...};

¿Alguien puede decirme cuál es el agujero de seguridad?

+0

No más de un agujero de seguridad que privado, si puede leer el código fuente y/o bytecode de cualquier manera ... – Amber

+1

¡La palabra clave es "potencial"! Todo lo que es públicamente accesible en una clase debe ser comprendido y * destinado *. Es un _contrato_! Como con cualquier contrato, debe ser bien pensado, claro y comprensible para todos, y su uso e implementación en * todas * circunstancias aceptables porque es inevitable que se intente cualquiera y todos los escenarios. La clave para crear cualquier clase es comenzar con la interfaz más restrictiva. Casi siempre es posible exponer características adicionales y casi siempre es difícil eliminarlas. – nicerobot

Respuesta

48

Declarar static final public campos es generalmente el sello distintivo de una constante de clase. Está perfectamente bien para tipos primitivos (ints, dobles, etc.) y clases inmutables, como strings y java.awt.Color. Con las matrices, el problema es que a pesar de que la referencia de la matriz es constante, los elementos de la matriz todavía se pueden cambiar, y como es un campo, los cambios están desprotegidos, no controlados y normalmente no son bienvenidos.

Para combatir esto, la visibilidad del campo de matriz puede restringirse a privado o paquete privado, por lo que tiene un cuerpo más pequeño de código para considerar al buscar modificaciones sospechosas. Alternativamente, y a menudo mejor, es eliminar la matriz y usar una 'Lista', u otro tipo de colección apropiada. Al usar una colección, usted controla si se permiten actualizaciones, ya que todas las actualizaciones pasan por métodos. Puede evitar actualizaciones envolviendo su colección usando Collections.unmodifiableList(). Pero tenga en cuenta que, aunque la colección es inmutable, también debe asegurarse de que los tipos almacenados en ella también sean inmutables o que reaparezca el riesgo de cambios no solicitados en una supuesta constante.

+0

La falta de matrices inmutables es una de mis cosas menos favoritas acerca de Java. – Andy

0

Creo que solo significa todo lo público vs lo privado. Se supone que es una buena práctica que las variables locales se declaren privadas, y luego usar los métodos get y set, en lugar de acceder directamente a ellas. Los hace un poco más difíciles de meter fuera de su programa. Sobre eso, hasta donde yo sé.

+3

Es más sutil que eso. Una 'cadena estática pública final 'está bien, pero una' cadena final estática pública []' no lo es, porque los * contenidos * de la matriz se pueden cambiar. –

14

Tenga en cuenta que una matriz de longitud distinta de cero es siempre mutable, por lo está mal que una clase tenga un campo public static final de matriz o un descriptor de acceso que devuelve un campo de este tipo. Si una clase tiene dicho campo o acceso, los clientes podrán modificar el contenido de la matriz.

- Efectivo Java, 2nd Ed. (página 70)

+0

Esta es la respuesta correcta; el problema es que el tipo da la impresión de una constante, pero no es – 00prometheus

1

En esta declaración, un cliente puede modificar Cosa [0], Cosa [1], etc. (es decir, elementos en la matriz).

2

Una clase externa puede modificar el contenido de la matriz, que probablemente no es lo que desea que hagan los usuarios de su clase (desea que lo hagan a través de un método). Parece que el autor quiso decir que viola la encapsulación y no la seguridad.

Supongo que alguien que declare esta línea podría pensar que otras clases no pueden modificar los contenidos de la matriz ya que está marcada como final, pero esto no es cierto, final solo le impide volver a asignar el atributo.

+2

.. si está ejecutando código que no es de confianza en un sandbox, y el 'string final estático público []' está en código de confianza, entonces esto ** es ** un problema de seguridad. ¡Creo que el autor quiso decir lo que escribió! –

+0

@Stephen C: Si la intención es tener una matriz cuyos contenidos son inmutables, entonces, si esto es un problema de seguridad. Si el programador lo hizo a propósito, dejar que alguien modifique el contenido de la matriz es parte de la interfaz de la matriz. El primer caso puede ser un problema de seguridad, este último probablemente no. ¿O me estoy perdiendo algo aquí? –

+0

Creo que el punto del autor es que este es ** potencial ** agujero de seguridad porque no está claro lo que el análisis de diseño/seguridad requiere. (Estaba a punto de decir "cuál era la intención del codificador", pero me di cuenta de que la * intención * del codificador es secundaria. Considere las posibilidades: 1) el codificador simplemente no pensó en el problema y no tenía ideas claras sobre él, o 2) el codificador deliberadamente hizo esto para introducir un agujero de seguridad.) –

0

Porque la palabra clave final solo garantiza el valor de referencia (supongamos que es la ubicación de la memoria, por ejemplo) pero no el contenido.

37

Para entender por qué esto es un problema de seguridad potencial y no simplemente mala encapsulación, consideremos el siguiente ejemplo:

public class SafeSites { 
    // a trusted class with permission to create network connections 
    public static final String[] ALLOWED_URLS = new String[] { 
     "http://amazon.com", "http://cnn.com"}; 

    // this method allows untrusted code to connect to allowed sites (only) 
    public static void doRequest(String url) { 
     for (String allowed : ALLOWED_URLS) { 
      if (url.equals(allowed)) { 
       // send a request ... 
      } 
     } 
    } 
} 

public class Untrusted { 
    // An untrusted class that is executed in a security sandbox. 

    public void naughtyBoy() { 
     SafeSites.ALLOWED_URLS[0] = "http://myporn.com"; 
     SafeSites.doRequest("http://myporn.com"); 
    } 
} 

Como se puede ver, el uso erróneo de una matriz definitiva significa que el código no confiable puede subvertir el restricción que el código de confianza/sandbox está tratando de imponer. En este caso, esto es claramente un problema de seguridad.

Si su código no es parte de una aplicación de seguridad crítica, puede ignorar este problema. Pero IMO esta es una mala idea. En algún momento en el futuro, usted (u otra persona) podría reutilizar su código en un contexto donde la seguridad es una preocupación. En cualquier caso, este es por lo que el autor considera que los arreglos finales públicos son un problema de seguridad.


ámbar dijo esto en un comentario:

No más de un agujero de seguridad privada sería, si usted puede leer el código fuente y/o el código de bytes de cualquier manera ...

Esto no es verdad.

El hecho de que un "chico malo" puede utilizar el código fuente/códigos de bytes para determinar que un private existe y se refiere a una matriz es no suficiente para romper la seguridad. El tipo malo también tiene que inyectar código en una JVM que tenga los permisos necesarios para usar la reflexión. Este permiso no está disponible para no confiable código que se ejecuta en un entorno limitado de seguridad (implementado correctamente).

+2

¡Genial, me encanta tu pornografía! –

+0

naughtyBoy: D. Buen nombre para la función. – peeyush

Cuestiones relacionadas