REBELION_EN_LA_GRANJA/docs/seguridad.md
s1to 7caa240c2e Ajustar al manual del M1000e, añadir diagramas y docs de operación
Especificaciones tomadas del manual del propietario del gabinete
PowerEdge M1000e (Dell, modelo BMX01, rev. A06, oct. 2019), que corrige
el spec sheet comercial usado hasta ahora.

Hardware:

- Peso máximo 200,5 kg, no 179. Profundidad 75,5 cm
- Seis fuentes y nueve ventiladores obligatorios, se usen 3 blades o 16.
  Toda bahía vacía necesita relleno
- Conector CEI/IEC C20 a 16 A. La fuente de 3.000 W exige 200-240 V
- Irrupción de 55 A por fuente durante 10 ms: un magnetotérmico de curva
  C salta, hace falta curva D
- Temperatura de funcionamiento continuo 10-35 °C
- ECM obligatorio con blades M630 de 120 W o más, o por encima de 30 °C

Red:

- Fabric A (ranuras A1/A2) es la Ethernet integrada de cada blade, así
  que no hacen falta tarjetas intermedias. Fabrics B y C sí las
  exigirían y no se usan
- Pendiente saber si en A1/A2 hay un switch o un módulo de paso a
  través: cambia el montaje de red por completo

Costes recalculados: el suelo fijo del chasis sube de 350 a ~500 W al
contar los nueve ventiladores, los módulos de I/O y las pérdidas de las
seis fuentes. 360 €/mes a 24/7, 59 €/mes por ventanas. Que las fuentes y
los ventiladores sean obligatorios convierte en hecho documentado lo que
antes era estimación: los pilotos parciales en el chasis son el peor
caso posible.

Documentación:

- assets/ con cuatro diagramas SVG propios: arquitectura, chasis, stack
  de software y modos de red
- docs/usabilidad.md: órdenes, flujos de trabajo, problemas conocidos y
  ergonomía del hardware
- Diagramas ASCII del panel frontal, el posterior y la topología de
  fabrics en hardware_m1000e.md
- Eliminada la parte de charla y divulgación, fuera del alcance del repo
2026-08-08 20:04:00 +02:00

216 lines
8.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Repaso de seguridad
Revisión del montaje completo — arquitectura, hardware y el código Ansible de
[`02_device_lab/ansible/`](../02_device_lab/ansible/). Fecha: 2026-08-08.
Incluye los fallos que introduce el propio código de este proyecto, no solo los del entorno.
## Resumen
| | Hallazgo | Severidad | Estado |
|---|---|---|---|
| **S1** | adb sin autenticación + contenedor privilegiado → root del anfitrión | **Crítico** | Mitigado a medias |
| **S2** | Credenciales por defecto del CMC / iDRAC (`root`/`calvin`) | **Alto** | Sin verificar |
| **S3** | macvlan mete 45 Android en la LAN de producción | **Alto** | Por diseño, hay que aislar |
| **S4** | `host_key_checking = False` en `ansible.cfg` | Medio | Aceptado, documentado |
| **S5** | SSH como root en el inventario de ejemplo | Medio | Documentado |
| **S6** | Imagen de Android por tag mutable | Medio | Abierto |
| **S7** | Sin gestión de secretos | Medio | Abierto |
| **S8** | Estado persistente en `/data` sin cifrar | Medio | Abierto |
| **S9** | `fleet install` no verifica el APK | Bajo | Abierto |
| **S10** | Microcódigo antiguo en CPUs de 2011-2016 | Bajo | Aceptado |
| **S11** | Infraestructura de doble uso | Contextual | Ver [legal_ue.md](../01_investigacion/legal_ue.md) |
---
## S1 · adb sin autenticación sobre contenedor privilegiado — **crítico**
Una cadena de tres eslabones que por separado parecen asumibles:
1. **adb no tiene autenticación** cuando escucha en TCP. Quien llega al puerto, entra.
2. **Las imágenes de redroid son `userdebug`**, así que `adb root` funciona: shell de root dentro
del Android.
3. **El contenedor es `privileged: true`** — redroid lo exige para acceder a binder. Un privilegiado
ve los devices del anfitrión y puede montar su sistema de ficheros.
Encadenado: cualquiera que alcance el puerto 5555 de un blade acaba siendo root en ese blade, sin
exploit, solo con `adb connect`. Con 45 dispositivos son 45 puertas.
Corregido en parte: el compose ataba adb a `0.0.0.0`. Ahora hay `redroid_adb_bind_ip`, que permite
atarlo solo a la interfaz interna del chasis:
```yaml
blade-02: { ansible_host: 10.0.0.12, redroid_adb_bind_ip: 10.0.0.12 }
```
**Lo que cierra el agujero:**
- **Red de laboratorio aislada.** VLAN propia para la granja, sin ruta hacia la LAN de casa ni
hacia internet salvo lo imprescindible. Es la medida que importa; el resto son parches.
- **Cortafuegos en cada blade** (nftables) que solo acepte 5555+ desde la IP del coordinador.
- **Nunca exponer estos puertos a internet.** Ni con reenvío de puertos, ni con VPN mal segmentada.
En modo `macvlan` el problema es peor: adb queda escuchando en la IP de LAN del propio Android,
donde `redroid_adb_bind_ip` no aplica. Ahí la única defensa es la VLAN.
---
## S2 · Credenciales por defecto del CMC y de los iDRAC — **alto**
Los Dell PowerEdge salen de fábrica con **`root` / `calvin`** en iDRAC, y el CMC del M1000e con las
mismas. Es la forma clásica en que se toma uno de estos chasis: no hay que romper nada, se entra.
El M1000e es de 2016 o anterior, así que el firmware de gestión arrastra años de CVEs conocidas y
TLS antiguo.
Antes de enchufarlo a nada:
- Cambiar las credenciales del CMC **y de cada uno de los 16 iDRAC**, no solo del CMC.
- Actualizar firmware de CMC e iDRAC hasta donde Dell lo permita para esa generación.
- **VLAN de gestión separada**, sin salida a internet. La gestión de un chasis nunca va en la
misma red que el resto.
- Desactivar IPMI sobre LAN si no se usa (`cipher 0` es un clásico de acceso sin autenticar).
Esto es independiente de la granja: aplica al hierro desde el momento en que se encienda.
---
## S3 · macvlan expone 45 Android en la LAN — **alto**
El modo `macvlan` es el que hace falta para el caso de los dos APKs de `oasis_mobile`, pero pone
cada Android **con IP real en la red**, cada uno con S1 encima.
- VLAN dedicada para la granja, con el coordinador como único puente.
- Reservar el rango de IPs en el DHCP, o habrá colisiones con máquinas reales.
- No usar la LAN doméstica.
---
## S4 · `host_key_checking = False` — medio
Lo puse yo en `ansible.cfg` por comodidad de arranque. El coste: si alguien se hace pasar por un
blade, Ansible se conecta igual y le entrega **comandos de root y, si se usa, la contraseña de
sudo**.
Es asumible en el primer aprovisionamiento de una red aislada. Después:
```bash
ssh-keyscan -H 10.0.0.11 10.0.0.12 ... >> ~/.ssh/known_hosts
```
y poner `host_key_checking = True`.
---
## S5 · SSH como root — medio
`inventory/hosts.yml.example` trae `ansible_user: root`. Funciona, pero:
- Usuario dedicado con sudo en vez de root directo
- **Solo clave, sin contraseña**: `PasswordAuthentication no`
- `PermitRootLogin no` en los blades
- Clave separada para la granja, no la personal
---
## S6 · Imagen de Android por tag mutable — medio
`redroid/redroid:13.0.0-latest` es un tag que **se mueve**. Consecuencias reales:
- Dos blades provisionados con una semana de diferencia acaban con imágenes distintas, y depurar
eso es un infierno.
- Cadena de suministro: si la cuenta del registro se compromete, el siguiente `docker compose pull`
se trae otra cosa. Y entra en 45 contenedores privilegiados.
Fijar por digest:
```yaml
redroid_image: "redroid/redroid@sha256:<digest>"
```
Con `docker buildx imagetools inspect redroid/redroid:13.0.0-latest` se saca el digest actual.
Se actualiza a mano cuando se quiera subir de versión, que es justo lo que se quiere.
---
## S7 · Sin gestión de secretos — medio
El inventario de ejemplo menciona `ansible_become_password` sin montar `ansible-vault`. Si se pone
una contraseña ahí en claro, queda en el disco y en cualquier copia del proyecto.
```bash
ansible-vault create group_vars/granja/vault.yml
ansible-playbook site.yml --ask-vault-pass
```
Mejor aún: sudo sin contraseña para el usuario de despliegue, restringido a los comandos que
necesita, y ninguna contraseña en ningún fichero.
---
## S8 · Estado persistente sin cifrar — medio
Cada Android guarda su `/data` en `{{ redroid_base_dir }}/data/device-NN` del blade, sin cifrar.
Si en las pruebas se entra con cuentas reales — cuentas SSB, credenciales de Gitea, lo que sea —
esas credenciales quedan en el disco del blade en claro.
`destroy.yml` **conserva los datos por defecto**, a propósito, así que sobreviven a un
redespliegue y a un cambio de manos del hardware.
- Cuentas de prueba desechables, nunca las reales.
- Cifrado de disco en los blades si van a manejar algo sensible.
- Al dar de baja un blade: `destroy.yml -e confirmar=si -e borrar_datos=si` **y** borrado del disco.
---
## S9 · `fleet install` no verifica nada — bajo
`fleet install app.apk` mete el APK en los 45 dispositivos sin comprobar firma ni hash. Como los
APK son propios (`oasis_mobile`), el riesgo es bajo, pero el patrón es malo: un fichero equivocado
se propaga a toda la flota de una vez.
Comprobar el hash antes, y a ser posible la firma con `apksigner verify --print-certs`.
---
## S10 · Microcódigo antiguo — bajo
CPUs de 20112016 con microcódigo sin actualizar: las mitigaciones de Spectre/Meltdown dependen de
microcódigo + kernel. En un laboratorio aislado que solo corre código propio, el riesgo es bajo.
Subiría si algún día se corre software de terceros no confiable en los Android.
`apt install intel-microcode` en los blades, y aun así esa generación no recibe todo.
---
## S11 · Infraestructura de doble uso — contextual
Técnicamente, esto es indistinguible de una granja de cuentas: 45 Android automatizados, con
control central y despliegue masivo de APKs. Lo que separa un laboratorio de QA de una granja de
fraude no es la infraestructura, son **tres cosas que no están aquí**: SIMs, proxies residenciales
y cuentas de plataforma.
Para que siga siendo lo que es:
- No conectar la granja a proveedores de SIM ni de números por API.
- No meter proxies residenciales o móviles.
- Documentar el propósito con evidencia — este repositorio ya lo hace.
El contexto legal está en [legal_ue.md](../01_investigacion/legal_ue.md). Y recuerda el hallazgo de
la investigación: estos Android **son detectables como emulador**, así que para las plataformas
sociales no servirían aunque se quisiera.
---
## Mínimos antes de encender
Por orden:
1. Cambiar credenciales del **CMC y de los 16 iDRAC** (S2)
2. **VLAN aislada** para granja y gestión, separadas entre sí (S1, S2, S3)
3. `redroid_adb_bind_ip` a la IP interna de cada blade (S1)
4. Claves SSH, sin root, sin contraseñas (S5)
5. Poblar `known_hosts` y `host_key_checking = True` (S4)
6. Fijar la imagen por digest (S6)
Los tres primeros no son opcionales. Sin ellos, la granja es 45 puertas abiertas a la red.