2 puntos por GN⁺ 2023-08-24 | 1 comentarios | Compartir por WhatsApp
  • Discord, una app de escritorio basada en Electron, funciona internamente como una ventana de Chromium, por lo que es posible abrir las herramientas para desarrolladores web y modificar código del lado del cliente
  • Algunos clientes modificados y plugins desbloquean del lado del cliente parte de las funciones que requieren una suscripción paga a Nitro
  • La clave está en inyectar módulos divididos mediante code splitting de Webpack en la variable webpackChunkdiscord_app para explorar y reemplazar funciones internas
  • La función que verifica la calidad de compartir pantalla se valida solo en el cliente y puede eludirse, pero los temas premium además activan una verificación de sincronización en el servidor
  • Todas las técnicas de la demo son una violación de los Términos de Servicio de Discord, con riesgo de suspensión de la cuenta y de robo de cuenta por ejecutar código no verificado

Panorama general

  • Existen numerosos clientes modificados de Discord que cambian la apariencia o agregan funciones, y algunos plugins incluso desbloquean funciones que requieren una suscripción paga a Nitro
  • Se explica el principio técnico que hace posible este comportamiento mediante el análisis de la estructura del cliente

Activación de las herramientas para desarrolladores

  • Discord está desarrollado con el framework Electron, que permite crear apps multiplataforma con tecnologías web, por lo que es similar a un sitio web que se ejecuta dentro de un navegador web
  • En esencia, es una ventana de Chromium, así que se pueden abrir las herramientas para desarrolladores, aunque vienen desactivadas de forma predeterminada
    • Se bloquearon porque hubo muchos casos en los que usuarios pegaron comandos maliciosos por ingeniería social de actores de amenazas y terminaron con sus cuentas robadas
  • Si se comprenden los riesgos, se puede activar agregando el valor DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING como true en el archivo de configuración %appdata%/discord/settings.json
    • Luego se abre la consola de desarrollo con ctrl + shift + i

Parchar funciones de Discord

  • Para optimizar la carga inicial, el código se divide en varios chunks que se cargan en paralelo o de forma diferida (lazy-loaded), usando la función de code splitting de Webpack
  • Todos los chunks cargados se guardan en la variable webpackChunkdiscord_app
  • Para ejecutar código que use variables y funciones de Discord, hay que inyectar (inject) código en esta variable
    • a.c es un objeto que contiene todos los módulos, y cada módulo tiene la forma chunk_id, loaded, exports
    • exports contiene las funciones, objetos y valores primitivos exportados por el módulo
  • Es posible crear una función find que recorra varios módulos JavaScript para localizar y llamar una función específica
    • Ejemplo: buscar y llamar la función getCurrentUser()
  • Se puede cambiar el comportamiento reemplazando (replace) la función original por otra, lo que permite modificar directamente el código

Desbloqueo de streaming en alta calidad

  • El contenido a partir de este punto viola claramente los Términos de Servicio de Discord y puede llevar a la suspensión de la cuenta, por lo que implica asumir el riesgo
  • Las dos funciones canStreamMidQuality y canStreamHighQuality, que verifican el nivel de suscripción del usuario, se llaman justo antes de la pantalla de selección de calidad para compartir pantalla
    • Si se fuerza el valor de retorno de ambas funciones a true, se puede seleccionar compartir pantalla en resolución original a 60 FPS incluso sin estar suscrito a Nitro
  • Actualmente, Discord parece no verificar en el servidor si el stream transmitido realmente cumple con los límites para usuarios no suscritos
    • Sin embargo, Discord todavía no usa cifrado de extremo a extremo (End-to-End encryption), por lo que existe la posibilidad de detección
    • Según el artículo de referencia, Discord ya inspecciona el contenido de audio y video de los usuarios, y podría agregar en el futuro una verificación del lado del servidor antes de compartir pantalla

Desbloqueo de temas premium

  • Si se cambia a true el valor de la función canUseClientThemes, que devuelve si el usuario puede usar temas de Nitro, se desbloquea el botón para seleccionar temas premium
  • Sin embargo, después de aplicarse por un momento, el tema vuelve enseguida al tema predeterminado
    • Esto ocurre porque el cliente intenta guardar el cambio de tema, pero el servidor verifica que no tiene permisos y, al recibir la respuesta, vuelve a aplicar el tema predeterminado
  • Si se parchea la función shouldSync para bloquear solo la sincronización de configuración de apariencia y hacer que devuelva false cuando el valor sea appearance, el cambio de tema se mantiene
  • Los temas se gestionan completamente del lado del cliente y siempre es posible modificar directamente el CSS, por lo que es difícil que Discord lo impida

Conclusión

  • Existe código que permite aplicar fácilmente los hacks demostrados, pero es importante ser prudente antes de modificar el cliente o usar mods
  • Discord puede suspender en cualquier momento cuentas que violen sus Términos de Servicio, y ejecutar código no verificado con acceso a la cuenta es muy peligroso
    • Mensaje codificado en el artículo: "No pegues en la consola de desarrollo código que no entiendas — es la forma más fácil de que te roben la cuenta"

1 comentarios

 
GN⁺ 2023-08-24
Opiniones en Hacker News
  • Creo que si basta con ejecutar un simple blob codificado en base64 pegado al final para activar todas las funciones, podría convertirse en un vector de ataque bastante fácil.
    No quería decir que sospechara del autor; lo acabo de decodificar y caí redondito.

    • Para quienes no tengan ganas de correr base64 --decode, este es el resultado:
      // Here's a cake if you thought about inspecting the code before executing it:
      let css = 'font-size: 36px; font-weight: bold; color: red';
      console.log("%cNEVER paste code you don't understand into the development console.", css);
      console.log("%cThis is the best way to compromise your account.", css);
  • “Actualmente, Discord no parece verificar en el servidor que el stream que se está transmitiendo realmente cumpla con los criterios para no suscriptores”; me pregunto quién pensó que esa era una buena implementación.
    La validación del lado del cliente de verdad parece un error de principiante.

    • Probablemente no fue tanto “esta es una implementación excelente”, sino más bien “si alguien descubre cómo romperlo, lo parcheamos entonces”.
      Llevo años usando Discord y es la primera vez que oigo de un intento de eludir la estructura de permisos de Nitro; si no es algo muy extendido, tampoco parece haber mucha razón para preocuparse.
    • No tengo idea de por qué lo hicieron, ya que estoy en la posición de implementar solo funciones terminadas, exactamente en su forma final deseada, y subir el PR.
      Por otro lado, este mes empecé mi quinto trabajo nuevo, así que parece que simplemente no me llevo nada bien con los project managers.
    • Considerando lo fácil que gasta dinero la gente hoy, especialmente los niños, puede que con eso sea suficiente.
      Me pregunto cuánta gente entiende este tipo de hack y además estaría dispuesta a pagar Nitro. Seguramente hay miles, quizá decenas de miles, de personas usando varios mods de cliente de Discord que activan algunas o todas las funciones de Nitro, pero tengo dudas de cuánto ingreso real generaría bloquear eso.
      Personalmente, si necesito o quiero esa función, es mucho menos molesto pagar 10 dólares al mes. Me parece mejor que estar siguiendo mods que se van a romper con cada actualización de Discord y esperar que el mantenedor no meta código malicioso.
    • A través de la API también se pueden ver los nombres, temas y la hora del último mensaje de canales ocultos.
      Los canales solo están ocultos en el cliente. Para ser claros, aun así eso no permite ver el contenido de los mensajes de esos canales.
    • Esto se debe a que no es un componente de la API de Discord, sino de los servidores de voz desplegados por cientos en todo el mundo.
      El servidor de voz solo confirma con la API si tienes permiso para entrar y, después de eso, funciona como un broadcaster de paquetes de uno a muchos.
  • Esto se acerca más al hacker clásico, en el sentido de alguien curioso y hábil.
    No hay daños graves y nos recuerda que las apps no son magia y que el código es genial.

    • Quizá esté más cerca de un “cracker”, pero coincido en que es el tipo de conocimiento que las empresas preferirían que no tuviéramos.
      Así pueden intentar exprimirnos más dinero sin resistencia.
  • Recordatorio: todo lo que envías por Discord, incluidos los DM, queda registrado en texto plano en Discord y queda accesible para Discord y para quien compre la empresa.
    En algún momento parecía que Microsoft la compraría, y ahora parece encaminarse a una IPO.
    El simple hecho de tener una cuenta normaliza conversaciones privadas fáciles de minar para IA o de usar por Discord y por administradores de bases de datos/sistemas. La Section 702 de la FISA Amendments Act (FAA702) permite que agencias federales de investigación accedan a esos datos sin orden judicial.
    Solo la posibilidad de front-running de criptomonedas podría valer decenas de millones de dólares al día.
    Si eres amigo de alguien, no deberías recomendarle usar un sistema de chat sin cifrado de extremo a extremo. No seamos miel dentro de una trampa.

    • Recordatorio: todo lo que envías a un foro, incluidos los DM, queda registrado en texto plano y accesible para los administradores.
      Es lo esperable salvo que uses uno de los pocos servicios que implementan un verdadero modelo zero trust donde el usuario gestiona sus propias claves. La razón por la que se guardan los mensajes es para que los usuarios puedan volver a acceder a ellos.
      Hay servicios como Matrix que logran mensajería grupal con cifrado de extremo a extremo de una forma relativamente amigable, pero son la excepción. No es justo presentar a Discord como especialmente malicioso solo por hacer lo mismo que ha hecho el 95% de las plataformas de comunicación electrónica.
    • Dicen que “el simple hecho de tener una cuenta lo normaliza”, pero eso ya se normalizó hace mucho y Discord ganó.
      No digo que sea bueno, pero en algunas comunidades no hay alternativa salvo no participar.
      Es peor que el viejo “todo el mundo usa WhatsApp”. En ese caso tenías el número de la otra persona y era fácil contactarla por otros medios, pero el atractivo de Discord no son las conversaciones privadas, sino las comunidades con espacios semipúblicos. Aquí “público” no significa abierto para todos, sino algo más cercano a que lo leen unas 100 personas.
    • Por suerte, Discord tiene eliminación de mensajes sin dejar rastro.
      Cuando borras un mensaje, ya no queda almacenado en la base de datos.
  • Hace poco OpenAI desactivó de golpe el Discord para beta testers, así que ya no podemos ver con quién hablábamos ni qué discutíamos.
    Me preguntaba si habría alguna forma de exportar el chat para que los administradores del servidor no pudieran cortar la comunidad entre sí sin dejar siquiera una forma de revisar el historial.
    Hay bastantes extensiones de Chrome para exportar chats de Discord, pero parece que la mayoría bloquea algunas funciones detrás de un pago.
    Resultó que era muy fácil copiar el código fuente de la extensión desde la carpeta de Chrome, modificar en JavaScript una comprobación booleana como is_pro y volver a cargarla como extensión descomprimida.

  • Aunque advierten correctamente que puedes ser baneado por usar estos trucos, ¿hay algún antecedente de que Discord haya baneado usuarios por algo así?

    • Discord no tiene reparos en banear gente por cualquier motivo.
      También bloquean el uso de clientes alternativos. Si tu cuenta es importante, mejor no meterse con Discord.
    • El README de Vencord, uno de los mods más populares, dice esto:
      “Modificar el cliente va contra los Términos de Servicio de Discord.”
      Dicho eso, a Discord parece importarle bastante poco, y no hay casos conocidos de baneos por usar mods de cliente. Así que, mientras no uses plugins que implementen abuso, en general deberías estar bien. No tienes que preocuparte: dicen que todos los plugins integrados son seguros.
  • Entiendo que algunos temas se activen de esta manera, pero es bastante difícil entender que hayan hecho que la calidad del streaming se decida con una comprobación del lado del cliente y no del servidor.

    • Sobre todo porque basta con revisar el bitrate de entrada y salida.
      Ni siquiera necesitas acceder al video real; aunque esté completamente cifrado, viendo la cantidad de datos transmitidos puedes saber en qué calidad se está streameando.
  • La gran regla de la ingeniería frontend vuelve a cumplirse:
    “Nunca, jamás confíes en el cliente”.

  • Desde que vi que se podía manejar solo del lado del cliente, he estado usando las herramientas de desarrollo para activar el botón de streaming 1080p60, y de hecho funciona.
    No sé cuántos años van ya, pero parece que a nadie en Discord le importa.

  • Hace tiempo intenté seguir este camino, pero al final me rendí porque no encontré una forma consistente de parchear el cliente, especialmente después de las actualizaciones.
    Pero al ver este método me vuelve la tentación de “abrirlo y pincharlo”.
    ¿Hay alguna forma sencilla de recorrer la API disponible de esta manera? Intenté registrarlo todo, pero era un desastre por maps, internacionalización y demás. Me pregunto si alguien ya se tomó el trabajo de hacer algo como documentación de ingeniería inversa.