Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
accfly — Divulgación de vulnerabilidades de la cámara Accfly: CVE-2020-25782, CVE-2020-25783, CVE-2020-25784, CVE-2020-25785. | Kitploit
Herramientas/GitHubGitHub/tezeb/accfly
Seguridad de Sistemas EmbebidosSeguridad IoTAnálisis de VulnerabilidadesExplotaciónIngeniería InversaFuzzingPruebas de PenetraciónSeguridad de Hardware e IoTExplotación de Binarios
GitHubtezeb/accfly

accfly

Divulgación de vulnerabilidades de la cámara Accfly: CVE-2020-25782, CVE-2020-25783, CVE-2020-25784, CVE-2020-25785.

3hace 5 añosAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Ver Repositorio

¿Qué tan segura es tu cámara de "seguridad"?

Resumen ejecutivo

A principios de 2020, en mi antiguo lugar de trabajo, tuve la oportunidad de participar en un evento interno estilo pwn2own. Había varios objetivos disponibles, pero el que más me interesaba era la cámara de seguridad inalámbrica Accfly. Desafortunadamente, no pude terminar mi investigación para el evento en sí, pero como no hubo otros intentos con este dispositivo, continué con ella.

El enfoque principal de la investigación fueron las vulnerabilidades que podrían llevar a la ejecución remota de código (RCE). Este tipo de vulnerabilidad permite a un atacante tomar el control total del dispositivo y, en el caso de una cámara de video, puede resultar en un compromiso completo de la privacidad del propietario. Desafortunadamente, se descubrió que el firmware del dispositivo está plagado de estos problemas.

Primero, el dispositivo no proporciona ninguna autenticación. Como resultado, un atacante capaz de conectarse a él puede acceder y reconfigurarlo libremente. En la forma más simple, es posible reiniciar continuamente el dispositivo, volviéndolo completamente inutilizable para el usuario legítimo. El alcance de este ataque está ligeramente limitado ya que el dispositivo está diseñado para usarse dentro de una red WiFi, generalmente detrás de NAT, por lo tanto no es directamente accesible desde Internet. Sin embargo, la falta de cifrado entre el dispositivo y la aplicación móvil de su propietario, junto con el uso del servidor del fabricante como proxy para la comunicación, crea una oportunidad para un ataque MitM o de manipulación de DNS, que puede romper la restricción de NAT de la WiFi.

Además, la aplicación utiliza un protocolo binario propietario para la comunicación. Se ha implementado en una mezcla de C y C++ y se ha descubierto que está lleno de funciones de manejo de cadenas inseguras. El ejecutable principal contiene una gran cantidad de código no utilizado, lo que sugiere que se reutiliza en otros dispositivos. Esto dificulta el mantenimiento y aumenta la superficie de ataque. La aplicación no habilita ningún mecanismo de seguridad moderno que la proteja contra muchas técnicas de explotación comunes. Además, ni siquiera limita los permisos de usuario, ejecutándose como root, con los privilegios más altos disponibles.

Como resultado de esta investigación, se han documentado las siguientes cuatro vulnerabilidades:

  • CVE-2020-25782 - Desbordamiento de búfer basado en pila no autenticado en la función CNetClientManage::ServerIP_Proto_Set al manejar mensajes entrantes
  • CVE-2020-25783 - Desbordamiento de búfer basado en montón no autenticado en la función CNetClientTalk::OprMsg al manejar mensajes entrantes
  • CVE-2020-25784 - Desbordamiento de búfer basado en pila no autenticado en la función CNetClientGuard::SubOprMsg al manejar mensajes entrantes
  • CVE-2020-25785 - Desbordamiento de búfer basado en pila no autenticado en la función CFtpProtocol::FtpLogin durante el procedimiento de actualización

Para tres de ellas se desarrollaron exploits de RCE, que permiten a un atacante obtener el control completo del dispositivo. Sin embargo, debido a la falta de respuesta del fabricante a los intentos de reporte de vulnerabilidades, este repositorio contiene solo exploits PoC limitados, que simplemente hacen fallar la aplicación.

Los problemas se encontraron en la versión de software V3.10.73 y se verificaron en la versión de software V4.15.77, la última disponible en el momento de esta publicación (26 de enero de 2021).

En caso de cualquier pregunta, no dudes en contactarme por correo electrónico (ver git commit) o a través de los issues de Github. Si tienes un dispositivo IoT que crees que podría ser interesante de hackear, estás buscando un Investigador de Seguridad o simplemente quieres saludar, estaré encantado de saber de ti. También puedes invitarme un café!

Introducción

El dispositivo objetivo es una cámara de video, que se controla desde la aplicación móvil acompañante. Mi análisis comenzó con el tráfico de red de la cámara y continuó hacia el firmware de la cámara. Se utiliza un protocolo binario personalizado para toda la comunicación. Los comandos se envían directamente al dispositivo móvil cuando están en la misma red o pasan a través del servidor del fabricante del dispositivo. El software de la cámara escucha en múltiples puertos TCP (23456,34567) y UDP (34568, 34569). No hay cifrado ni autenticación para el tráfico de red, lo que permite ataques MitM o acceso directo cuando la cámara está expuesta en la red. Parece probable que el acceso a la transmisión de video también sea posible sin autenticación, pero no he realizado suficiente ingeniería inversa del protocolo propietario para probarlo.

Después de una breve descripción general de la comunicación, el siguiente paso fue intentar acceder al firmware del dispositivo. Mi primer intento fue descargarlo directamente secuestrando el proceso de actualización del dispositivo, pero no ocurrió nada similar en el tráfico de red. Me habría quedado estancado en esta etapa, si no fuera por la muy necesaria ayuda de un colega que extrajo el firmware de la memoria flash, lo que me permitió continuar con esta investigación.

Se descubrió que el firmware ejecuta Linux en una CPU MIPS little-endian. Hay exactamente un proceso interesante, llamado Alloca, que es responsable de la captura de video y también maneja todas las comunicaciones de red. La aplicación está creada en C++ y contiene mucho código que no se utiliza en este dispositivo. Esto indica que el mismo software se utiliza en diferentes dispositivos también.

La fuga

Aunque este problema se encontró al final, es crucial para la explotación real de la mayoría de los demás, porque se derivan del uso de funciones de cadena inseguras del lenguaje C. Si bien existen varias técnicas que se pueden utilizar para una ejecución de código exitosa en escenarios similares, la aplicación está creada de tal manera que resultan mayormente inútiles. El problema principal es que el código y los datos de Alloca se asignan estáticamente en direcciones bajas ( <&nbsp;0x01000000). Por lo tanto, los intentos de reutilizar código existente (es decir, ROP y similares) no son útiles, ya que requieren la capacidad de escribir direcciones en la memoria del programa. Debido a que las cadenas en C usan \x00 como carácter de terminación, y las funciones de cadena finalizan el procesamiento en el primer byte de este tipo, no es posible usar más de un solo byte NULL. Además, la ubicación de la pila está aleatorizada y la aplicación tiene múltiples hilos de ejecución, lo que hace que otras técnicas sean mucho menos confiables.

Esta vulnerabilidad es el resultado de compartir datos entre múltiples hilos y el uso inseguro de strcpy. Si bien he analizado este problema en particular durante mucho tiempo, no había visto la oportunidad de usarlo como vector de fuga de datos hasta solo unas pocas semanas antes de esta publicación. Curiosamente, gracias a la fuga de la dirección del montón de un objeto C++, esta vulnerabilidad también permite la ejecución remota de código. Sin embargo, este ataque no está incluido en este informe.

La aplicación Alloca puede actualizarse a través de FTP. Esta operación puede ser solicitada por un servidor, que también proporciona el nombre de usuario, contraseña y nombre de archivo necesarios. La función que inicia la actualización se muestra aquí: Llamadas strcpy vulnerables

Tres llamadas a strcpy son obviamente inseguras y conducen a un desbordamiento del montón, ya que el objeto ftpUpgrade se asigna dinámicamente. Desafortunadamente, el orden en que se realizan las copias y la disposición de la estructura ftpUpgrade hacen imposible realmente iniciar un hilo que filtre datos. Al observar más de cerca el paquete entrante se revela la siguiente estructura:

root@kitploit:~
struct ftp_upgrade_pkt {
	struct pktHeader;
	char username[16];
	char password[16];
	char filename[128];
}

mientras que el objeto ftpUpgrade se ve algo así:

root@kitploit:~
struct CNetClientFtpUpgrade {
	// ... algo aquí
	char filename[128];
	char unknown[6];
	char username[16];
	char password[16];
	CFtpDownlad *;
	CNetClientConnect*;
	int something[5];
	bool threadRunning;
	// ... y más
}

La fuga puede ocurrir después de que uno de los punteros internos (CFtpDownload*, CNetClientConnect*) sea completado por la aplicación. Además, el nombre de usuario y la contraseña se copian (una vez más, pero de forma segura esta vez) al objeto recién creado antes de que su puntero se almacene en la ubicación filtrable, por lo tanto, la fuga solo puede ocurrir con filename. Como resultado, el nombre de archivo debe ser muy largo, pero debido al orden y al comportamiento de terminación de strcpy, el nombre de archivo suficientemente largo resultará en un nombre de usuario y contraseña aún más largos, lo que en efecto sobrescribirá threadRunning y no iniciará un hilo en absoluto.

Si este código fuera de un solo hilo, no se podría hacer mucho. Pero como el nuevo hilo FtpDownload se genera y ejecuta la función DownloadFile, presenta una oportunidad interesante, ya que comparte el objeto CNetClientFtpUpgrade con el hilo que maneja los paquetes entrantes. No solo tiene múltiples operaciones de E/S que pueden controlarse externamente (solicitudes DNS, procesamiento de conexión FTP), sino que también intenta conectarse al FTP hasta 10 veces (esto se hace en el llamador de DownloadFile). Esto permite controlar la ejecución del hilo FtpDownload (bloqueándolo en operaciones de E/S), dando así tiempo al hilo de manejo de mensajes para procesar otras solicitudes.

Función DownloadFile que permite filtrar la dirección del montón

En resumen, simplemente enviando múltiples solicitudes de actualización, es posible cambiar el filename (y otros parámetros) utilizado por el hilo FtpDownload ya en ejecución y recibir la dirección del montón filtrada. Como beneficio adicional, la función FtpSize (marcada en verde) utiliza el búfer dentro del objeto referenciado por la dirección filtrada para almacenar el filename en sí mismo, lo que permite una inyección trivial del primer shellcode de etapa. La única limitación aquí son la longitud y la falta de bytes NULL, debido al uso de strcpy. Se proporciona un PoC de muestra que simplemente filtra una dirección del montón del dispositivo.

CVE-2020-25782

Desbordamiento de búfer basado en pila no autenticado en la función CNetClientManage::ServerIP_Proto_Set

La completa falta de autenticación en el manejo del tráfico entrante me llevó a buscar manejadores de paquetes. Una de las funciones interesantes es ServerIP_Proto_Set. Parece que se utiliza para crear una sobrescritura estática para la resolución de DNS. No he encontrado una forma de redirigir el tráfico de esta manera, pero hay otro desbordamiento de búfer aquí (marcado en naranja).

ServerIP_Proto_Set

Los datos, que se leen directamente del paquete, se utilizan dentro de la función sprintf. En este caso se asume que los datos del paquete cabrán en un búfer de 16 bytes, pero el uso de %s simple permite escribir tantos bytes como se desee, siempre que no contengan NULL.

Esta vulnerabilidad es bastante limitada. Aunque es posible escribir muchos datos en la pila, por lo que usar un NOP-sledge podría funcionar, no es posible escribir bytes NULL. Incluso intentar escribir un solo byte NULL fallará, ya que la función sprintf lo precede con un \n. Otro obstáculo es un objeto CMutex que se almacena después del búfer. Cualquier intento de desbordamiento debe llenar este mutex con un valor correcto (o al menos uno que satisfaga el destructor de CGuard

  • marcado en rojo). Esto es problemático, ya que el destructor desreferencia la variable pasada dos veces y luego usa su valor en la llamada a pthread_mutex_unlock. Después de algunas pruebas, descubrí que un búfer lleno de NULLs es suficiente para regresar correctamente de pthread_mutex_unlock, pero aún así necesitaba ser desreferenciado a una dirección de memoria adecuada.

La fuga viene al rescate. El ataque es un poco complejo, ya que necesitamos una dirección del montón que no contenga bytes NULL. Afortunadamente, la búsqueda se facilita, ya que el dispositivo nos proporciona la capacidad de realizar un reinicio remoto no autenticado. Cada vez que se asigna un espacio de direcciones del montón diferente. Por lo tanto, es posible simplemente reiniciar el dispositivo y filtrar una dirección hasta que se encuentre una adecuada. Convenientemente, esto también permite almacenar una primera etapa corta del shellcode. Como necesitamos superar el problema del mutex (se necesita un puntero a un puntero), filtramos otra dirección, esta vez pasando una dirección previamente filtrada como el nombre de archivo. El siguiente diagrama muestra la disposición de memoria esperada:

Disposición de memoria filtrada

Si todo sale según lo planeado, es posible pasar una segunda dirección como el mutex y la primera como dirección de retorno. Sin embargo, esto no es necesario para simplemente hacer fallar una aplicación como lo hace el PoC.

CVE-2020-25783

Desbordamiento de búfer basado en montón no autenticado en la función CNetClientTalk::OprMsg

Se supone que el dispositivo permite la comunicación de voz bidireccional. Otro manejador de paquetes entrantes parece responsable de recibir y reproducir audio. El paquete de red audio_pkt_hdr se describe mediante la siguiente estructura:

root@kitploit:~
struct audio_pkt_hdr {
	struct pktHeader field_0x0;
	int field_0x14
	int field_0x18
	int field_0x1c
	char audioBuff[0x140];
}

Uno de los campos de la estructura pktHeader es la longitud del paquete (tal como se transfiere a través de la red). Este campo puede ser configurado libremente por el remitente. La parte vulnerable es la copia de datos directamente del paquete entrante usando un valor de longitud no confiable proporcionado en el encabezado del paquete entrante.

Manejo de paquete de audio

Como se puede ver, el objeto CNetClientTalk se crea con el siguiente constructor:

Constructor de CNetClientTalk

por lo que la llamada anterior a memcpy resulta en un desbordamiento del búfer en el montón. Desafortunadamente, la explotación real de este problema es bastante difícil. Aunque es posible sobrescribir repetidamente el montón, no he encontrado una manera de controlar qué datos se almacenarán en el montón después del búfer que se desborda. Como la aplicación tiene más de 50 hilos activos, algunos de ellos responsables de procesar audio y video, está constantemente asignando y liberando memoria. Esto da como resultado que los datos del montón cambien constantemente, lo que dificulta predecir qué se almacena después del búfer y sobrescribirlo correctamente.

CVE-2020-25784

Desbordamiento de búfer basado en pila no autenticado en la función CNetClientGuard::SubOprMsg

Aquí hay otro manejador de paquetes entrantes. Esta vez el paquete de red tiene la siguiente estructura (el encabezado de paquete común se omite):

root@kitploit:~
struct pkt_hdr_sub_cliGuard {                            
  dword deviceId;                                 
  dword userId;                                  
  dword magic;                                  
  dword subCmd;                                  
  dword field_0x10;                                
  dword field_0x14;                                
  dword field_0x18;                                
  dword field_0x1c;                                
  dword guard_icommand;                              
  dword moreThenRandomStackValue;                         
  dword itemCnt;                                 
  char array_of_0x18[24];                             
};              

Nuevamente, la parte interesante es el último arreglo (ya que podemos crecer este paquete tanto como queramos), que contiene alguna estructura interna de tamaño 24. La vulnerabilidad surge de la suposición de que el itemCnt recibido no excederá 6, porque el búfer de destino de la copia tiene un tamaño de 144 (=24*6), que es visible en el siguiente listado (resaltado en naranja):

Vulnerabilidad en la función Guard OprMsg

Esta vez la copia se realiza usando memcpy (resaltado en verde), por lo que no hay límite en los caracteres permitidos. La copia se realiza en fragmentos, mediante un bucle while (marcado en azul). Vale la pena notar que el contador cnt_v0 disminuye dentro del bucle, por lo que los fragmentos se copian en orden inverso. Incluyendo las variables que siguen al búfer vulnerable buf, el desbordamiento necesita tener 256 bytes, luego 4 registros ($s0-$s3) y $ra. Debido a que no tenemos conocimiento del diseño de la memoria, el código PoC utiliza una técnica ROP. Se usa un solo gadget, que reproduce uno de los sonidos integrados del dispositivo (y falla).

CVE-2020-25785

Desbordamiento de búfer basado en pila no autenticado en la función CFtpProtocol::FtpLogin

Una de las direcciones iniciales de mi análisis fue buscar el procedimiento de actualización. Como descubrí, el dispositivo tiene una funcionalidad de actualización por FTP, que puede ser iniciada enviando una solicitud de actualización y resulta en la descarga del firmware desde un sitio FTP externo. Al igual que con otras vulnerabilidades, no es necesario autenticarse antes de solicitar la actualización del dispositivo. El análisis en profundidad de la funcionalidad ftp descubrió un desbordamiento de búfer basado en pila en la función CFtpProtocol::FtpLogin. Como podemos ver en el listado descompilado a continuación, la función pasa un arreglo char de tamaño 256 a la función FtpPwd.

Vulnerabilidad oculta en la función FtpLogin

FtpPwd se usa para obtener el directorio de trabajo actual del servidor FTP. Carga su búfer interno con hasta 1500 bytes de respuesta y luego los copia al búfer proporcionado. Esta secuencia de llamadas resulta en un desbordamiento de 1242 bytes. En este caso, los caracteres permitidos son muy limitados, ya que el uso de " (comillas dobles) resultaría en acortar la cadena de entrada (se usa strchr para buscar char en una cadena C) y no desbordaría el búfer. Afortunadamente, solo es necesario entregar una única dirección, a la que se redirigirá la ejecución del código.

Función FtpPwd vulnerable

Para explotar esta vulnerabilidad, es necesario controlar el DNS o redirigir (o hacer MitM) la conexión al servidor FTP. La aplicación no tiene protecciones modernas, por lo que es posible ejecutar el código directamente desde la pila. Sin una fuga de dirección, lo mejor que se puede hacer es adivinar la ubicación de la pila o redirigir la ejecución a una única función, que luego hará fallar la aplicación. Mis primeros intentos fueron precisamente eso, reproducir uno de los sonidos integrados, que se proporciona como PoC. Usando la fuga, es posible obtener el control total del dispositivo.

Cronología

  • Abril 2020 - Se descubrieron las vulnerabilidades
  • Junio 2020 - Primer intento fallido de contactar al fabricante (Accfly)
  • Julio 2020 - Segundo intento fallido de contactar al fabricante (Accfly)
  • Septiembre 2020 - Solicitud de asignación de CVE
  • Enero 2021 - Divulgación completa de las vulnerabilidades

Agradecimientos

  • Michał 'Michoo' Madziar por su magia con el soldador y por extraer el firmware
  • _0kami por los scripts y consejos muy útiles de ghidra
  • tzdybal por revisar el borrador de este documento
Descargar herramienta