Referencias Directas Inseguras a Objetos


Las Referencias Directas Inseguras a Objetos (también conocidas como IDOR) ocurren cuando es posible obtener acceso directo a diferentes objetos de datos dentro de una aplicación web que están expuestos a los usuarios. Como resultado de esta vulnerabilidad, es posible que los atacantes potenciales omitan la autorización o accedan a datos como archivos o registros de bases de datos en el sistema directamente. Esto se puede hacer modificando el valor de un parámetro utilizado para apuntar directamente a un objeto. Esto se debe al hecho de que la aplicación web toma los datos de entrada proporcionados por el usuario y los usa para recuperar un objeto sin realizar verificaciones de autorización.

Ejemplo con el objeto sin cambios para el usuario Peter Parker: Ejemplo IDOR

Ejemplo con el objeto cambiado para ver la información de la cuenta de administrador (en este ejemplo, el valor del parámetro acct se ha cambiado de peterparker a admin). Si no se requiere autorización adicional del usuario, tenemos una violación de seguridad: IDOR ejemplo cambiado

¿Por qué debería importarme esto?

IDOR ha jugado un papel importante en grandes violaciones de seguridad y escándalos en todo el mundo. Algunos casos que vale la pena mencionar son:

¿Cómo pruebo IDOR?

Una buena manera de probar IDOR es tener primero 2 o más usuarios que tengan acceso a diferentes objetos en el mismo sitio web. Primeramente, ambos usuarios deben iniciar sesión. Luego, un usuario debe modificar el valor del parámetro utilizado para hacer referencia a los objetos para que sea el mismo que el del otro usuario. Si es capaz de recuperar el objeto que solo el otro usuario debería ver, entonces IDOR está presente. La razón para tener más de un usuario es que ahorra mucho tiempo al no adivinar los valores de los objetos a probar.

¿Qué puede hacer alguien con Referencias Directas Inseguras a Objetos?

Las Referencias Directas Inseguras a Objetos son muy fáciles de explotar y, por eso, es muy probable que se abuse de ellas. Por supuesto, esto también varía, ya que no siempre es obvio cómo enumerar los enlaces para los archivos.

Algunos ejemplos…

El valor de un parámetro se puede usar directamente para recuperar un registro de base de datos. En el ejemplo, 1337 es la clave de la entrada de la base de datos y el cambio que podría mostrar otra entrada en la base de datos. Esto podría revelar información confidencial que no debería ser accesible para el usuario. https://www.example.com/somepage?receipt=1337


El valor de un parámetro se puede usar directamente para acceder a la funcionalidad de la aplicación. En el ejemplo, 4 podría ser una vista del perfil de usuario normal. Cambiar eso a otro número podría dar como resultado el acceso a una vista de perfil de administradores o alguna otra vista que debería estar restringida. https://www.example.com/accessPage?menuitem=4


El valor de un parámetro se puede usar directamente para recuperar un recurso del sistema de archivos (como Path Traversal). En el ejemplo, img056.png es el nombre del archivo de imagen que se abre. Cambiar ese valor podría resultar en obtener acceso a otras imágenes o, peor aún, a otros archivos en el sistema.

https://www.example.com/showImage?img=images/img056.png


El valor de un parámetro se puede usar directamente para realizar una operación en el sistema. En el ejemplo, bob es el usuario cuya contraseña se va a cambiar. Cambiar el nombre de usuario podría resultar en el cambio de la contraseña de otro usuario. A menos que Bob sea administrador, estoy bastante seguro de que no se le permite hacer eso.

https://www.example.com/changepassword?user=bob

¿Qué sucede detrás del telón?

Tomemos el primer ejemplo donde se muestra un recibo al usuario. Lo que sucede en segundo plano es que se selecciona una entrada de base de datos utilizando la clave de base de datos receipt_id. Si el parámetro del recibo se cambia, por ejemplo, a 855 en la URL, este obtendrá la información del recibo que tiene el receipt_id 855. Si la autorización no se verifica, el usuario puede acceder a cualquier recibo, en lugar de solo el recibo del usuario correspondiente.

Ejemplo:

// the database query which selects a row from the 'receipt' table where all the receipts are located
String query = "SELECT * FROM receipts WHERE receipt_id = ?"; 

// creates a prepared statement from that database query
PreparedStatement pstmt = connection.prepareStatement(query , … );

// sets the value for the placeholder
// this is where the user can manipulate the input from the URL to view other receipts
pstmt.setString( 1, request.getParameter("receipt"));

// executes the query
ResultSet results = pstmt.executeQuery( );

¿Cómo evito esto en mi código?

Hay varias formas de evitar que los usuarios accedan a referencias directas a objetos.

  • Implementar un esquema de autorización en la aplicación que mantenga el control sobre qué información está autorizado a ver un usuario.
  • Utilizar referencias de objetos difíciles de adivinar, como por ejemplo usar las UUID en lugar de ID autoincrementales.
  • No exponer claves internas o identificadores. No usar listados de directorio ni permitir el acceso directo a objetos de datos.
  • Utilizar referencias de objeto indirecto por usuario o sesión o implementar mapeo de referencias.

¿Entonces, en conclusión?

IDOR todavía está muy extendido porque es muy fácil olvidarse de agregar código de autorización a todos los lugares donde se accede a los objetos, que son visibles para los usuarios. Dado que explotar IDOR generalmente es solo manipular la URL de una página web para obtener datos que no están destinados a todos. Para evitar IDOR, debes aplicar el control de acceso a tu código.

Roland Kaur