Como saben, la mayoría de los ataques de los piratas informáticos de BlackHat están destinados a comprometer los datos del servidor de las aplicaciones y servicios web. Al mismo tiempo, la parte del cliente es atacada al menos hoy. Según la definición en seco, cualquier ataque es un conjunto de medidas por parte de un hacker dirigido a la red y la transferencia de datos, los datos y su sustitución, infraestructura y características técnicas de la implementación de la aplicación web. Por lo tanto, las compañías internacionales requieren que los ingenieros de desarrollo adopten un enfoque más responsable y exhaustivo para la seguridad de las aplicaciones del cliente.
En el ejemplo de mi proyecto, hablaré sobre cómo las aplicaciones cliente atacan hoy y cómo puede evitar estas amenazas.
Las 10 principales amenazas para 2013-2017.Como puede ver, entre las principales amenazas, la inyección, la activación de errores, la omisión de autenticación y los datos confidenciales inseguros ocupan el primer lugar. La amenaza de usar componentes con vulnerabilidades conocidas sigue siendo relevante. También aparecieron nuevas amenazas: piratería del mecanismo de control de acceso, deserialización y serialización inseguras de datos, registro y monitoreo insuficientemente detallados.
En 2001, Mark Curfy y Dennis Groves fundaron el OWASP (Open Web Application Security Project). Este es un proyecto internacional de código abierto para el intercambio de experiencias sobre el combate de vulnerabilidades en aplicaciones cliente, en el que participan una gran cantidad de ingenieros de seguridad de aplicaciones. La comunidad OWASP llena el portal con una multitud de artículos con información de vulnerabilidad, materiales de capacitación, herramientas para probar y repeler ataques. Se describen ataques reales, se revelan sus aspectos y se describe lo que hay que hacer para prevenir amenazas.
Para comprender qué amenazas son peligrosas para un proyecto, debe probarlo a fondo. Para hacer esto, la red tiene aplicaciones, marcos y servicios en línea que identifican automáticamente ciertas vulnerabilidades. Para las pruebas locales, recomiendo usar aplicaciones y marcos, y para probar proyectos en funcionamiento, también es muy útil agregar servicios en línea.

Pero incluso si las herramientas de prueba no le informaron en informes sobre vulnerabilidades significativas (lo cual es poco probable), aún preste atención al almacenamiento de datos confidenciales en el sistema de control de versiones, la creación de la aplicación, el mecanismo de autenticación, el algoritmo de hash de contraseña, el cifrado de datos confidenciales y los sistemas de registro y monitoreando toda la aplicación web. En este caso, es mejor ir a lo seguro y no confiar en la automatización ciega.
Git
Primero, hablemos de datos confidenciales en Git. Idealmente, se asigna un depósito separado de secretos para almacenar datos confidenciales. A partir de él, durante el ensamblaje para la puesta en marcha, los datos confidenciales se extraen y se cosen a la aplicación. Hoy, Hashicorp Vault, Keywhiz, Docker secrets, Azure Key Vault y muchos otros son populares.
Pero, ¿qué pasa si no tienes ese almacenamiento? Puede usar herramientas para codificar y ocultar archivos con secretos que ampliarán las capacidades de los sistemas de control de versiones.
Lo primero que viene a la mente es la solución universal BlackBox. Se puede usar con cualquier sistema de control de versiones, por ejemplo, Mercurial, Git, etc. Además, hay dos extensiones para Git: git-crypt y git-secret. Recomiendo usar el segundo, porque me pareció el más conveniente de usar y más comprensible en términos de descripción en la documentación oficial. Después de instalar git-secret, debe inicializarlo en el repositorio de Git. Recuerde especificar la extensión a usar en el archivo .gitattributes . A continuación, configure la accesibilidad de los secretos: identifique los usuarios a los que desea proporcionar acceso a datos confidenciales. Luego agregue archivos con datos confidenciales y git-secret-hide
a través de git-secret-hide
. Puede obtener archivos ocultos a través de git-secret-reveal.
brew install git-secret //
git secret init //
git secret tell your@gpg.email  //
git secret add <files...> //
git secret hide  //
git secret reveal  //
Paquete web
Otra forma de eliminar amenazas es configurar el paquete web correctamente. Para protegerse contra XSS, XEE y ataques similares, debe considerar adherirse a las políticas CORS (Intercambio de recursos de origen cruzado) y CSP (Política de seguridad de contenido). En ambos casos, es importante seguir los encabezados para verificar la autenticidad de ciertos scripts que se utilizan en el proyecto. Los navegadores tienen mecanismos para verificar la confiabilidad de una fuente en particular, por ejemplo, Safari emitirá advertencias en cada paso si CORS y CSP están configurados incorrectamente.
Hay dos formas de cumplir con CORS y CSP. El primero es configurar los encabezados para responder a las solicitudes en el lado del servidor. El segundo es registrar ambas políticas a través de metaetiquetas y atributos. Se recomienda este último método si tiene desarrolladores de back-end perezosos, siempre están ocupados y no están interesados en las políticas de seguridad. Las metaetiquetas se pueden registrar de inmediato al crear la aplicación. Los complementos como html-webpack-plugin, html-webpack-exclude-assets-plugin, script-ext-html-webpack-plugin, csp-html-webpack-plugin y crypto nos ayudarán con esto. Además, si tiene recursos de terceros en su proyecto (por ejemplo, enlaces a fuentes externas utilizadas en CSS; recursos cargados desde CDN, etc.), entonces también recomiendo usar el complemento webpack-subresource-INTEGMENT-INTEGRITY. Por lo tanto, informará al navegador que los recursos cargados en el script son confiables, no hay inyecciones en ellos, son completos y están intactos. E incluso si alguien inyectó datos maliciosos en el recurso, y usted lo cargó, debe estar preparado para esto y proteger su proyecto de tales amenazas.
Quiero prestar especial atención al orden en que se crean las instancias de clase para los complementos. El orden debería ser así:
const SHA256 = (str) => CRYPTO.createHash('sha256').update( str, 'utf8').digest('base64'); const sha256Str = SHA256( '' + Date.now() ); […] new HtmlWebpackPlugin({ filename: 'index.html', template: 'public/index.html' }), new ScriptExtHtmlWebpackPlugin({ custom: [{ test: /\.js$/, attribute: 'nonce', value: 'nonce-' + sha256Str }] }), new HtmlWebpackExcludeAssetsPlugin(), new CspHtmlWebpackPlugin({ 'base-uri': '\'self\'', 'object-src': '\'none\'', 'script-src': ['\'self\'', '\'unsafe-eval\'', '\'nonce-' + sha256Str + '\''], 'style-src': ['\'unsafe-inline\'', '\'self\''] }, { devAllowUnsafe: false, enabled: true, hashingMethod: 'sha256' }), new SriPlugin({ hashFuncNames: ['sha256', 'sha384'], enabled: true }), […]
Luego, durante el ensamblaje, la <hed>
mostrará la <hed>
http-equiv=content-security-policy
. Las directivas se escribirán en el atributo de content
, que dice en qué scripts y recursos se puede confiar.
La directiva base-uri
muestra qué URL base se usa para cargar scripts, CSS, imágenes y más.
Los objetos generalmente no se cargan, por lo tanto, none
configure none
en la directiva object-sr
c.
La directiva script-src
aplica a los scripts JS.
No olvide registrar un atributo de tipo nnce-<hshVlue>
cada vez. Además, el hash debe calcularse utilizando el algoritmo SHA256 o SHA512.
En cuanto a la directiva style-src
, nuestro proyecto tiene una peculiaridad: utilizamos componentes con estilo para escribir CSS para cada componente y aislarlos unos de otros. Y, por lo tanto, es necesario especificar que en us style-src
unsafe-inline
y self
se usan en style-src
, de lo contrario los componentes con estilo se caerán.

La etiqueta del script
se establecerá automáticamente en nnce-<hshVlue>
, integrity
y cross-origin
. Le dicen al navegador que los recursos se obtienen de fuentes confiables. De lo contrario, si el navegador ve que el recurso no coincide con CSP o CORS, simplemente no cargará este script o archivo CSS, y escribirá algo en la consola como: "Presta atención a este script, a esta línea donde inicializas el. ¡Mira, tienes algo mal! .
La documentación de MDN , OWASP y W3C proporciona pautas para hacer cumplir las políticas de CSP y CORS. Además, cualquier herramienta de prueba de penetración informará el cumplimiento de las normas CORS y CSP en el proyecto. Cualquier marco o herramienta que realice pruebas automáticas de un proyecto señalará fallas.
Autenticación de usuario
Utilizamos OpenID Connect y el protocolo Kerberos. Se utiliza un estándar OpenID bastante común para autenticar usuarios externos.
Kerberos es más adecuado para la red interna, en el banco se usa para la autenticación automática de los empleados. Supongamos que hay una máquina local en la que trabaja un empleado de la organización. Se autenticó una vez en esta máquina y ya no necesitará ingresar nuevamente el nombre de usuario y la contraseña: el empleado inicia sesión en cualquier aplicación y el sistema la autentica de inmediato. Kerberos tiene configuraciones sutiles para la máquina local, y esto es difícil porque tiene que configurarse para cada computadora y cada navegador. Si Internet Explorer normalmente muestra la configuración predeterminada y Chrome muestra la configuración de IE, entonces Firefox tiene que configurarla por separado. Safari en MacOS X encontrará la configuración en sí, pero para Safari en Windows deberá especificarlos manualmente.
Debe verificar su aplicación en todos los navegadores, ya sea que funcione en todas partes como debería. Por ejemplo, si trabajo en Windows, instalo Safari localmente y pruebo mi proyecto en él, y si trabajo en Mac, levanto Windows en una máquina virtual para ejecutar la aplicación en las versiones correspondientes de los navegadores.
La autenticación se puede implementar en aplicaciones modernas utilizando Passport.js y paquetes de sesión rápida, así como el SDK Auth0.
Si no puede desarrollar un servicio de autenticación a través de OpenID Connect o cualquier otro protocolo, utilice una capa proxy, como Auth0 y similares, para que la autenticación se realice a través de una empresa externa que se especialice en proporcionar a los usuarios acceso seguro a los recursos de Internet.
Cuando actualizamos alguna aplicación a Node.js, recomendamos utilizar los paquetes Passport.js, express-session, etc. en el servidor. Para garantizar la seguridad del cliente, elevamos de forma independiente el componente para la autenticación. No olvide especificar el atributo de autocompletar en el formulario de autenticación para excluir la finalización automática de los campos del formulario.
Hashing de contraseña
El sitio web de OWASP recomienda que no utilice mecanismos de hash de contraseña integrados en la base de datos. Para esto, es mejor usar paquetes como Argon2, PBKDF2, ccrypt y bcrypt. En mi práctica, uso Argon2: este es un contenedor para algoritmos GCC, PGP / GPG, etc., pero requiere que primero instale el paquete GCC. Esquema de uso de Argon2:
1. GCC >= 4.8 install $ brew install gcc
2. - $ npm install -g node-gyp
3. Argon2 $ npm install argon2
4. import * as ARGON from 'argon2'; ARGON.generateSalt().then( (salt: string) => { ARGON.hash('some-user-password', salt) .then((hash : string) => { console.log('Successfully created Argon2 hash:', hash);
Ofuscación
La ofuscación le permite modificar el código para que no se pueda analizar en componentes. Después de todo, los atacantes, y no solo ellos, a menudo usan ingeniería inversa: el programador toma un archivo JS y comienza a analizar las fuentes. Por lo tanto, puede aprender los métodos utilizados o comprender el mecanismo de trabajo de un script en particular para implementar código malicioso. O utilice estos mecanismos para hackear una aplicación web y realizar un ataque sigiloso.
Los hackers no se meten en problemas. Primero, realizan una exploración del recurso, determinan las vulnerabilidades y atacan el vector. Por ejemplo, manipulan datos o explotan vulnerabilidades contenidas en protocolos de transporte. El vector de ataque puede estar dirigido a las vulnerabilidades de un sistema operativo en particular; hay muchas de ellas en cualquier sistema UNIX. Pero las vulnerabilidades solo se pueden usar si el administrador tiene políticas de seguridad mal configuradas, por ejemplo, establece incorrectamente las URL que salen.
Entonces, para el reconocimiento, se usa ingeniería inversa. Es imposible excluirlo por completo, pero puede ser muy difícil. Para esto, se utilizan varios ofuscadores, en mi caso, javascript-ofuscador. En base a ello, se crea un complemento para webpack: webpack-ofuscador. También para webpack creado ofuscator-loader. Este paquete tiene configuraciones recomendadas para diferentes niveles de paranoico: bajo, medio y alto, se pueden encontrar en el sitio web oficial. Si usa este ofuscador, recuerde que funciona muy mal con el mecanismo de minificación integrado en el paquete web. No use la minificación y la ofuscación juntas, de lo contrario, el ofuscador puede romper completamente el código del script.
Además, el ofuscador aumenta el volumen del script y su carga. Aquí debe decidir por sí mismo: o mejora la seguridad, la estabilidad y la confiabilidad, pero pierde en comodidad y velocidad; o se preocupan por la velocidad, pero olvídate de la seguridad, de seguir cualquier guía
Registro de amenazas y monitoreo
Existe una amenaza tal como el uso de paquetes con vulnerabilidades ya conocidas. Los analizadores de amenazas como npm audit, Snyk y LGTM ayudarán en tales situaciones. Npm audit es una utilidad estándar que está integrada en npm, pero debe llamar constantemente a este comando o crear muletas. Por lo tanto, le aconsejo que use Snyk. Este proyecto tiene su propia base de datos con vulnerabilidades. Cuando comienza la prueba, Snyk accede a esta base de datos y carga confidencialmente el informe a su proyecto Snyk, al que no pueden acceder personas externas. Es cierto, puede verificar su proyecto de forma gratuita solo 300 veces, y cuando verifica cada confirmación previa, estos 300 intentos gratuitos terminan muy rápidamente. Por lo tanto, es mejor ejecutar una prueba para los ganchos de pre-inserción o pre-fusión.
El hombre es la vulnerabilidad más importante de cualquier sistema. Por lo tanto, asegúrese de verificar el proyecto antes de comenzar a compilar la aplicación, ya que incluso el código fuente puede contener algo malicioso. Es bueno cuando solo una persona tiene acceso al proyecto, pero generalmente trabajamos en equipo. ¿Qué pasaría si apareciera algún tipo de "simpatizante" que decidiera dejar la empresa "maravillosamente" y dejar una marca? Esto también debe tenerse en cuenta.
Recomiendo usar el paquete Snyk desde el comienzo del proyecto e iniciar el escaneo desde la consola. Aquí todo es simple: después de la instalación, configure el inicio de sesión y la contraseña para la cuenta, y la prueba en sí se puede realizar de esta manera:
- Después de instalar la dependencia npm i snyk —D y especificar "snyk": verdadero en package.json, ejecute:
./node_modules/.bin/snyk wizard --dev
- En package.json agregue scripts y configuraciones:
{ ... "scripts": { ... "test": "npm run test:snyk && npm run test:jest", ... "test:snyk": "snyk test --dev", ... "prepare": "npm run prepare:snyk", "prepare:snyk": "snyk protect" }, "husky": { "hooks": { "commit-msg": "commitlint -E HUSKY_GIT_PARAMS", "pre-commit": "npm run test:snyk && npm run lint && npm run test:jest", "pre-push": [ "npm run test:snyk", "npm run lint", "npm run test:jest", "npm run build:production" ], ... } }, "snyk": true }
Arriba, miramos un cheque local para amenazas de seguridad. Para verificar paquetes de amenazas conocidas, también recomiendo usar LGTM. Use este proyecto junto con GitHub o Bitbucket (hasta que lo haya probado, no era necesario), y el código se verificará inmediatamente con cada pulsación.
Monitoreo de la aplicación
En el ámbito de Front-end, las herramientas ya están bien establecidas; las herramientas para todos los gustos están disponibles para registrar y monitorear la parte del cliente. Los más famosos son Sentry, TrackJS e InsightOps. Sentry Server se puede implementar en sus servidores físicos. Por ejemplo, en nuestros dos proyectos utilizamos un servidor separado, que estaba completamente configurado para registrar el funcionamiento de las aplicaciones. Fuimos a la URL y soltamos todos los registros allí. Si se produce un error en la aplicación, se envuelve en un bloque try catch y se envía al servidor Sentry a través de los métodos del paquete raven. Todo es simple y conveniente. Si ve URL oscuras en Sentry que no registró, si ve incrustaciones o mensajes oscuros, entonces están tratando de hackearlo. En mi práctica, esto sucedió regularmente. Por ejemplo, uno de los proyectos, un servicio para evitar los bloqueadores de anuncios y los antivirus, intentaba constantemente contrarrestarlo, descifrarlo.
Para el monitoreo, también recomiendo usar Grafana. Es importante considerar un sistema de criterios e indicadores que serán monitoreados por el sistema. Nos sintonizamos en el tráfico, en el retorno de la publicidad, en el grado de presentación de anuncios, en la cantidad de pancartas que provenían de Yandex, etc. (proyectos en Rambler Group). Necesitábamos entender cómo funciona Yandex con nuestras solicitudes, porque es un servicio de terceros, lo que significa que debe ser monitoreado, porque si falla, todo el proyecto puede colapsar por completo.
Si supervisa todas las comunicaciones con servicios de terceros, encontrará rápidamente cualquier error. La historia es de mi práctica: vimos que desde Yandex, las respuestas publicitarias dejaron de llegar. Resultó que tenían fallas técnicas y que toda la red de publicidad cayó con fuerza. Y no fue Yandex quien nos informó primero, pero los llamamos y les pedimos que vieran qué estaba pasando con sus servicios.
¿Cuál es la mejor manera de monitorear? Tome una URL pequeña, escriba los parámetros GET y envíe una solicitud GET a esta URL. En el lado del servidor, procese esta URL, escriba el registro en la base de datos y aumente la supervisión a Grafana. Todo es simple
Eso es todo En el futuro intentaré seguir escribiendo sobre el tema de proteger las aplicaciones web de las amenazas. A todos los que han leído hasta el final: deseo seguridad para sus proyectos)))
Lista de fuentes para leer sobre el tema:
www.owasp.org/index.php/Main_Page
tproger.ru/translations/webapp-security
S. Hawks. Aplicación de página única incluso más rápida: seguridad
Seacord, Robert C. El estándar de codificación segura CERT C / Robert C. Seacord. - 2008
Chetan Karande. Asegurar aplicaciones de nodo - 2017
Steven Palmer. Detección, explotación, prevención de vulnerabilidades de aplicaciones web: 2011
Robert Shimonski, Sean-Philip Oriyano. Ataques y defensa del lado del cliente - 2012
Marcus Pinto, Dafydd Stuttard. El Manual del hacker de aplicaciones web: Encontrar y explotar fallas de seguridad, 2ª edición - 2011
Karl Duuna Asegure su aplicación web Node.js - 2015