The Information Systems and Computer Applications examination covers material that is usually taught in an introductory college-level business information systems course.

Archive for January 18, 2013

Deserializando objetos Java sin los .class by Pablo M.

En una auditoría que llevamos a cabo recientemente, surgió la necesidad de inspeccionar el contenido de ciertos ficheros en formato binario, que a todas luces se trataba de objetos Java serializados:

$ file serialized.bin
serialized.bin: Java serialization data, version 5

En efecto, los dos primeros bytes eran el magic number de este tipo de ficheros:

0000000 edac 0500 ...
0000010 ...
0000020 ...
0000030 ...
0000040 ...

pero los objetos serializados debían ser relativamente complejos, por lo que un merostrings sobre el fichero no nos ayudaba a “descifrar” la información.

Lo primero que intentamos fue su deserializado directamente mediante la API estándar de Java ObjectInputStream.readObject():

import java.io.*;

class Deserialize {
    public static void main(String[] args) throws Exception {
        FileInputStream fis = new FileInputStream("serialized.bin");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object object = (Object) ois.readObject();
        ois.close();
    }
}

Sin embargo, como enseguida pudimos comprobar, este método requiere que las clases a partir de las cuáles se han instanciado los objetos serializados estén presentes en elCLASSPATH de la JVM para poder llevar a cabo la correspondiente deserialización:

$ java Deserialize
Exception in thread "main" java.lang.ClassNotFoundException: CENSURADO ;-)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
[...]

En efecto, si tomamos una clase de prueba:

class Account implements Serializable {
    private String user;
    private String password;

    public String getUser() {
        return this.user;
    }
    public void setUser(String user) {
        this.user = user;
    }

[...]

    public Account(String user, String password) {
        setUser(user);
        setPassword(password);
    }
}

y generamos un fichero con su serialización:

import java.io.*;

class Serialize {
    public static void main(String[] args) throws Exception {
        Account account = new Account("pablo", "secreto");
        FileOutputStream fos = new FileOutputStream("serialized.bin");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(account);
        oos.flush();
        oos.close();
    }
}

no podremos deserializarlo con readObject() si no tenemos la clase Account en elCLASSPATH:

$ java Deserialize
Exception in thread "main" java.lang.ClassNotFoundException: Account
	at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
	at java.security.AccessController.doPrivileged(Native Method)
[...]
$ ls ../serialize
Account.class  Account.java  Serialize.class  serialized.bin  Serialize.java
$ CLASSPATH=.:../serialize java Deserialize
...

Lo usual, cuando estamos auditando por ejemplo applets o aplicaciones Android, es disponer de los .jar y .class correspondientes a los objetos serializados, por lo que sí que seríamos capaces de deserializarlos, además de obtener el bytecode de sus clases asociadas con decompiladores como JAD, Jdec, y muchos otros… Esto nos facilitaría en gran medida el análisis.

Sin embargo, en este caso tan sólo disponíamos de los ficheros, y en principio no había nada que hacer. Pero la información estaba ahí; un strings sobre nuestro fichero serializado de pruebas mostraba perfectamente los nombres de las clases, los campos y sus tipos:

$ strings serialized.bin
Account
passwordt
Ljava/lang/String;L
userq
secretot
pablo

Tras buscar un poco, dimos con una de las conferencias de la BlackHat EU 2010, Attacking Java Serialized Communication, de Manish Saindane, y el plugin DSer para Burp Suite, que permite manipular objetos Java serializados presentes en peticiones HTTP. Sin embargo, según nuestras pruebas (y algún comentario del autor) esta herramienta también necesita que las clases correspondientes estén presentes en su directorio de librerías (¿alguno de nuestros lectores ha conseguido hacerla funcionar sin las clases?).

Escarbando en la documentación de Java al respecto, confirmamos nuestra creencia de que la información necesaria para llevar a cabo la deserialización está presente en los ficheros, y cuando estábamos a punto de escribir nuestro propio parser en Python según la especificación, ¡por fin! dimos con la herramienta: jdeserialize (lo peor de todo es que habíamos buscado por “java deserialization”, “java serialization decompile”, etc. pero no probamos lo jobvio 😉

El uso de la herramienta es harto sencillo, está escrita en Java puro, y además no tiene dependencias más allá de las librerías estándar. Aplicada a nuestro objeto Account de prueba, ésta es la salida que arroja:

$ java -jar jdeserialize-1.2.jar serialized.bin
read: Account _h0x7e0002 = r_0x7e0000;
//// BEGIN stream content output
Account _h0x7e0002 = r_0x7e0000;
//// END stream content output

//// BEGIN class declarations (excluding array classes)
class Account implements java.io.Serializable {
    java.lang.String password;
    java.lang.String user;
}

//// END class declarations

//// BEGIN instance dump
[instance 0x7e0002: 0x7e0000/Account
  field data:
    0x7e0000/Account:
        user: r0x7e0004: [String 0x7e0004: "pablo"]
        password: r0x7e0003: [String 0x7e0003: "secreto"]
]
//// END instance dump

Como se observa, indica la estructura de las clases, con los respectivos tipos, y la información contenida en las instancias serializadas. Su utilidad se aprecia mejor si se aplica sobre clases con estructuras algo más complicadas. Por ejemplo, si los objetos serializados fueran instancias de esta clase, que contiene una lista enlazada de objetos Account:

import java.io.*;
import java.util.*;

class Accounts implements Serializable {
    private LinkedList accounts =
        new LinkedList();

    public void addAccount(Account account) {
        this.accounts.add(account);
    }
}

Si serializamos varios objetos:

import java.io.*;

class Serialize {
    public static void main(String[] args) throws Exception {
        Accounts accounts = new Accounts();
        accounts.addAccount(new Account("62774889", "aqdauw)ZLCz:"));
        accounts.addAccount(new Account("23354642", "Jf!<Tkc9LWSC"));
        accounts.addAccount(new Account("98388213", "{rp9r[C4WY@u"));
        accounts.addAccount(new Account("75627389", "b54KXH)Uh)Z!"));
        FileOutputStream fos = new FileOutputStream("serialized2.bin");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(accounts);
        oos.flush();
        oos.close();
    }
}

un strings empieza a ser un poco más difícil de interpretar (pese a que el nombre de los campos, user y password, es totalmente revelador; en nuestro caso los campos no tenían nombres tan “sugerentes” ;-):

$ strings serialized2.bin
Accountsw#E7!Y
accountst
Ljava/util/LinkedList;xpsr
java.util.LinkedList
)S]J`
Account
passwordt
Ljava/lang/String;L
userq
aqdauw)ZLCz:t
62774889sq
Jf!<Tkc9LWSCt
23354642sq
{rp9r[C4WY@ut
98388213sq
b54KXH)Uh)Z!t
75627389x

mientras que jdeserialize nos facilitaría en gran medida la ingeniería inversa:

$ java -jar jdeserialize-1.2.jar serialized2.bin
read: Accounts _h0x7e0002 = r_0x7e0000;
//// BEGIN stream content output
Accounts _h0x7e0002 = r_0x7e0000;
//// END stream content output

//// BEGIN class declarations (excluding array classes)
class Account implements java.io.Serializable {
    java.lang.String password;
    java.lang.String user;
}

class java.util.LinkedList implements java.io.Serializable {
}

class Accounts implements java.io.Serializable {
    java.util.LinkedList accounts;
}

//// END class declarations

//// BEGIN instance dump
[instance 0x7e0010: 0x7e0005/Account
  field data:
    0x7e0005/Account:
        user: r0x7e0012: [String 0x7e0012: "75627389"]
        password: r0x7e0011: [String 0x7e0011: "b54KXH)Uh)Z!"]
]
[instance 0x7e0007: 0x7e0005/Account
  field data:
    0x7e0005/Account:
        user: r0x7e0009: [String 0x7e0009: "62774889"]
        password: r0x7e0008: [String 0x7e0008: "aqdauw)ZLCz:"]
]
[instance 0x7e0004: 0x7e0003/java.util.LinkedList
  object annotations:
    java.util.LinkedList
        [blockdata 0x00: 4 bytes]
        Account _h0x7e0007 = r_0x7e0005;
        Account _h0x7e000a = r_0x7e0005;
        Account _h0x7e000d = r_0x7e0005;
        Account _h0x7e0010 = r_0x7e0005;  

  field data:
    0x7e0003/java.util.LinkedList:
]
[instance 0x7e0002: 0x7e0000/Accounts
  field data:
    0x7e0000/Accounts:
        accounts: r0x7e0004: java.util.LinkedList _h0x7e0004 = r_0x7e0003;
]
[instance 0x7e000d: 0x7e0005/Account
  field data:
    0x7e0005/Account:
        user: r0x7e000f: [String 0x7e000f: "98388213"]
        password: r0x7e000e: [String 0x7e000e: "{rp9r[C4WY@u"]
]
[instance 0x7e000a: 0x7e0005/Account
  field data:
    0x7e0005/Account:
        user: r0x7e000c: [String 0x7e000c: "23354642"]
        password: r0x7e000b: [String 0x7e000b: "Jf!<Tkc9LWSC"]
]
//// END instance dump

Esperamos que el post os haya resultado ameno, y que como mínimo la información os ahorre el proceso de búsqueda y pruebas hasta dar con la herramienta adecuada si os veis en la misma situación. Y por supuesto, si conoceis alguna otra forma (que seguro que la hay), os animamos a que la compartais con nosotros y el resto de lectores.

 


Apple ofrece el MacBook Pro Retina de 15 pulgadas con un 15% de descuento by Nacho

macbook retina refurbished Apple ofrece el MacBook Pro Retina de 15 pulgadas con un 15% de descuento

El MacBook Pro con Retina Display es una pieza de hardware que muy pocos se pueden permitir por su alto precio, afortunadamente, la sección de refurbished siempre nos trae pequeñas rebajas que en un producto tan caro, se transforman en grandes rebajas.

Por un precio de 2699 euros, te puedes llevar a casa un equipo con las siguientes prestaciones:

  • Pantalla Retina de 15,4 pulgadas (en diagonal); resolución de 2.880 por 1.800 con 220 píxeles por pulgada
  • 16 GB de SDRAM DDR3L a 1.600 MHz
  • 512 GB de almacenamiento flash
  • Cámara FaceTime HD a 720p
  • GeForce GT 650M de NVIDIA con 1 GB de memoria GDDR5

Ese equipo configurado a través de la Apple Store, costaría un total de 3179 euros por lo que el ahorro es de 480 euros. Los equipos refurbished no ofrecen ningún tipo de carencia con respecto al original aunque la caja que lo contiene sí suele ser diferente pero no se puede tener todo.

Si tienes acceso a los productos de la Apple Store de Estados Unidos, también hay el mismo descuento aplicado para el MacBook Pro con Retina Display de 13 pulgadas. Si estabas pensando en adquirir uno de estos dos modelos de MacBook Pro, quizás te animes ahora que puedes ahorrar algo de dinero.

Más información – Colors, el anuncio de Apple para el MacBook Pro Retina de 13 pulgadas
Enlace – MacBook Pro Retina de 15 Pulgadas Refurbished

El artículo Apple ofrece el MacBook Pro Retina de 15 pulgadas con un 15% de descuento ha sido originalmente publicado en Soy de Mac.