En los viejos tiempos, cuando el desarrollo web se basaba en el hecho de que las aplicaciones del servidor enviaban solicitudes a bases de datos relacionales y emitían salida HTML, a menudo se encontraba este código:
o tal:
Desde entonces, hemos aprendido a usar enfoques más seguros.
Se utilizan ampliamente herramientas como motores de plantillas y enlace de parámetros. Hoy en día es raro encontrar una concatenación de cuerdas peligrosa.
En este artículo, me gustaría compartir mis pensamientos sobre los ataques mediante la inyección de código. Aparentemente, siguen siendo una amenaza en JavaScript.

Para entender por qué, dividimos uno de los ejemplos fallidos en fragmentos más simples. Así:
function f(userInput: A): A { const firstCommand: A = ...; const secondCommand: A = ...; return firstCommand.concat(userInput.concat(secondCommand)); }
¡Obviamente, la
causa raíz de los ataques al implementar el código es que no hay diferencia para una computadora entre un comando y la entrada del usuario! Por lo tanto, un atacante puede ingresar datos que luego se procesarán como código.Naturalmente, como dije, hay defensas bien conocidas contra tales ataques. En lugar de esto:
"SELECT name FROM users WHERE login = \"" + login + "\""
mejor escribir algo como esto:
query("SELECT name FROM users WHERE login = :login", {login})
Por lo tanto, el
SELECT name FROM users WHERE login =:login
comando de
SELECT name FROM users WHERE login =:login
está claramente separado de los datos de
{login}
. Al mismo tiempo, los mecanismos internos aseguran que los datos estén preparados para su uso en una consulta SQL. Fallarán las comillas y la inyección de código malicioso.
Sin embargo, el desarrollo de aplicaciones web está en auge. No solo esto se encuentra cada vez más:
{ paramA: "the value of the A parameter", paramB: "the value of the A parameter", }
pero también esto:
{ paramA: "the value of the A parameter", paramB: {$in: [ "the value of the B parameter", "the value of the C parameter", ]}, }
¡Una diferencia significativa entre las dos opciones es que el valor del parámetro es un objeto que incluye un comando!
Digamos que los valores se leen desde
userInput
:
{ paramA: userInput.paramA, paramB: {$in: [ userInput.paramB[0], userInput.paramB[1], ]}, }
No hay necesidad de preocuparse por el usuario que proporciona una cadena maliciosa. Todo se manejará de manera segura.
El problema es que los valores de los parámetros pueden ser no solo valores simples como
the value of the A parameter
, sino también comandos, por ejemplo
{$in: ["B", "C"]}
. El usuario puede enviar una solicitud de varias maneras, después del descifrado del cual se obtiene un objeto (formulario, JSON o XML), y por lo tanto, el código puede ser atacado por inyección.
Suponga que
userInput.paramA
es
{$empty: false}
. Entonces la consulta es la siguiente:
{ paramA: {$empty: false}, paramB: {$in: [ userInput.paramB[0], userInput.paramB[1], ]}, }
Nuevamente, resulta que para una computadora, los comandos confiables son indistinguibles de la entrada no confiable del usuario.
Solo que ahora no se trata de cadenas confiables y no confiables, sino de objetos confiables y no confiables.Para evitar este problema, siempre debe escribir comandos para que no puedan recibirse del usuario. Esto se puede implementar, entre otras cosas, utilizando el enfoque utilizado en
React y
Snabbdom-Signature (esta es una pequeña biblioteca para protección contra la inyección en el DOM virtual), es decir, marcando cada objeto del comando
Symbol
para que no se pueda enviar a través de la red.
Lo admito, a menudo yo mismo he pensado que, dado que no hay una base de datos SQL o si uso el DOM virtual, los ataques mediante la inyección de código no me amenazan. ¡Qué equivocado estaba!
LOOKING.HOUSE : el proyecto recolectó más de 150 puntos de espejo en 40 países. Puede ejecutar rápidamente los comandos host, ping, traceroute y mtr.
