Aunque pueda resultar obvio, utilizar HTTPS es siempre el primer paso para securizar una web.
- Todo va cifrado, previniendo sniffing en la red.
- Dificulta ataques tipo Man in the Middle.
a b c d e f g h i j k l m n o p q r s t u v w x y z
z a b c d e f g h i j k l m n o p q r s t u v w x y
david
czuhc
a b c d e f g h i j k l m n o p q r s t u v w x y z
w x y z a b c d e f g h i j k l m n o p q r s t u v
david
zwrez
Cifrado César
Desplazamiento
1
Desplazamiento
4
Cliente
Servidor
¿Desplazamiento?
Desplazamiento X
GET /url
Respuesta cifrada
Router
Tu
ordenador
Ordenador
sniffer
Tu tráfico
Tu tráfico
Muchas veces exponemos por defecto todos los datos que contienen nuestros recursos, exponiendo información que no debería estar disponible para cualquier usuario.
Apliquemos el SRP a los endpoints:
- Más endpoints
- Más pequeños
{
"name": "David",
"link": "/user/david",
"avatar": "/img/david.png",
"mail": "david.hernandez@politicalwatch.es",
"pass": "password"
}
{
"name": "David",
"link": "/user/david",
"avatar": "/img/david.png"
}
Normalmente en la base de datos tenemos IDs secuenciales. Cuando tenemos un endpoint para obtener estos datos, es común usar ese ID para acceder a estos datos.
GET /usuario/1
{
"name": "David",
"link": "/user/david",
"avatar": "/img/david.png",
"id": 1
}
GET /usuario/1234-ABCD
{
"name": "David",
"link": "/user/david",
"avatar": "/img/david.png",
"uuid": "1234-ABCD"
}
Al igual que en una web no todo es público y tenemos inicios de sesión para controlar el acceso, en las APIs también es necesario controlar quién puede acceder a qué endpoint.
Aunque podemos implementar un sistema de autentificacion de 0, ya existen sistemas preparados para hacerlo:
- OAuth
- JWT
Cliente
Servidor
Servicio de autentificación
Endpoints
HTTP Request con credenciales
HTTP Response con token
Request con token
Response con datos
Request sin token
401: Unauthorized
PROs:
- Externalizamos la auth.
- Mejor con varios clientes.
CONs:
- Damos info a terceros.
- Más complejo de montar.
PROs:
- Mejor con solo un cliente.
- Queda todo en local.
CONs:
- No sirve para no APIs.
Si yo como usuario, no debería poder acceder a la información de otro usuario, ¿porque en las APIs si que puedo?
Una vez tenemos implementado un sistema de autentificación, debemos hacer otros controles de acceso.
- ¿El usuario tiene acceso a ese recurso?
- ¿Puede ver todos los campos?
Este ataque puede ocurrir cuando los parámetros que usa el endpoint se utilizan para realizar operaciones en la base de datos y estos no son debidamente sanitizados.
Es importante que cualquier dato que se mande a la API no se utilice directamente contra la base de datos.
const mysql = require('mysql');
const connection = mysql.createConnection(config);
app.get('/user/:id', (req, res) => {
const id = req.params.id
const sql = 'SELECT * FROM users WHERE id = ' + id
connection.query(sql)
}));
GET /user/1
GET /user/1; DELETE FROM users WHERE 1=1
Significa `Cross-origin resource sharing` y es un mecanismo de los servidores que impide responder a una request que no viene de un dominio autorizado.
Por defecto, el único dominio autorizado es el que use la API.
Es importante no desactivar el CORS a menos que sea estrictamente necesario.
Significa `Cross-site scripting` y es cuando un atacante consigue inyectar código malicioso en el HTML que se renderiza al usuario.
Por ejemplo, un atacante podría inyectar un minero de cryptomonedas o un script para robar datos del usuario.
app.get('/user/:id', (req, res) => {
const id = req.params.id
res.send('Usuario: ' + id)
}));
GET /user/1
GET /user/<script src="cryptominer.js"/>