added SNI trick to catch old browsers (apache)
[ach-master.git] / src / practical_settings / webserver.tex
1 %%---------------------------------------------------------------------- 
2 \subsection{Apache}
3
4 Note that any cipher suite starting with EECDH can be omitted, if in doubt.
5 (Compared to the theory section, EECDH in Apache and ECDHE in OpenSSL are
6 synonyms~\footnote{https://www.mail-archive.com/openssl-dev@openssl.org/msg33405.html})
7
8 \subsubsection{Tested with Versions}
9 \begin{itemize*}
10   \item Apache 2.2.22 linked against OpenSSL 1.0.1e, Debian Wheezy
11   \item Apache 2.4.6 linked against OpenSSL 1.0.1e, Debian Jessie
12 \end{itemize*}
13
14 \subsubsection{Settings}
15 Enabled modules \emph{SSL} and \emph{Headers} are required.
16
17 \begin{lstlisting}
18 SSLCertificateFile server.crt
19 SSLCertificateKeyFile server.key
20 SSLProtocol All -SSLv2 -SSLv3 
21 SSLHonorCipherOrder On
22 SSLCompression off
23 # Add six earth month HSTS header for all users...
24 Header add Strict-Transport-Security "max-age=15768000"
25 # If you want to protect all subdomains, use the following header
26 # ALL subdomains HAVE TO support HTTPS if you use this!
27 # Strict-Transport-Security: max-age=15768000 ; includeSubDomains
28
29 SSLCipherSuite '%*\cipherStringB*)'
30 \end{lstlisting}
31
32 \subsubsection{Additional settings}
33 You might want to redirect everything to \emph{https://} if possible. In Apache
34 you can do this with the following setting inside of a VirtualHost environment:
35
36 \begin{lstlisting}
37 <VirtualHost *:80>
38   RewriteEngine On
39   RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=permanent]
40 </VirtualHost>
41 \end{lstlisting}
42
43 In case you want to catch those old clients that do not support the recommended
44 cipher string (eg. WinXP or Java 6) you might use their inability to understand
45 SNI to create a catchall page with a default SSL server:
46
47 begin{lstlisting}
48 # Debian: add this to /etc/apache2/ports.conf
49 NameVirtualHost *:443
50 Listen 443
51
52 # This needs to be the first virtual host entry; on Debian systems put this
53 # in /etc/apache2/sites-enabled/000-default-ssl
54 <VirtualHost *:443>
55     DocumentRoot /var/www/bad-ssl
56     SSLEngine on
57     SSLProtocol All
58     SSLCipherSuite ALL:!ADH:!NULL:!EXPORT:+HIGH:+MEDIUM:+LOW:+SSLv3
59     SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
60     SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
61 </VirtualHost>
62 \end{lstlisting}
63
64 The catchall virtual server needs to be the first server in the config. On the
65 default page you should provide information about upgrading the browser to the
66 user. You also should not use snakeoil certificates (as in the snipplet above)
67 but the very same certificate as you use for the real service. In case you
68 provide several virtual servers via SNI, the certificate for the catchall page
69 needs to include all their names.
70
71 %\subsubsection{Justification for special settings (if needed)}
72
73 \subsubsection{References}
74 \begin{itemize*}
75   \item Apache2 Docs on SSL and TLS: \url{https://httpd.apache.org/docs/2.4/ssl/}
76 \end{itemize*}
77
78
79 \subsubsection{How to test}
80 See appendix \ref{cha:tools}
81
82
83 %%---------------------------------------------------------------------- 
84 \subsection{lighttpd}
85
86 \subsubsection{Tested with Versions}
87 \begin{itemize*}
88   \item lighttpd/1.4.31-4 with OpenSSL 1.0.1e on Debian Wheezy
89   \item lighttpd/1.4.33 with OpenSSL 0.9.8o on Debian Squeeze (note that TLSv1.2 does not work in openssl 0.9.8 thus not all ciphers actually work)
90   \item lighttpd/1.4.28-2 with OpenSSL 0.9.8o on Debian Squeeze (note that TLSv1.2 does not work in openssl 0.9.8 thus not all ciphers actually work)
91 \end{itemize*}
92
93
94 \subsubsection{Settings}
95 \begin{lstlisting}
96 $SERVER["socket"] == "0.0.0.0:443" {
97   ssl.engine  = "enable"
98   ssl.use-sslv2 = "disable"
99   ssl.use-sslv3 = "disable"
100   ssl.pemfile = "/etc/lighttpd/server.pem"
101   ssl.cipher-list = "%*\cipherStringB*)"
102   ssl.honor-cipher-order = "enable"
103   setenv.add-response-header  = ( "Strict-Transport-Security" => "max-age=15768000") # six months
104   # use this only if all subdomains support HTTPS!
105   # setenv.add-response-header  = ( "Strict-Transport-Security" => "max-age=15768000; includeSubDomains")
106 }
107 \end{lstlisting}
108
109 Starting with lighttpd version 1.4.29 Diffie-Hellman and Elliptic-Curve Diffie-Hellman key agreement protocols are supported.
110 By default, elliptic curve "prime256v1" (also "secp256r1") will be used, if no other is given.
111 To select special curves, it is possible to set them using the configuration options \verb|ssl.dh-file| and \verb|ssl.ec-curve|.
112 \begin{lstlisting}
113 ssl.dh-file = "/etc/lighttpd/ssl/dh2048.pem"
114 ssl.ec-curve = "secp521r1"
115 \end{lstlisting}
116 Please read section \ref{section:DH} for more information on Diffie Hellman key exchange and elliptic curves.
117
118 \subsubsection{Additional settings}
119 As for any other webserver, you might want to automatically redirect \emph{http://}
120 traffic toward \emph{https://}. It is also recommended to set the environment variable
121 \emph{HTTPS}, so the PHP applications run by the webserver can easily detect,
122 that HTTPS is in use.
123
124 \begin{lstlisting}
125 $HTTP["scheme"] == "http" {
126   # capture vhost name with regex condition -> %0 in redirect pattern
127   # must be the most inner block to the redirect rule
128   $HTTP["host"] =~ ".*" {
129     url.redirect = (".*" => "https://%0$0")
130   }
131   # Set the environment variable properly
132   setenv.add-environment = (
133     "HTTPS" => "on"
134   )
135 }
136 \end{lstlisting}
137
138
139 \subsubsection{Additional information} 
140 The config option \emph{honor-cipher-order} is available since 1.4.30, the
141 supported ciphers depend on the used OpenSSL-version (at runtime). ECDHE has to
142 be available in OpenSSL at compile-time, which should be default. SSL
143 compression should by deactivated by default at compile-time (if not, it's
144 active).
145
146 Support for other SSL-libraries like GnuTLS will be available in the upcoming
147 2.x branch, which is currently under development.
148
149
150 \subsubsection{References} 
151 \begin{itemize*}
152   \item HTTPS redirection: \url{http://redmine.lighttpd.net/projects/1/wiki/HowToRedirectHttpToHttps}
153   \item Lighttpd Docs SSL: \url{http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs\_SSL}
154   \item Release 1.4.30 (How to mitigate BEAST attack) \url{http://redmine.lighttpd.net/projects/lighttpd/wiki/Release-1\_4\_30}
155   \item SSL Compression disabled by default: \url{http://redmine.lighttpd.net/issues/2445}
156 \end{itemize*}
157
158
159 \subsubsection{How to test} 
160 See appendix \ref{cha:tools}
161
162
163 %%---------------------------------------------------------------------- 
164 \subsection{nginx}
165
166 \subsubsection{Tested with Version} 
167 \begin{itemize*}
168   \item 1.4.4 with OpenSSL 1.0.1e on OS X Server 10.8.5
169   \item 1.2.1-2.2+wheezy2 with OpenSSL 1.0.1e on Debian Wheezy
170   \item 1.4.4 with OpenSSL 1.0.1e on Debian Wheezy
171   \item 1.2.1-2.2~bpo60+2 with OpenSSL 0.9.8o on Debian Squeeze (note that TLSv1.2 does not work in openssl 0.9.8 thus not all ciphers actually work)
172 \end{itemize*}
173
174
175 \subsubsection{Settings}
176 \begin{lstlisting}
177 ssl_prefer_server_ciphers on;
178 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # not possible to do exclusive
179 ssl_ciphers '%*\cipherStringB*)';
180 add_header Strict-Transport-Security max-age=15768000; # six months
181 # use this only if all subdomains support HTTPS!
182 # add_header Strict-Transport-Security "max-age=15768000; includeSubDomains"
183 \end{lstlisting}
184
185 If you absolutely want to specify your own DH parameters, you can specify them via
186
187 \begin{lstlisting}
188 ssl_dhparam file;
189 \end{lstlisting}
190
191 However, we advise you to read section \ref{section:DH} and stay with the standard IKE/IETF parameters (as long as they are \textgreater 1024 bits).
192
193 \subsubsection{Additional settings}
194 If you decide to trust NIST's ECC curve recommendation, you can add the following line to nginx's configuration file to select special curves:
195
196 \begin{lstlisting}
197 ssl_ecdh_curve          secp384r1;
198 \end{lstlisting}
199
200 You might want to redirect everything to \emph{https://} if possible. In Nginx you can do this with the following setting:
201
202 \begin{lstlisting}
203 return 301 https://$host$request_uri;
204 \end{lstlisting}
205
206 In case you want to catch those old clients that do not support the recommended
207 cipher string (eg. WinXP or Java 6) you might use their inability to understand
208 SNI to create a catchall page with a default SSL server:
209
210 \begin{lstlisting}
211 server {
212     listen 443 default;
213     listen [::]:443 default ipv6only=on;
214     root /var/www/bad-ssl;
215     index index.html
216     ssl on;
217     ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
218     ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
219
220     ssl_session_timeout 5m;
221
222     ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
223     ssl_ciphers ALL:!ADH:!NULL:!EXPORT:+HIGH:+MEDIUM:+LOW:+SSLv3;
224 }
225 \end{lstlisting}
226
227 The real service then needs to be in its own server definition omitting the
228 \texttt{default} keyword in the \texttt{listen} directive. On the default page
229 you should provide information about upgrading the browser to the user. You
230 should not use snakeoil certificates (as in the snipplet above) but the very
231 same certificate as you use for the real service. In case you provide several
232 virtual servers via SNI, the certificate for the catchall page needs to include
233 all their names.
234
235 \subsubsection{References} 
236 \begin{itemize*}
237   \item \url{http://nginx.org/en/docs/http/ngx_http_ssl_module.html}
238   \item \url{http://wiki.nginx.org/HttpSslModule}
239 \end{itemize*}
240
241 \subsubsection{How to test}
242 See appendix \ref{cha:tools}
243
244
245 %%---------------------------------------------------------------------- 
246 \subsection{MS IIS}
247 \label{sec:ms-iis}
248 \todo{Daniel: add screenshots and registry keys}
249
250
251 \subsubsection{Tested with Version} \todo{Daniel: add tested version}
252
253
254 \subsubsection{Settings}
255 When trying to avoid RC4 and CBC (BEAST-Attack) and requiring perfect
256 forward secrecy, Microsoft Internet Information Server (IIS) supports
257 ECDSA, but does not support RSA for key exchange (consider ECC suite
258 B doubts\footnote{\url{http://safecurves.cr.yp.to/rigid.html}}).
259
260 Since \verb|ECDHE_RSA_*| is not supported, a SSL certificate based on
261 elliptic curves needs to be used.
262
263 The configuration of cipher suites MS IIS will use, can be configured in one
264 of the following ways:
265 \begin{enumerate}
266   \item Group Policy \footnote{\url{http://msdn.microsoft.com/en-us/library/windows/desktop/bb870930(v=vs.85).aspx}}
267   \item Registry
268   \item IIS Crypto~\footnote{\url{https://www.nartac.com/Products/IISCrypto/}}
269 \end{enumerate}
270
271
272 Table~\ref{tab:MS_IIS_Client_Support} shows the process of turning on
273 one algorithm after another and the effect on the supported clients
274 tested using https://www.ssllabs.com.
275
276 \verb|SSL 3.0|, \verb|SSL 2.0| and \verb|MD5| are turned off.
277 \verb|TLS 1.0| and \verb|TLS 2.0| are turned on.
278
279 \begin{table}[h]
280   \centering
281   \small
282   \begin{tabular}{ll}
283     \toprule
284     Cipher Suite & Client \\
285     \midrule
286     \verb|TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256| & only IE 10,11, OpenSSL 1.0.1e \\
287     \verb|TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256| & Chrome 30, Opera 17, Safari 6+ \\
288     \verb|TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA| & FF 10-24, IE 8+, Safari 5, Java 7\\
289     \bottomrule 
290   \end{tabular}
291   \caption{Client support}
292   \label{tab:MS_IIS_Client_Support}
293 \end{table}
294
295 Table~\ref{tab:MS_IIS_Client_Support} shows the algorithms from
296 strongest to weakest and why they need to be added in this order. For
297 example insisting on SHA-2 algorithms (only first two lines) would
298 eliminate all versions of Firefox, so the last line is needed to
299 support this browser, but should be placed at the bottom, so capable
300 browsers will choose the stronger SHA-2 algorithms.
301
302 \verb|TLS_RSA_WITH_RC4_128_SHA| or equivalent should also be added if
303 MS Terminal Server Connection is used (make sure to use this only in a
304 trusted environment). This suite will not be used for SSL, since we do
305 not use a RSA Key.
306
307 % \verb|TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256| ... only supported by: IE 10,11, OpenSSL 1.0.1e
308 % \verb|TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256| ... Chrome 30, Opera 17, Safari 6+
309 % \verb|TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA| ... Firefox 10-24, IE 8+, Safari 5, Java 7
310
311 Clients not supported:
312 \begin{enumerate}
313   \item Java 6
314   \item WinXP
315   \item Bing
316 \end{enumerate}
317
318
319 \subsubsection{Additional settings}
320 %Here you can add additional settings
321
322
323 \subsubsection{Justification for special settings (if needed)}
324 % in case you have the need for further justifications why you chose this and that setting or if the settings do not fit into the standard Variant A or Variant B schema, please document this here
325
326
327 \subsubsection{References}
328 \todo{add references}
329
330 % add any further references or best practice documents here
331
332
333 \subsubsection{How to test}
334 See appendix \ref{cha:tools}
335
336 %%% Local Variables: 
337 %%% mode: latex
338 %%% TeX-master: "../applied-crypto-hardening"
339 %%% End: