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

Uma pequena empresa de cibersegurança resolveu a briga entre FBI e Apple

Um iPhone 5c, celular da Apple, foi tema de investigação do FBI em 2015 - Glenn Chapman/AFP
Um iPhone 5c, celular da Apple, foi tema de investigação do FBI em 2015 Imagem: Glenn Chapman/AFP

Colaboração para Tilt, em São Paulo

15/04/2021 18h50

Uma pequena empresa de cibersegurança australiana chamada Azimuth foi a responsável por desbloquear oiPhone 5C de Syed Rizwan Farook, um dos terroristas por trás das 14 mortes a tiros em uma festa em San Bernardino (EUA) em dezembro de 2015. Na época, a Apple se recusou a desbloquear o aparelho para o FBI, agência da investigação do país.

Segundo reportagem do "Washington Post" publicada nesta quarta-feira (14), para conseguir esse feito, a Azimuth criou uma sequência de "exploits", programas criados para aproveitar vulnerabilidades de sistemas.

Mark Dowd, fundador da empresa, havia encontrado uma falha em um código-fonte criado pela Mozilla —fundação sem fins lucrativos e dona do navegador Firefox— que a Apple usava no iPhone, para permitir que órios fossem conectados à porta Lightning do aparelho. David Wang, um especialista em iOS da Azimuth, aproveitou essa falha para entrar no sistema do iPhone 5C de Farook.

Quando já estava lá dentro, Wang usou em sequência mais dois "exploits": um de autoria sua, e outro criado por outro pesquisador da Azimuth, para finalmente ter o total ao processador do iPhone bloqueado. Mas ainda faltava mais um o para ar o conteúdo interno dos aplicativos: um software que testava todas as combinações possíveis de senha enquanto desviava dos recursos de segurança do iOS 9 —especialmente o que apagava os dados do celular. Depois de ser experimentada em vários iPhones 5C e funcionar, a sequência de "exploits" foi chamada de Condor.

Com tudo pronto, a Azimuth mostrou ao FBI como desbloquear o iPhone 5C. O FBI pagou US$ 900 mil pela solução. Mas quando foi desbloqueado, o celular de Farook não tinha nada importante para a investigação.

Pouco depois de os agentes do FBI desbloquearem o telefone, a Mozilla corrigiu a falha em seu sistema em uma atualização de rotina. Com isso, todos os clientes da empresa ficaram imunes ao "exploit" da Azimuth - o que o tornou inútil.

Disputa nos tribunais

Em 2015, a Apple alegou que abrir para o FBI um backdoor no iPhone —isto é, uma entrada forçada ao sistema do celular— enfraqueceria a segurança dos aparelhos. O caso foi parar na Justiça: uma ordem determinou que a empresa colaborasse com o desbloqueio, mas a Apple recorreu. Para não perder ainda mais tempo, o FBI contratou a Azimuth.

Depois de tudo, a Apple tentou contratar Wang, mas ele preferiu cofundar a Corellium. A empresa desenvolve ferramentas para pesquisadores de segurança: são iPhones virtuais que podem ser usados para testes no sistema operacional da Apple.

Em 2019, a Apple processou a Corellium por violação de direitos autorais. Em dezembro de 2020, o juiz Rodney Smith, de Fort Lauderdale, na Flórida, rejeitou os pedidos. Segundo ele, os iPhones virtuais são usados para encontrar falhas de segurança e não competem com as vendas da Apple.

A Apple ainda pode apelar da decisão e já adicionou mais uma reclamação: as ferramentas da Corellium burlam suas medidas de segurança. A briga entre eles parece ainda estar longe de terminar e o julgamento está programado para o meio do ano.