Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Herramientas/GitHubGitHub/tc39/proposal-symbol-proto
Vulnerability AnalysisWeb SecurityPapers & ResearchLearning & Education
GitHubtc39/proposal-symbol-proto

proposal-symbol-proto

TC39 proposal for mitigating prototype pollution

Ver Repositorio
532hace 2 añosRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Mitigación de la contaminación de prototipos / Symbol.proto

Autores: Santiago Díaz (Google)

Champion: Shu-yu Guo (Google)

Etapa: 1

Índice

  • Descripción del problema
    • Acción fantasmagórica a distancia
    • Ataques solo de datos
  • Problemas con freeze, seal y preventExtensions
    • El error de sobrescritura
    • Granularidad gruesa
    • Puntos de congelación
    • Tipos de aplicación
  • Solución propuesta
    • Proporcionar APIs de reflexión
    • Característica de adopción voluntaria
      • Refactorización automática
    • ¿Qué significa eliminar?
  • Bases de código incompatibles
  • Apéndice
    • ¿Qué hay de la contaminación de constructores?
    • Acceso computado en JS minimizado
    • Ejemplos de vulnerabilidades

tl;dr

Esta propuesta busca mitigar una vulnerabilidad a nivel de lenguaje conocida como contaminación de prototipos con un mecanismo que complementa las primitivas de congelación y un mecanismo para hacer que la mayoría de las bases de código sean compatibles con él. Describe una característica de adopción voluntaria que hace que los prototipos estén disponibles únicamente a través de APIs de reflexión. Al hacerlo, la sentencia obj[key] ya no puede acceder a los prototipos. Las bases de código compatibles con esta característica son más intencionales en la forma en que usan los prototipos.

Descripción del problema

Acción fantasmagórica a distancia

Las vulnerabilidades de PP permiten a los atacantes manipular objetos que no controlan o a los que no tienen acceso en tiempo de ejecución. Esta primitiva de 'acción fantasmagórica a distancia' puede utilizarse para cambiar la forma de otros objetos y sobrescribir sus propiedades, contaminando así objetos en el tiempo de ejecución.

Los objetos contaminados invalidan las suposiciones subyacentes del código que de otro modo sería seguro/correcto y pueden conducir a la ejecución arbitraria de código y a una amplia gama de otros problemas de seguridad en bases de código JS. Los errores de contaminación de prototipos se manifiestan a menudo en aplicaciones web, pero también afectan a los tiempos de ejecución JS no web.

Las propiedades de los objetos en JS pueden ser escritas por cualquier código que pueda hacer referencia a ellas. En particular, si muchos objetos dependen de una propiedad compartida, cualquiera de ellos puede realizar cambios en todos los demás.

Ataques solo de datos

Una propiedad especial de PP es que se trata de un ataque solo de datos, que permite lograr la ejecución de código puramente a través de datos. Por ejemplo, véase el siguiente código vulnerable y un exploit correspondiente:

root@kitploit:~
// source is attacker-controlled
function merge(target, source) {
  for (let key in source) {
    if (typeof source[key] === 'object')  {
      if(target[key] === undefined) {
        target[key] = {};
      }
      target[key] = merge(target[key], source[key]);
    } else {
      target[key] = source[key];
    }
  }
  return target;
}

// User input comes as a string
const userSuppliedObj = JSON.parse('{"__proto__": {"polluted": true}}');
// Trigger prototype pollution
merge({}, userSuppliedObj);
// Create a brand new object
const newObj = {};
// Has polluted property
console.log(newObj.polluted); // true

Tenga en cuenta que el exploit es capaz de contaminar la creación de nuevos objetos sin inyectar ningún código externo.

Debido a esta propiedad especial, las mitigaciones modernas contra problemas de ejecución de código —como la Content Security Policy o Trusted Types— se quedan cortas a la hora de proteger contra PP, ya que se centran en hacer cumplir la procedencia del código.

Nótese que los ataques solo de datos son relevantes en situaciones donde el código que se ejecuta en la VM es de confianza y la ejecución arbitraria de código tiene impacto en la seguridad.

Problemas con freeze, seal y preventExtensions

Las primitivas de congelación existentes sufren problemas de diseño significativos que hacen poco probable su adopción generalizada. Pueden ser útiles para usuarios expertos, pero no son adecuadas para ser implementadas por la mayoría de los desarrolladores, quienes razonablemente esperan que los prototipos sean mutables:

El error de sobrescritura

Las APIs de congelación sufren el error de sobrescritura y otras inconsistencias que introducen errores en bases de código existentes, haciendo que lancen excepciones o, peor aún, fallen silenciosamente en modo no estricto (sloppy mode). Una investigación anterior del error de sobrescritura concluyó que este se activa en ~10% de las bases de código en modo estricto y en 20% en modo no estricto. La investigación se abandonó poco después.

Granularidad gruesa

Las APIs de congelación otorgan a los desarrolladores la pesada responsabilidad de saber qué prototipos deben congelarse para mantener una base de código segura, asumiendo que los desarrolladores son expertos en seguridad. Estas APIs describen el qué pero no el cómo de la seguridad. Congelar Object ciertamente no es suficiente, ya que muchos exploits abusan de Array. ¿Qué pasa con Error, Date, Reflect o Proxy? ¿O con los futuros tipos integrados? Las APIs de congelación no ofrecen respuestas a estas preguntas.

Puntos de congelación

Las APIs de congelación asumen un punto de congelación estable: un momento fijo en tiempo de ejecución en el que los prototipos se han asentado y pueden congelarse. En la práctica, este punto es volátil y cambia con el tiempo en bases de código que se desarrollan activamente. Aunque hoy se puede encontrar ese punto en muchas aplicaciones, la incorporación de nuevas dependencias, polyfills, cambios en la estructura del código y funciones avanzadas como el hotswap y las herramientas de desarrollo convierten los puntos de congelación en un objetivo móvil.

Tipos de aplicación

Las APIs de congelación no pueden proteger la cadena de prototipos completa. En JS, los objetos pueden añadirse o eliminarse de la cadena de prototipos en cualquier momento. Para proteger toda la cadena, siempre hay que recordar congelar los objetos que se añaden a la cadena, un proceso propenso a errores. Cuando se eliminan de la cadena, ya no se pueden descongelar.

Solución propuesta

En pocas palabras: una característica que expone los prototipos únicamente a las APIs de reflexión. Si los prototipos no estuvieran disponibles a través de propiedades como __proto__ o prototype, no estarían expuestos a los problemas solo de datos.

Esto se entiende mejor con un ejemplo: la sentencia obj[one][two] = value es vulnerable a PP a través de obj.__proto__.polluted. Si se elimina la propiedad Object.prototype.__proto__, la misma sentencia ya no es vulnerable porque no puede hacer uso de la única otra forma de llegar a los prototipos, que es obj.constructor.prototype.polluted. Nótese que prototype no puede eliminarse.

Esta propuesta puede implementarse proporcionando APIs de reflexión y creando una nueva característica de encapsulación de adopción voluntaria que elimina las propiedades de prototipo. A continuación se describe cada paso.

Proporcionar APIs de reflexión

__proto__ es un nombre de propiedad heredado que puede eliminarse, pero el slot interno que hay detrás todavía puede leerse mediante Object/Reflect.getPrototypeOf y escribirse mediante Object/Reflect.setPrototypeOf, que simplemente seguirán haciendo que esta propiedad sea accesible para el código que ya está en ejecución.

Proponemos la creación de nuevas APIs para prototype, por ejemplo getClassPrototypeOf y setClassPrototypeOf, que permitirían eliminar este nombre de propiedad sin cambiar en nada la forma en que esta propiedad especial funciona y es compatible con la VM.

Las APIs de reflexión pueden tener polyfills, lo que permite que las bases de código endurecidas funcionen en todos los navegadores, incluidas las versiones antiguas.

Característica de adopción voluntaria

Una nueva 'característica de encapsulación' de adopción voluntaria en la que no se crean nombres de propiedad para las funciones getter y setter de los slots de prototipo, lo cual ahora es posible porque las referencias a esas propiedades pueden utilizar en su lugar las APIs de reflexión.

La característica se habilita mediante un flag fuera de banda:

  • En contextos de navegador, mediante una cabecera HTTP como X-Encapsulate-Prototype: true
  • En otros contextos, mediante un flag de funcionalidad como --encapsulate-prototype

Cuando la encapsulación está deshabilitada, los prototipos están disponibles tanto a través de propiedades como de APIs de reflexión.

Cuando la encapsulación está habilitada, los prototipos solo están disponibles a través de APIs de reflexión, habiendo eliminado tanto __proto__ como prototype.

La encapsulación también incluye la siguiente refactorización automática:

Refactorización automática

Cuando la encapsulación está habilitada, los motores JS que cargan nuevo código fuente activan un paso adicional en sus fases de parseo que registra toda notación de punto a propiedades de prototipo como si fueran llamadas a sus APIs de reflexión. Este paso puede implementarse de forma eficiente y permite que las bases de código con dependencias de terceros, transitivas o cargadas dinámicamente sean compatibles con la encapsulación.

En el futuro, este cambio allanará el camino para marcar prototype como obsoleto.

¿Qué significa eliminar?

Las propiedades de prototipo podrían simplemente ser undefined cuando la encapsulación está habilitada, pero podrían lanzar un error cuando se intente leerlas o escribirlas. Esto significaría fallar más rápido y de forma ruidosa y permitiría probar las migraciones a las APIs de reflexión/encapsulación.

Esto implica hacer que los getters y setters de __proto__ y prototype sean condicionales a la encapsulación, mediante un host hook, de la misma manera que la función eval lanza una excepción bajo la Content Security Policy.

Bases de código incompatibles

El código que depende del acceso computado a propiedades para hacer referencia a prototipos no es compatible con la encapsulación ni con la refactorización automática. Debe refactorizarse para referirse explícitamente a los prototipos cuando se utilicen. Esta refactorización en realidad hace que el código exprese su intención, lo que hace visibles los patrones peligrosos para el análisis estático. En la práctica, las bases de código con esta característica suelen ser frameworks de reflexión, herramientas de depuración y otros casos de uso intensivos en reflexión que probablemente ya son conscientes de cómo usan los prototipos.

Las bases de código que utilizan la palabra prototype para definir propiedades personalizadas no son compatibles. Estas bases de código pueden hacerse compatibles con la encapsulación si esta propiedad se establece/obtiene siempre mediante notación de corchetes. Históricamente y según las consultas al HTTP Archive, hay un pequeño porcentaje de bases de código que son incompatibles por esta razón.

Apéndice

¿Qué hay de la contaminación de constructores?

Algunos cambios en la propiedad constructor también pueden tener acción fantasmagórica a distancia. Durante nuestra investigación, no hemos encontrado vulnerabilidades prácticas afectadas por esto.

El listón es bastante alto para que este ataque funcione: al igual que en PP, se debe encontrar una aplicación con gadgets para escribir y leer propiedades arbitrarias. Pero en la contaminación de constructores, el gadget de lectura debe leer de constructor.polluted en lugar de polluted. Esto reduce drásticamente el número de gadgets útiles.

Acceso computado en JS minimizado

Parte del JS minimizado puede ser incompatible con el modo de encapsulación, porque el acceso estático a propiedades podría ser minificado a acceso computado. Hemos consultado el HTTP Archive para obtener una estimación de esto en la práctica. La siguiente tabla muestra que las páginas con este comportamiento se mantienen constantemente por debajo del 1% durante los últimos 12 meses en todas las páginas rastreadas con un navegador de escritorio:

Ejemplos de vulnerabilidades

Google ha observado una tendencia al alza en los errores enviados a nuestro Programa de Recompensas por Vulnerabilidades: 1 en 2020, 3 en 2021 y 5 hasta ahora en 2022. Hemos identificado varios más en nuestra investigación interna.

Los ejemplos de vulnerabilidades incluyen:

  1. En la web: Varios problemas de XSS en servicios que deberían haber estado protegidos porque utilizan Strict CSP. Y una amplia gama de librerías vulnerables conocidas.
  2. En el escritorio: Un error en una aplicación de escritorio propiedad de Google donde los usuarios podían recibir un objeto JSON malicioso que podía permitir la filtración de archivos locales debido a una vulnerabilidad de contaminación. (Actualmente no público, divulgación por determinar.)
  3. En características de seguridad: Múltiples bypass en sanitizadores, incluyendo la API Sanitizer de Chrome, DOMPurify y el sanitizador de Closure.
  4. En el navegador: Un escape del sandbox de Firefox que conduce a la ejecución remota de código.
  5. En NodeJS: Se han descubierto varios RCEs.

Esperamos que el número de aplicaciones vulnerables crezca a medida que las aplicaciones JavaScript se desplieguen en más entornos (por ejemplo, Electron, Cloudflare Workers, etc.). Por lo tanto, se requiere una solución a nivel de lenguaje para mitigar los ataques en todos los entornos.

Descargar herramienta
TablaDocumentos que acceden dinámicamente a __proto__ o constructorNúmero total de documentos rastreadosProporción
2023_03_01_desktop5,407,936609,469,4580.89%
2023_02_01_desktop4,842,383549,089,7080.88%
2023_01_01_desktop5,283,826589,519,1600.90%
2022_12_01_desktop5,161,471577,073,8830.89%
2022_11_01_desktop5,023,169561,726,2390.89%
2022_10_01_desktop4,393,377476,880,6240.92%
2022_09_01_desktop4,239,257466,278,7620.91%
2022_08_01_desktop4,259,814463,784,0470.92%
2022_07_01_desktop3,011,137339,468,6150.89%
2022_06_01_desktop2,301,317257,501,2220.89%
2022_04_01_desktop2,368,577263,144,6570.90%
2022_03_01_desktop2,319,518259,249,0130.89%