Búsqueda de sitios web

javascript - Cómo proteger las variables globales (window) de ser sobrescritas


Actualmente estoy trabajando en un proyecto donde la seguridad es muy importante. Por defecto, todas las variables/propiedades globales como Promise o incluso crypto pueden ser sobrescritas.

¿Hay alguna manera de protegerlos para que no sean sobrescritos?

Ejemplo :

window.crypto.getRandomValues = () => { return [1] }

window.crypto.getRandomValues(new Uint32Array(1))[0] // 1

Mi primer pensamiento fue usar Object.freeze() para bloquear el objeto, pero uno puede simplemente sobrescribir el método Object.freeze para que no haga nada.

Ya somos muy selectivos con las dependencias que usamos, pero todavía me gustaría asegurarme de que esas variables no puedan ser sobrescritas. O al menos detectar si fueron sobrescritas.

Respuesta #1

Descargo de responsabilidad: Todo esto es solo un esquema aproximado, no ha sido probado a fondo. Estoy seguro de que hay más problemas por resolver.

Congelar el objeto window no es una opción, esto solo causaría problemas, pero ¿quizás objetos como window.crypto?

Pero puedes redefinir propiedades para que ya no sean modificables, incluso en el objeto window

function freezeProp(target, propertyName) {
  const { value, get = () => value, set = () => void 0, ...desc } = Object.getOwnPropertyDescriptor(target, propertyName);
  Object.defineProperty(target, propertyName, { ...desc, get, set, configurable: false });
}

freezeProp(window, "crypto");

Pero estos métodos solo funcionan si puedes asegurarte de que eres el primer script en ejecutarse.

Detectar si algunos métodos han sido cambiados también es posible solo si tienes una referencia a ellos; y volvemos a ser el primer script en ejecutarse.

Pero si no estás seguro de si el ámbito global ha sido estropeado, ¿por qué no conseguir un objeto window nuevo?

window.crypto.getRandomValues = () => {
  return [1]
};

const secure = (() => {
  let iframe = document.createElement("iframe");
  document.body.appendChild(iframe);
  const contentWindow = iframe.contentWindow;
  document.body.removeChild(iframe);
  return contentWindow;
})();

var a = window.crypto.getRandomValues(new Uint8Array(1));
console.log(a);

var b = secure.crypto.getRandomValues(new Uint8Array(1));
console.log(b);