;(function() { window.createMeasureObserver = (measureName) => { var markPrefix = `_uol-measure-${measureName}-${new Date().getTime()}`; performance.mark(`${markPrefix}-start`); return { end: function() { performance.mark(`${markPrefix}-end`); performance.measure(`uol-measure-${measureName}`, `${markPrefix}-start`, `${markPrefix}-end`); performance.clearMarks(`${markPrefix}-start`); performance.clearMarks(`${markPrefix}-end`); } } }; /** * Gerenciador de eventos */ window.gevent = { stack: [], RUN_ONCE: true, on: function(name, callback, once) { this.stack.push([name, callback, !!once]); }, emit: function(name, args) { for (var i = this.stack.length, item; i--;) { item = this.stack[i]; if (item[0] === name) { item[1](args); if (item[2]) { this.stack.splice(i, 1); } } } } }; var runningSearch = false; var hadAnEvent = true; var elementsToWatch = window.elementsToWatch = new Map(); var innerHeight = window.innerHeight; // timestamp da última rodada do requestAnimationFrame // É usado para limitar a procura por elementos visíveis. var lastAnimationTS = 0; // verifica se elemento está no viewport do usuário var isElementInViewport = function(el) { var rect = el.getBoundingClientRect(); var clientHeight = window.innerHeight || document.documentElement.clientHeight; // renderizando antes, evitando troca de conteúdo visível no chartbeat-related-content if(el.className.includes('related-content-front')) return true; // garante que usa ao mínimo 280px de margem para fazer o lazyload var margin = clientHeight + Math.max(280, clientHeight * 0.2); // se a base do componente está acima da altura da tela do usuário, está oculto if(rect.bottom < 0 && rect.bottom > margin * -1) { return false; } // se o topo do elemento está abaixo da altura da tela do usuário, está oculto if(rect.top > margin) { return false; } // se a posição do topo é negativa, verifica se a altura dele ainda // compensa o que já foi scrollado if(rect.top < 0 && rect.height + rect.top < 0) { return false; } return true; }; var asynxNextFreeTime = () => { return new Promise((resolve) => { if(window.requestIdleCallback) { window.requestIdleCallback(resolve, { timeout: 5000, }); } else { window.requestAnimationFrame(resolve); } }); }; var asyncValidateIfElIsInViewPort = function(promise, el) { return promise.then(() => { if(el) { if(isElementInViewport(el) == true) { const cb = elementsToWatch.get(el); // remove da lista para não ser disparado novamente elementsToWatch.delete(el); cb(); } } }).then(asynxNextFreeTime); }; // inicia o fluxo de procura de elementos procurados var look = function() { if(window.requestIdleCallback) { window.requestIdleCallback(findByVisibleElements, { timeout: 5000, }); } else { window.requestAnimationFrame(findByVisibleElements); } }; var findByVisibleElements = function(ts) { var elapsedSinceLast = ts - lastAnimationTS; // se não teve nenhum evento que possa alterar a página if(hadAnEvent == false) { return look(); } if(elementsToWatch.size == 0) { return look(); } if(runningSearch == true) { return look(); } // procura por elementos visíveis apenas 5x/seg if(elapsedSinceLast < 1000/5) { return look(); } // atualiza o último ts lastAnimationTS = ts; // reseta status de scroll para não entrar novamente aqui hadAnEvent = false; // indica que está rodando a procura por elementos no viewport runningSearch = true; const done = Array.from(elementsToWatch.keys()).reduce(asyncValidateIfElIsInViewPort, Promise.resolve()); // obtém todos os elementos que podem ter view contabilizados //elementsToWatch.forEach(function(cb, el) { // if(isElementInViewport(el) == true) { // // remove da lista para não ser disparado novamente // elementsToWatch.delete(el); // cb(el); // } //}); done.then(function() { runningSearch = false; }); // reinicia o fluxo de procura look(); }; /** * Quando o elemento `el` entrar no viewport (-20%), cb será disparado. */ window.lazyload = function(el, cb) { if(el.nodeType != Node.ELEMENT_NODE) { throw new Error("element parameter should be a Element Node"); } if(typeof cb !== 'function') { throw new Error("callback parameter should be a Function"); } elementsToWatch.set(el, cb); } var setEvent = function() { hadAnEvent = true; }; window.addEventListener('scroll', setEvent, { capture: true, ive: true }); window.addEventListener('click', setEvent, { ive: true }); window.addEventListener('resize', setEvent, { ive: true }); window.addEventListener('load', setEvent, { once: true, ive: true }); window.addEventListener('DOMContentLoaded', setEvent, { once: true, ive: true }); window.gevent.on('allJSLoadedAndCreated', setEvent, window.gevent.RUN_ONCE); // inicia a validação look(); })();
  • AssineUOL
Topo

Falha no site do Detran-RS expôs RG e CNH de 5,1 milhões de motoristas

Estúdio Rebimboca/UOL
Imagem: Estúdio Rebimboca/UOL

Guilherme Tagiaroli

De Tilt, em São Paulo

29/01/2021 10h17

Uma falha recém-descoberta nos sistemas do Detran-RS (Departamento Estadual de Trânsito do Rio Grande do Sul) expôs informações pessoais de 5,1 milhões de motoristas. Era possível ar RG (identidade), número de CNH (Carteira Nacional de Habilitação), Renach (Registro Nacional de Carteira de Habilitação), multas e placas de carro, entre outros dados. Após o alerta feito por Tilt, a falha foi corrigida na quarta-feira (27).

É sempre bom reforçar que deixar dados pessoais sensíveis dando sopa por aí é algo bem sério e pode facilitar uma série de golpes. O criminoso pode usar seu RG para se inscrever em algum serviço e fazer compras em seu nome. Ou usar sua CNH para clonar seu veículo ou falsificar sua carteira de motorista.

Consultado pela reportagem, o Detran-RS informou num primeiro momento que a Procergs (Companhia de Processamento de dados do RS) está investigando o caso e que se pronunciaria após as análises de segurança. Após a publicação da reportagem, o departamento informou que conta com dispositivos de segurança para monitorar e bloquear tentativas de os irregulares (mais detalhes da nota podem ser encontrados mais abaixo).

Descoberta pelo técnico em redes Mateus Gomes e pelo pesquisador de segurança Jonathan Fonseca, a falha foi encontrada no Portal de Trânsito, um site do Detran-RS com serviços para os motoristas. Ao analisar o código, Gomes notou que era possível ter o a duas APIs (uma espécie de "interface de consulta") sem a necessidade de autenticação ( e senha). Uma API tinha detalhes dos motoristas, e outra, dados de veículos.

Do motorista:

  • Número de RG (identidade)
  • Número, validade, data de Emissão e tipo de categoria da CNH
  • Número do Renach
  • Endereço e telefone da Auto-Escola que a CNH foi retirada

Do carro:

  • Número da Placa
  • Modelo do Veículos
  • Renavam (Registro Nacional de Veículo)
  • Valores, local e hora da aplicação de multas

Tendo dados do RG de um condutor, um atacante poderia consultar essas informações e, a partir dela, fazer associações para obter outros dados sensíveis.

Segundo Gomes, o sistema não validava corretamente a origem das requisições —ou seja, qualquer pessoa com conhecimento técnico poderia ar dados privados sem nenhum tipo de identificação de segurança.

"Além de não validar corretamente a origem das solicitações, o sistema não possuía nenhum tipo de proteção contra ataques de força bruta ou limitador de requisições", explica o técnico em redes. Dessa forma, conclui ele, um atacante poderia testar diversas possibilidades até encontrar dados válidos de forma automatizada.

Após a publicação da reportagem, o Detran-RS enviou uma nota para Tilt informando que possui uma série de serviços de consultas e que é referência em transparência. O departamento ressalta que "o o à esta base de dados pressupõe que o interessado tenha, em mãos, dados pessoais (como RG, Renach ou CNH)" e que "não é possível a obtenção de dados sem essas informações anteriores".

Por fim, o órgão diz que conta com uma "série de dispositivos de segurança que monitoram e bloqueiam eventuais os irregulares ou indevidos a essas informações.

Não há relatos ainda se esses dados foram obtidos por terceiros. Ao todo, o Estado do Rio Grande do Sul diz ter 5,1 milhões de CNHs de condutores.

Problemas à parte, resta saber se os responsáveis pelas informações dos dados do Detran-RS irão cumprir aquilo que está previsto na LGPD (Lei Geral de Proteção de Dados), que inclui uma advertência ou divulgação da infração pela ANPD (Autoridade Nacional de Proteção de Dados).