Postřehy z bezpečnosti: i LED diody mohou zradit

27. 2. 2017
Doba čtení: 4 minuty

Sdílet

Ilustrační obrázek
Autor: Depositphotos – stori
Ilustrační obrázek
V dnešním díle našeho seriálu se podíváme na útok pomocí LED kontrolek, varování výrobce před špehujícími televizemi, užitečný nástroj na ochranu MongoDB databáze a nové vyděračské finty autorů ransomwaru a další.

Sofistikovaný útok, jako vystřižený z hollywoodského filmu, vyzkoušeli naživo v rámci bezpečnostního výzkumu vědci z Ben-Gurion university of Negev. Výzvou pro autory bylo získání dat z izolovaného, offline počítače. Autoři pro tento účel vytvořili speciální malware, který je schopen převzít kontrolu nad LED kontrolkami obvykle indikujícími činnost pevného disku a dokáže je zapínat a vypínat rychlostí vyšší než je člověk schopen zrakem rozlišit – až 5800 bliknutí za sekundu. 

Při reálném testu útoku, trefně nazvaného LED-it-GO, pak výzkumníci vyslali na místo dálkově řízený dron s různými typy kamer, od speciálních průmyslových až po obyčejné běžně dostupné kamery GoPro. Po navázání vizuálního kontaktu, bylo možné zahájení samotného přenosu. Přenos samotný probíhal binárně – zhasnutá LED dioda reprezentovala binární 0, rozsvícená 1. Dle autorů závisí rychlost přenosu především na vzdálenosti a kvalitě přijímače, ale v ideálních podmínkách je možné dosáhnout rychlosti až 4000 bitů/s (0,5 KB/s).  

Přestože autoři útok úspěšně demonstrovali, je třeba dodat, že se nezabývali otázkou jak vlastně do takového počítače malware dostat. Další překážkou by byl nejspíš také fakt, že podobné „air-gapped“ stanice bývají v reálném světě umísťovány v izolovaných místnostech bez oken.

Naše postřehy

Společnost NeoSmart Technologies v minulém týdnu upozornila na kampaň šířící malware v podobě trojského koně či ransomware Spora. Útočníci napadají špatně zabezpečené webové stránky, do kterých vkládají JavaScript, který z textu na stránkách vytvoří změť nesmyslných znaků. Pokud přijde na takovou stránku uživatel prohlížeče Google Chrome, je mu zobrazeno okno s informací "The ‚HoeflerText‘ font wasn't found” a výzvou k updatu balíčku fontů pro Chrome. Netřeba dodávat, že stažený soubor Chrome Font v7.5.1.exe místo “potřebného” fontu přináší výše zmiňovaný malware.

Samsung varuje zákazníky před soukromými konverzacemi před svými chytrými televizemi. Tato informace byla nalezena v přiložených zásadách ochrany soukromí (privacy policy). Poté, co na tento fakt jeden ze zákazníků upozornil, vydal Samsung prohlášení, že se třetí stranou (Nuance Communications, Inc.) sdílí pouze část hlasového záznamu, sloužící uživateli pro vyhledání obsahu.

Není to tak dávno, co proběhla vlna útoků na databáze MongoDB. V mnoha případech, bylo po správcích databází výměnou za navrácení dat požadováno výkupné, často však byly databáze nenávratně smazány. Útoky využívaly toho, že mnoho MongoDB instalací má nastavení ponecháno ve výchozím stavu, ve kterém jsou zranitelné. Tento fakt inspiroval autory nástroje Mongoaudit, což je CLI nástroj, který poslouží správci databáze jako jakýsi průvodce a auditor zabezpečení jeho databáze a testuje databázi na celý seznam možných zranitelností.

Scott Helme ve svém článku nastínil další možnost ochrany proti Cross-Site Request Forgery. Popisuje SameSite atribut cookie, který dá pokyn prohlížeči, že cookie má jistou ochranu. V striktním módu prohlížeč nepošle cookie v žádném požadavku mimo původní doménu, protokol a číslo portu („origin“). V laxním módu může prohlížeč poslat cookie jen přes bezpečnou HTTP metodou; to jsou podle RFC 7321 metody GET, HEAD, OPTIONS a TRACE. Na stránce caniuse.com můžeme vidět podporu SameSite atributu v prohlížečích. Prohlížeč Google Chrome atribut podporuje od v51, naopak Mozilla Firefox ho zatím nepodporuje vůbec.

Tvůrci ransomware zkoušejí různé způsoby, jak si domluvit dostaveníčko s obětí. Malware Lockdroid nedávno experimentoval s čárovým kódem, který oběť měla naskenovat, aby se dověděla, kde má zaplatit výkupné. Nyní Lockdroid dělá jiný experiment – oběť se dozví nickname anonymního účtu na instant messaging službě Tencent QQ, kde se spojí s útočníkem, vyhandluje cenu a dostane kód, který do svého zablokovaného telefonu namluví. Poprvé se tak u tohoto typu kriminality setkáváme s využitím text-to-speech. Doufejme, že po nás útočníci brzy nebudou chtít kvůli odemčení dat zazpívat čínskou hymnu nebo zatancovat twerk. Neinstalujte na Androidu aplikace z jiného než oficiálního Play Store!

bitcoin_smenarna

Chyba, která si v linuxovém jádru (nejspíš) netušeně žije již 11 let, byla opravena. Tuto chybu bylo možné ještě před pár dny zneužít k lokálnímu spuštění libovolného kódu v kontextu kernelu následovně vedoucí třeba k eskalaci privilegií či DoS. Náprava v jádře byla provedena 18. února a například linuxová distribuce Ubuntu patch ihned převzala a má k dipozici aktualizaci.

Ve zkratce

Pro pobavení

Závěr

Tento seriál vychází střídavě za pomoci pracovníků Národního bezpečnostního týmu CSIRT.CZ provozovaného sdružením CZ.NIC a bezpečnostního týmu CESNET-CERTS sdružení CESNET.

Neutrální ikona do widgetu na odběr článků ze seriálů

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


Autor článku

Národní bezpečnostní tým CSIRT.CZ je provozován sdružením CZ.NIC. Podílí se především na řešení incidentů týkajících se kybernetické bezpečnosti v sítích provozovaných v České republice.

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }