Investigación sobre granjas de dispositivos y automatización completa para levantar un laboratorio Android sobre un chasis de blades Debian. Conclusión que ordena el repositorio: el cuello de botella nunca fue el cómputo sino la identidad. Desde que la atestación de dispositivo pasó de estadística a criptográfica, un servidor no puede hacerse pasar por un teléfono — le falta una clave grabada en fábrica que ningún software produce. Contenido: - 01_investigacion/ — capa de identidad (verificación telefónica, eSIM, reputación de IP, atestación por hardware, correlación entre cuentas), mercado y players, stack técnico, marco legal en la UE - 02_device_lab/ansible/ — Ansible para 16 blades: preflight de solo lectura que identifica el hardware por DMI, despliegue de redroid en Docker y control de flota por adb. Solo ansible.builtin, sin colecciones externas - docs/ — requisitos, costes y repaso de seguridad con 11 hallazgos - 03_charla/ — guion para HackMadrid / Hackmeeting València Estado: la automatización está escrita pero SIN ejecutar contra hardware. YAML validado, plantillas renderizadas en ambos modos de red y fleet.sh comprobado con bash -n. El modelo de blade sigue sin confirmar.
8.7 KiB
Repaso de seguridad
Revisión del montaje completo — arquitectura, hardware y el código Ansible de
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 |
S1 · adb sin autenticación sobre contenedor privilegiado — crítico
El fallo más serio, y es una cadena de tres eslabones que por separado parecen asumibles:
- adb no tiene autenticación cuando escucha en TCP. Quien llega al puerto, entra.
- Las imágenes de redroid son
userdebug, así queadb rootfunciona: shell de root dentro del Android. - 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.
No hace falta ningún exploit, solo adb connect.
Y con 45 dispositivos son 45 puertas.
Qué se ha corregido hoy. El compose ataba adb a 0.0.0.0 — todas las interfaces. Ahora hay
redroid_adb_bind_ip, así que se puede atar solo a la interfaz interna del chasis:
blade-02: { ansible_host: 10.0.0.12, redroid_adb_bind_ip: 10.0.0.12 }
Qué falta, y es lo que de verdad 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 0es 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 de casa. Nunca.
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:
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 noen 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 pullse trae otra cosa. Y entra en 45 contenedores privilegiados.
Fijar por digest:
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.
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=siy 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 2011–2016 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. 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:
- Cambiar credenciales del CMC y de los 16 iDRAC (S2)
- VLAN aislada para granja y gestión, separadas entre sí (S1, S2, S3)
redroid_adb_bind_ipa la IP interna de cada blade (S1)- Claves SSH, sin root, sin contraseñas (S5)
- Poblar
known_hostsyhost_key_checking = True(S4) - Fijar la imagen por digest (S6)
Los tres primeros no son opcionales. Sin ellos, la granja es 45 puertas abiertas a la red.