25.1.2016
Obvyklým přístupem pro přihlašování k webové aplikace je vyžádání jména a hesla uživatele. Při použití obyčejného nezabezpečeného protokolu HTTP je zde samozřejmě riziko, že kdokoliv po cestě může odposlechnout vaše heslo. K odposlechutí hesla stačí jednoduchá aplikace typu tcpdump nebo wireshark, které lze snadno nainstalovat na libovolný počítač.
To pochopitelně není dobře - nechcete samozřejmě, aby vám neznámý útočník s pomocí odposlechnutého hesla vyplundroval bankovní účet. Bankovní aplikace nevyrábíme, ale nepříjemné může být třeba i jen to, že vám někdo přestaví vaši domácí Wifi. Proto je dobrým zvykem choulostivá data tekoucí přes http spojení šifrovat.
O šifrovaném http serveru pro C++ a Qt jsem psal dříve:
Podpora SSL v HTTP serveru pro C++ a Qt
Pro šifrování spojení se běžně používá SSL. To vám dokáže nabídnout o cosi více, než jen šifrování. Pokud byste se spoléhali pouze na šifrování, byli byste prakticky ve stejné situaci, jako kdybyste hesla nešifrovali vůbec. Při odposlechu byste sice eliminovali nejjednodušší prostředky (pasivní poslouchání), ale proti počítačovému banditovi usazenému uprostřed vašeho internetového spojení byste byli stále bezmocní. Pro takového banditu by totiž bylo velmi jednoduché vydávat se za banku. Místo abyste se bavili s bankou, bavíte se ve skutečnosti s vetřelcem - vaše heslo k těžce vydělaným penězům je prozrazeno i na šifrovaném kanálu. Abyste předešli takové situaci, musíte mít jistotu, že se bavíte se skutečnou bankou. V reálném světě je to jednoduché - banku najdete vždy na svém obvyklém místě a úředník za přepážkou banky je celkem snadno k rozeznání od maskovaného lupiče. Na internetu tuto jistotu nemáte, ale můžete ji získat jinak.
Pokud chcete mít jistotu, že se bavíte skutečně s bankou, je potřeba zajistit obrazně řečeno dvě věci:
Roli občanky hrají ve světě počítačů SSL certifikáty a klíče. Platnost občanky (tj. vím, jak občanka vypadá, není padělaná) zajišťují certifikační autority.
Situace je oboustranná - stejným postupem, tedy kontrolou občanky, může banka ověřit, že jste skutečně ten, za koho se vydáváte.
Pokud se vám banka prokázala občankou a vy jste se prokázali občankou bance, je už celkem zbytečné vyžadovat nějaké další heslo. A to je další věc, kterou vám šifrované spojení přes SSL nabízí - je možné se přihlašovat k internetové aplikaci i bez hesel, pouze na základě certifikátu.
Server má několik konfiguračních parametrů, které vám dovolí nastavit šifrování:
[http] useSSL = true sslKey = /etc/ssl/private/mysite.bravenec.eu.key.pem sslCrt = /etc/ssl/private/mysite.bravenec.eu.crt.pem sslCaCrt = /etc/ssl/private/hobrasoft.crt.pem
Parametry sslKey a sslCrt by stačily pro vytvoření šifrovaného kanálu a přihlašování jménem a heslem (bez ověření klientského certifikátu). Další parametr, sslCaCrt, je potom certifikát, kterým by měl být podepsaný klientský certifikát, aby byl považován za důvěryhodný.
V programu používajícím hobrasoft httpd server pak stačí zavolat metodu HttpConnection::verified(), abyste zjistili, jestli certifikát vydala zadaná certifikační autorita. Třída HttpConnection má i další metody pro přístup ke klientskému certifikátu:
Prohlížečů existuje celá řada, postup nastavení si ukážeme pouze na Chrome:
Pro aplikaci běžící na serveru byste měli být tímto identifikovaní - pokud jste kontroler na straně serveru napsali tak, aby byl certifikát dostačující pro přihlášení, nemusí váš kontroler dále kontrolovat uživatelské jméno a heslo. Potřebné informace se dozví voláním metod peerCertificate() a commonName().
Curl je fikaná utilita pro přístup k http stránkám z povelové řádky. Utilitu používáme pro ladění různých webových API, kdy běžný prohlížeč nevyhovuje, protože toho umí zbytečně moc.
Volání na povelové řádce může vypadat třeba takto, na rozdíl od prohlíče Chrome vyžaduje curl klíč i certifikát ve formátu PEM:
curl \ --cacert hobrasoft.crt.pem \ --cert bravenec.crt.pem \ --key bravenec.key.pem \ -v -X GET https://weblight.bravenec.eu:8099/
V Qt aplikacích se pro přístup k http serverům využívá třída QNetworkAccessManager. Třída vyřizuje požadavky asynchronně, pro každý požadavek se vytváří samostatná instance třídy QNetworkRequest. Třídě QNetworkRequest se předává konfigurace SSL ve třídě QSslConfiguration:
QNetworkAccesManager *manager = new QNetworkAccessManager() // ... nastavení manageru - propojení signálů do obslužných slotů ... // V konfiguraci se použije výchozí nastavení QSslConfiguration configuration = QSslConfiguration::defaultConfiguration(); // Připojí se ale vlastní CA certifikáty místo systémových QListcaCertificates; QFile fileca("hobrasoft.crt.pem"); filecea.open(QIODevice::ReadOnly); caCertificates << QSslCertificate(fileca); configuration.setCaCertificates(caCertificates); // Připojí se klientský privátní klíč QFile filekey("bravenec.key.pem"); filekey.open(QIODevice::ReadOnly); QSslKey key = QSslKey(filekey); configuration.setPrivateKey(key); // Připojí se klientský certifikát QFile filecrt("bravenec.crt.pem"); filecrt.open(QIODevice::ReadOnly); QSslCertificate crt = QSslCertificate(filecrt); configuration.setLocalCertificate(crt); // Vytvoří se požadavek a připojí se konfigurace SSL QNetworkRequest request(QUrl("https://weblight.bravenec.eu:8099")); request.setSslConfiguration(configuration); // Požadavek se předá ke zpracování třídě QNetworkAccessManager QNetworkReply *reply = manager->get(request);
Použití třídy QNetwokAccessManager je zde pouze naznačeno - ve skutečnosti je její použití o cosi složitější a vydalo by na samostatný článek.
Tento postup bude fungovat pouze v případě, že je vše řádně nastaveno, certifikáty jsou platné a jméno serveru odpovídá jménu v certifikátu serveru.
Pokud se budete snažit připojit k https serveru pod jiným jménem, než je nastaveno v serverovém certifikátu, autentikace neprojde. Pak je potřeba vypnout vefifikaci serveru, vaše aplikace potom nebude ověřovat občanku serveru, ke kterému se připojila:
configuration.setPeerVerifyMode(QSslSocket::VerifyMone);
Zároveň není nikdy na škodu chytat signál QNetworkAccessManager::sslErrors(QNetworkReply *, QList<QSslError>). Případné chyby lze ignorovat voláním QNetworkReply::ignoreSslErrors() v napojeném slotu. Ignorování chyb je však dobré vždy pečlivě zvážit a případně v aplikaci projednat s uživatelem. Ignorování chyby SSL může vést k zásadnímu ohrožení bezpečnosti.
Přihlašování certifikátem není příliš rozšířená technika u běžných webových aplikací. V praxi se využívá například při přihlašování k certifikační autoritě PostSignum pro získání časového razítka. Zde se ale předpokládá použití specializované aplikace.
Využití najde přihlašování certifikátem i tam, kde mezi sebou komunikují různá zařízení a je vhodné obejít běžnou správu uživatelů a hesel. Správu hesel mívají pod palcem obvykle přímo uživatelé takových systémů a je jen otázkou času, kdy nějakého horlivého spráce napadne vyčistit "nepoužívané" uživatelské účty. Navíc je u takových systémů jistota, že zařízení a informace v síti pocházejí skutečně od jediného výrobce.