vulnerabilidad de parámetro de tipo de clase Java

1

En un libro de programación de Java hay una sección que detalla la JVM y las direcciones de memoria y la ubicación en lo que respecta a los parámetros de un tipo de clase. Como puede ver en la salida de la consola, el objeto inicial se sobrescribe en la memoria (potencialmente involuntariamente para el autor de la API). Se me explicó que esto puede ser una vulnerabilidad de seguridad de software no intencionada y que se detectaría durante una revisión manual del código.

¿Puede alguien explicar de qué manera se explotaría esta vulnerabilidad? ¿Estaría usando la API de otra persona que contiene esta vulnerabilidad o estaría explotando una aplicación real que contenga esto? ¿Hay algún ejemplo (quizás en las noticias) de que se esté haciendo esto?

Así es como funciona, según el texto:

MainActivity.class:

public class MainActivity {

public static void main(String[] args) {
        ToyClass anObject = new ToyClass("Mr. Cellophane", 0);
        System.out.println(anObject);
        System.out.println("Now we call changer with anObject as an argument");
        ToyClass.changer(anObject);
        System.out.println(anObject);
    }
}

ToyClass

public class ToyClass {
    private String name;
    private int number;

    public ToyClass(String initialName, int initialNumber) {
        name = initialName;
        number = initialNumber;
    }

    public ToyClass() {
        name = "No name yet.";
        number = 0;
    }
    public void set(String newName, int newNumber) {
        name = newName;
        number = newNumber;
    }
    public String toString() {
        return (name +" " + number);
    }
    public static void changer(ToyClass aParameter) {
        aParameter.name = "Hot Shot";
        aParameter.number = 42;
    }
    public boolean equals(ToyClass otherObject) {
        return ((name.equals(otherObject.name)&& (number == otherObject.number) ));
    }
}

Salida de consola:

Mr. Cellophane 0
Now we call changer with anObject as an argument
Hot Shot 42

Editar: para explicar el fondo un poco más. Este ejemplo muestra cómo en el sistema de memoria JVM dos objetos se encuentran en una dirección diferente, mientras que el parámetro almacenado se encuentra en la misma ubicación de memoria y se sobrescribe con el segundo método. Esta es la base de la "vulnerabilidad".

    
pregunta KDEx 21.09.2012 - 21:06
fuente

3 respuestas

3

Lo que muestra este ejemplo es que las instancias de clase en Java son mutable : el contenido de una instancia puede cambiar durante el tiempo de vida de la instancia. Esto puede ser sorprendente para las personas que han hecho demasiado Haskell pero, por lo demás, es una característica bastante básica de Java, que es compartida por muchos lenguajes de programación, incluyendo C, C ++, Javascript, C #, Forth, Pascal ...

Las

instancias inmutables son convenientes para la programación, en particular cuando varios desarrolladores deben colaborar. En Java, la clase String es el ejemplo canónico de instancias inmutables: cada instancia String representa una cadena dada que no se puede cambiar (*). Cuando quiere modificar una cadena, llama a un método como substring() que not realmente modifica la cadena; en su lugar, crea y devuelve una nueva instancia String , sin tocar la cadena original. Cuando tiene instancias inmutables, puede guardarlas y compartirlas con menos precauciones.

Por ejemplo, suponga que tiene una clase que representa a un usuario autenticado:

public class AuthenticatedUser {

    private String name;

    public String getName()
    {
        return name;
    }
}

Dicha instancia mantiene el nombre del usuario autenticado en un campo interno. El método getName() devuelve ese nombre: puede devolver la misma instancia que mantiene internamente, ya que las instancias de String son inmutables: el llamante no podrá modificarlo de todos modos. Por lo tanto, no es necesario crear una copia, el getName() público puede proporcionar la cadena real de inmediato.

Las instancias mutables, por el contrario, requieren más cuidado y, a menudo, mucha copia. No hacerlo puede dar lugar a errores sutiles, y las vulnerabilidades de seguridad no son otra cosa que los errores que han llamado la atención de un individuo malintencionado.

Java es un lenguaje que tiene algunas características útiles para hacer objetos inmutables:  - Sus tipos fuertes prohíben las operaciones que no siguen los sistemas de tipo (a diferencia de, por ejemplo, C, donde todo es solo un conjunto de bytes y se puede acceder como tal).  - Los métodos y campos se pueden etiquetar con una visibilidad como el private anterior.  - Java incluye un recolector de basura que es el complemento necesario para compartir instancias inmutables a través de llamadas a métodos (sin memoria automática administración, dicho intercambio debe incluir reglas sobre quién es responsable de liberar la memoria, y esto rara vez funciona bien).

Entonces, el punto que estás describiendo es no una "vulnerabilidad de Java". Más bien, es una fuente común de errores (algunos de los cuales son vulnerabilidades) que se pueden evitar gracias a las herramientas que proporciona Java. Sería más apropiado llamarlo "vulnerabilidad de C, con la que no necesita vivir si se desarrolla en Java".

(*) Eso no es del todo cierto: las instancias de cadena pueden se pueden modificar a través de la reflexión, aunque no de forma confiable y estándar. El acceso reflexivo a los campos privados es un permiso especial que el applet de Java no firmado no tiene, así que no se preocupe por esto.

    
respondido por el Thomas Pornin 23.09.2012 - 04:09
fuente
2

No creo que el código que publicaste se pueda explotar específicamente como una vulnerabilidad. Lo que publicaste es una práctica de programación razonable. Ese método "cambiador (ToyClass)" reasigna el valor del parámetro. Básicamente, puedes hacerlo desde cualquier lugar, como lo siguiente:

public class WhateverClass {

public static void changer(ToyClass aParameter) {
      aParameter.name = "Anything";
      aParameter.number = 99;
}
}

Y así llamando

WhateverClass.changer(anObject);

hará lo mismo que su código, aunque necesita cambiar el alcance del nombre y el número al paquete y no al privado. Pero esencialmente como lo veo, solo estás cambiando la variable de una clase específica. Sucede que ese método está dentro del objeto en cuestión y es estático.

No veo cómo alguien explotaría eso. Sería bueno tener a alguien que conozca los componentes internos de la VM para comentar.

    
respondido por el george_h 22.09.2012 - 11:07
fuente
1

Esto no es una vulnerabilidad en Java. Así es como Java está diseñado para funcionar.

En algunos casos, podría ser una vulnerabilidad en ToyClass, si el autor de este código no se diera cuenta de que estaba proporcionando la capacidad de cambiar instancias, pero en ese caso, el programador probablemente no sepa Java y debería No esté escribiendo código crítico para la seguridad en Java.

Por supuesto, si el programador no entiende el lenguaje de programación en el que está programando, ciertamente puede terminar con horribles vulnerabilidades, pero eso es cierto para todos los lenguajes. Si desea crear un código seguro, debe comenzar por entender sus herramientas.

Línea inferior: este es un aspecto bastante básico de Java. No veo nada sorprendente o particularmente peligroso para la seguridad aquí.

    
respondido por el D.W. 23.09.2012 - 02:34
fuente

Lea otras preguntas en las etiquetas