Szyfrujemy transmisję HTTP / Apache 1.3.37 + SSL

Szyfrowanie jest procedurą przekształcania tekstu z postaci jawnej, czytelnej dla człowieka na postać, której nie da się wprost odczytać. W momencie przechwycenia transmisji danych bez użycia żadnych mechanizmów szyfrujących intruz jest w stanie odczytać wszystkie przesyłane dane. Wyobraźmy sobie logowanie do poczty poprzez interfejs WWW. Użytkownik aby móc się uwierzytelnić musi podać swój login oraz hasło. W tej samej sieci jest intruz, którego zadaniem jest przechwycenie tajnych danych użytkownika. Aby to było możliwe wystarczy, aby sieć komputerowa, do której są obaj podłączeni była siecią Ethernet zbudowaną w oparciu o zwykłe huby Ethernetowi, które nie posiadają możliwości izolacji portów.

Do przechwytywania transmisji danych w sieciach ethernet służą narzędzia, nazywane snifferami. Najpopularniejsze z nich to tcpdump, ethereal, wireshark. Chciałbym zaprezentować poniżej jak może wyglądać przechwycona niezaszyfrowana transmisja danych pomiędzy przeglądarką a serwerem HTTP.

Na poniższym rysunku widać, że przechwycenie transmisji jawnej, automatycznie ujawnia nasze tajne dane przesyłane z użyciem metody GET, takie jak login i hasło w tym przypadku, user=jamzed i pass=trudnehaslo.

Gdybyśmy używali protokołu HTTPS, czyli wykorzystywali transmisję szyfrowaną, to przechwycenie ruchu nie ujawni żadnych danych, poniżej przykładowy zrzut transmisji:

Gdy przesyłamy w Internecie jakiekolwiek dane zawierające informacje, które nie są publiczne, zawsze powinniśmy wykorzystywać transmisję szyfrowaną. Pozwoli to nam uniknąć sytuacji, w której nasze dane zostają odczytane przez pośrednie osoby.

Mechanizm SSL zapewnia szyfrowanie danych przesyłanych między serwerem a klientem, dodatkowo daje możliwość weryfikacji tożsamości serwera. Polega to na tym, że każdy certyfikat powinien być podpisane przez zaufane centrum autoryzacyjne, które poświadcza, że dany certyfikat jest prawidłowy dla danej konkretnej domeny, dla której został wygenerowany. Dodatkowym zabezpieczeniem dostępu do zasobów danych może być umieszczenie ich na serwerze i wymuszenie na kliencie weryfikacji tożsamości przy próbie dostępu. W takim przypadku klient musi przedstawić swój prywatny certyfikat, który jest dodany jako zaufany na serwerze HTTP.

Aby zaimplementować obsługę protokołu SSL dla serwera Apache należy zainstalować pakiet OpenSSL, który zawiera niezbędne biblioteki do kompilacji modułu mod_ssl. Poza pakietem OpenSSL system operacyjny musi mieć możliwość generowania wartości pseudolosowych, czyli w przypadku systemów Unix/Linux jest to domyślne pseudo urządzenie /dev/random. Dla Apache serii 1.3.X implementacja mod_ssl wygląda następująco:

  • pobranie źródeł modułu mod_ssl
  • rozpakowanie
  • skonfigurowanie i kompilacja serwera Apache

deface Sources # wget http://www.modssl.org/source/mod_ssl-2.8.28-1.3.37.tar.gz
deface Sources # tar zxfv mod_ssl-2.8.28-1.3.37.tar.gz -C Unpacked/
deface Sources # cd Unpacked/mod_ssl-2.8.28-1.3.37/
deface mod_ssl-2.8.28-1.3.37 # ./configure --with-apache=../apache_1.3.37/
Configuring mod_ssl/2.8.28 for Apache/1.3.37
+ Apache location: ../apache_1.3.37/ (Version 1.3.37)
+ Auxiliary patch tool: ./etc/patch/patch (local)
+ Applying packages to Apache source tree:
o Extended API (EAPI)
o Distribution Documents
o SSL Module Source
o SSL Support
o SSL Configuration Additions
o SSL Module Documentation
o Addons
Done: source extension and patches successfully applied.

Now proceed with the following commands (Bourne-Shell syntax):
$ cd ../apache_1.3.37/
$ SSL_BASE=/path/to/openssl ./configure ... --enable-module=ssl
$ make
$ make certificate
$ make install

W tym momencie zgodnie z informacją przechodzimy do katalogu ze źródłami serwera HTTP Apache 1.3.37 i wydajemy wszystkie polecenia dokładnie w takiej kolejności:

deface apache_1.3.37 # ./configure --prefix=/usr/local/apache/ --enable-module=so --enable-module=rewrite --enable-module=ssl

Najważniejszym parametrem jest --enable-module=ssl, który powoduje, że pozostała konfiguracja uwzględnia moduł SSL:

Configuring for Apache, Version 1.3.37
+ using installation path layout: Apache (config.layout)
Creating Makefile
Creating Configuration.apaci in src
Creating Makefile in src
+ configured for Linux platform
+ setting C compiler to gcc
+ setting C pre-processor to gcc -E
+ using "tr [a-z] [A-Z]" to uppercase
+ checking for system header files
+ adding selected modules
o rewrite_module uses ConfigStart/End
disabling DBM support for mod_rewrite
(perhaps you need to add -ldbm, -lndbm or -lgdbm to EXTRA_LIBS)
o ssl_module uses ConfigStart/End
+ SSL interface: mod_ssl/2.8.28
+ SSL interface build type: OBJ
+ SSL interface compatibility: enabled
+ SSL interface experimental code: disabled
+ SSL interface conservative code: disabled
+ SSL interface vendor extensions: disabled
+ SSL interface plugin: Built-in SDBM
+ SSL library path: [SYSTEM]
+ SSL library version: OpenSSL 0.9.8d 28 Sep 2006
+ SSL library type: installed package (system-wide)
+ enabling Extended API (EAPI)
+ using system Expat
+ using -ldl for vendor DSO support
+ checking sizeof various data types
+ doing sanity check on compiler and options
Creating Makefile in src/support
Creating Makefile in src/regex
Creating Makefile in src/os/unix
Creating Makefile in src/ap
Creating Makefile in src/main
Creating Makefile in src/modules/standard
Creating Makefile in src/modules/ssl

Po zakończonym poleceniu ./configure należy wydać polecenie make, które spowoduje, że odbędzie się pełna kompilacja serwera Apache, zakończona komunikatem:

Before you install the package you now should prepare the SSL
certificate system by running the 'make certificate' command.
For different situations the following variants are provided:

% make certificate TYPE=dummy    (dummy self-signed Snake Oil cert)
% make certificate TYPE=test     (test cert signed by Snake Oil CA)
% make certificate TYPE=custom   (custom cert signed by own CA)
% make certificate TYPE=existing (existing cert)
CRT=/path/to/your.crt [KEY=/path/to/your.key]

Use TYPE=dummy    when you're a  vendor package maintainer,
the TYPE=test     when you're an admin but want to do tests only,
the TYPE=custom   when you're an admin willing to run a real server
and TYPE=existing when you're an admin who upgrades a server.
(The default is TYPE=test)

Additionally add ALGO=RSA (default) or ALGO=DSA to select
the signature algorithm used for the generated certificate.

Use 'make certificate VIEW=1' to display the generated data.

Thanks for using Apache & mod_ssl.
Ralf S. Engelschall [email protected] www.engelschall.com

Pozostaje nam wygenerowanie certyfikatów. Najszybciej możemy je wygenerować poleceniem: make certificate. Zostaniemy poproszeni o podanie następujących informacji:

  • Country Name
  • State or Province Name
  • Locality Name
  • Organization Name
  • Organizational Unit Name
  • Common Name
  • Email Address
  • Certificate Validity

Po uzupełnieniu wszystkich informacji możemy wydać polecenie make install. W tym momencie nastąpi instalacja serwera HTTP z wsparciem dla SSL. Pozostaje już tylko uruchomienie serwera:

deface ssl.crt # /usr/local/apache/bin/apachectl startssl
/usr/local/apache/bin/apachectl startssl: httpd started

Po wystartowaniu możemy przetestować, czy serwer poprawnie obsługuje szyfrowanie SSL, do tego celu możemy po prostu spróbować połączyć się przeglądarką, wykorzystując protokół HTTPS.

Przy próbie załadowania strony zostaniemy poinformowani, że nasz certyfikat nie został poprawnie zweryfikowany. Wynika to z tego, że nie został podpisany przez zaufane CA, a przez nasze własne. Pomijając powyższe ostrzeżenie, sam mechanizm szyfrujący będzie działał prawidłowo.

Konfiguracja modułu mod_ssl wymaga zapoznania się w wieloma dyrektywami. Najważniejsza z nich to SSLEngine, która włącza lub wyłącza mechanizm SSL/TLS, zazwyczaj zostaje wymieniona w kontenerze VirtualHost dla portu 443, może przyjować dwie wartości ON lub OFF. Dla zwiększenia bezpieczeństwa poprzez wzmocnienie samego mechanizmu szyfrującego, możemy wykorzystać dyrektywę SSLCipherSuite, która pozwala na wyznaczenie długości klucza szyfrowania oraz algorytmu kryptograficznego. Najwyższy poziom zabezpieczeń uzyskamy jeśli dyrektywa będzie miała następującą treść:

SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM

co oznacza, że dozwolone są tylko silne algorytmy szyfrujące, ponadto zostają wyłączone słabsze algorytmy i nieszyfrujące danych. Bardzo ważny element w szyfrowaniu danych odgrywa mechanizm generowania liczb losowych. Użycie losowych wartości jako wartości wejściowej dla funkcji szyfrowania OpenSSL zdecydowanie utrudnia atakującemu predykację przyszłych danych, aby mieć wpływ na powyższe czynniki, może wykorzystać dyrektywę SSLRandomSeed. Serwer Apache pozwala na wykorzystywanie tej dyrektywy w dwóch kontekstach - startu, oraz połączenia. Zalecane ustawienia dyrektywy to:

SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect file:/dev/urandom 512

Aby wskazać pliki naszego certyfikaty oraz klucza szyfrowania, musimy użyć dyrektyw SSLCertificateFile oraz SSLCertificateKeyFile, składnia wygląda następująco:

SSLCertificateFile /usr/local/apache/conf/ssl.crt/server.crt
SSLCertificateKeyFile /usr/local/apache.conf/ssl.key/server.key

Implementacja modułu mod_ssl nie jest skomplikowana, więc powinniśmy wykorzystywać ją jak najczęściej, jeśli zależy nam na zachowaniu bezpieczeństwa przesyłanych danych.

A Wy jak szyfrujecie transmisję?