¿Reflection es una desventaja ya que las variables privadas no se pueden restringir?

14

El privatemodificador se usa para restringir el acceso fuera de la clase, pero al usar la reflexión, otras clases pueden acceder a métodos y campos privados. Así que me pregunto cómo podemos restringir la accesibilidad si es parte del requisito.

usuario245930
fuente
2
El código de baja confianza no puede usar la reflexión privada (al menos no en otros ensamblados, olvidé los detalles). El código de confianza completo simplemente puede usar punteros para evitar cualquier restricción dentro del proceso.
CodesInChaos
55
Los modificadores de acceso privado existen principalmente para decirles a los programadores que "no utilicen esto desde fuera de la clase, y si realmente lo hacen, no se quejen si la próxima versión rompe su código", no como una característica de seguridad estrictamente aplicada.
CodesInChaos
44
Los usuarios también pueden simplemente parchear su código para hacer lo que quieran. Con una excepción parcial para DRM (que no es lo suficientemente potente como para proporcionar protección duradera), cualquier persona que tenga acceso a su aplicación (binarios o código fuente) puede hacer cualquier cosa con ella.
Brian
66
¿No es esta una pregunta específica del idioma? La reflexión opera de manera diferente en diferentes idiomas. Me pregunto si esta pregunta debería tener una etiqueta para Java u otra cosa.
Wayne Conrad

Respuestas:

54

El propósito de los modificadores de acceso es informar a los desarrolladores que escriben código sobre cuál es la interfaz pública de una clase. No son de ninguna manera una medida de seguridad y, literalmente, no ocultan ni aseguran ninguna información.

JacquesB
fuente
33
Esto no es universalmente cierto. Citando a Eric Lippert , "Los modificadores de acceso en el CLR son características de seguridad. Las reglas de acceso están completamente combinadas con los sistemas de seguridad y seguridad de tipo". En C #, Reflection solo está disponible para el código que se ejecuta con plena confianza. Esto no se aplica (y no se puede) a los usuarios maliciosos del sistema que ejecutan el código. Sin embargo, se aplica a complementos maliciosos.
Brian
55
@Brian Cuando el problema que menciona Brian es relevante es cuando un sistema permite que se ejecute código de terceros sin confiar plenamente en él. Los ejemplos incluyen cajas de arena del navegador (por ejemplo, el applet muy odiado), el motor de aplicaciones de Google y Azure . Sería realmente estúpido para Azure permitir que el código no confiable explore los detalles de las bibliotecas principales de la plataforma.
JimmyJames
3
@Brian Eso no es 100% correcto: hay algunas operaciones de reflexión que puede hacer en código parcialmente confiable; simplemente no le permite hacer cosas como acceder a campos privados.
Luaan
1
@Brian Hasta que alguien encuentre una vulnerabilidad o ingeniería social que les permita evitar las restricciones. No tiene sentido tratar de usarlos de esa manera. Ese no es su propósito principal.
jpmc26
31

Para citar a Herb Sutter sobre los derechos de acceso a clases :

"El problema aquí es proteger contra Murphy frente a proteger contra Maquiavelo ... es decir, proteger contra el mal uso accidental (que el lenguaje hace muy bien) frente a proteger contra el abuso deliberado (que es efectivamente imposible). Al final, si un programador quiere lo suficiente como para subvertir el sistema, encontrará una manera "

Nemanja Trifunovic
fuente
2
No son momentos en los que necesita para caja de arena código no confiable, pero eso es una tarea de enormes proporciones. La protección contra el error (Murphy) es el caso mucho más común.
Paul Draper
#define private public(ignorando que en realidad es un comportamiento indefinido) y listo, tengo acceso completo desde el exterior a la parte restringida de sus clases.
bolov
La protección contra el abuso deliberado puede ser teóricamente imposible, pero es efectivamente posible, haciendo que el abuso sea lo suficientemente difícil como para que ocurra muy raramente. Es importante ser claro al respecto. De lo contrario, el software no podría utilizarse en absoluto en situaciones tales como dispositivos médicos críticos.
MarkJ
@MarkJ. El comentario de Herb Sutter es sobre el abuso deliberado por parte del desarrollador que escribió la clase en primer lugar y tal vez sus compañeros de equipo. No creo que haya una manera de prevenir ese tipo de abuso por las características del lenguaje.
Nemanja Trifunovic
@bolov ese truco depende del idioma, creo. Si bien los preprocesadores de C / C ++ probablemente le permitirían salirse con la suya, cualquier cosa sin ellos probablemente daría un error de "no se pueden usar palabras reservadas en un #define".
Dan está jugando con Firelight el
10

No, esto es realmente una ventaja importante. Simplemente porque algún desarrollador no consideró que alguien necesitaría acceso a algún estado interno no significa que nunca se presente un caso de uso legítimo. En estos casos, usar Reflection para realizar una cirugía en un objeto puede ser el último recurso. He tenido que usar esta técnica más de una vez.

Mason Wheeler
fuente
1
En otras palabras, es una forma de eludir una API probablemente rota, ya sea debido a requisitos incompletos o una implementación incompleta.
Vuelva a instalar Mónica
4

Restringe aún más la accesibilidad al subir un nivel más: el entorno de ejecución.

No todos los idiomas tienen este concepto, pero al menos con Java puede usar un administrador de seguridad que prohíbe hacer accesibles los campos privados. Puede instalar manualmente el administrador de seguridad en tiempo de ejecución o agregar una política de seguridad en un archivo jar que luego se sella para evitar modificaciones.

Más información sobre cómo hacer esto en Java: Reflection Security

Comunidad
fuente
3

¿De qué reflexión estás hablando?

En muchos sistemas de reflexión, eludir la encapsulación es una capacidad explícita que su código necesita obtener, y no tiene por defecto.

Si le preocupa la encapsulación, la solución simple es simplemente no usar un sistema de reflexión que no lo conserve.

Jörg W Mittag
fuente
3

En Python, no hay modificadores de acceso. La convención es prefijar con un guión bajo los métodos y variables a los que no se espera acceder desde fuera de la clase. ¿Te impide técnicamente acceder a dicho campo desde una clase de terceros? De ningún modo; pero si lo hace, está solo y corre el riesgo de romper algo, sin poder culpar a la otra clase.

En C #, los modificadores de acceso existen, pero todavía son solo una convención, una que es aplicada por un compilador, pero sigue siendo una convención. Esto significa que técnicamente, todavía se puede acceder y cambiar variables privadas, ya sea a través de Reflection o alterando directamente la memoria (como hacen los entrenadores de juegos ). La consecuencia es exactamente la misma: si las variables de su clase se cambian a través de Reflection de otra clase, o mediante la manipulación de la memoria por otra aplicación, y se rompe algo en su clase, no es su culpa.

Tenga en cuenta que esto, obviamente, crea problemas de seguridad en los que un tercero puede acceder a sus datos; algo que conduce a variantes encriptadas de una cadena y estructuras de datos similares. Pero proteger su código de dicho uso es un sistema operativo más relacionado y restricciones de acceso a nivel de código , y no tiene nada que ver con Reflection per se.

Arseni Mourzenko
fuente
2
Tenga en cuenta que en C #, solo el código totalmente confiable puede reflejar miembros privados. Escribir directamente en la memoria de proceso aún funciona, pero es más difícil que en el código nativo.
Luaan