Opened 6 years ago

Closed 6 years ago

#1690 closed enhancement (wontfix)

Add MITM detection

Reported by: Fabian Franz BSc Owned by:
Priority: minor Milestone:
Component: nginx-module Version: 1.15.x
Keywords: TLS Cc:
uname -a: Linux host 4.19.5.a-1-hardened #1 SMP PREEMPT Fri Nov 30 01:54:36 CET 2018 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.14.1
built with OpenSSL 1.1.1 11 Sep 2018 (running with OpenSSL 1.1.1a 20 Nov 2018)
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --sbin-path=/usr/bin/nginx --pid-path=/run/nginx.pid --lock-path=/run/lock/nginx.lock --user=http --group=http --http-log-path=/var/log/nginx/access.log --error-log-path=stderr --http-client-body-temp-path=/var/lib/nginx/client-body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-cc-opt='-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fno-plt -D_FORTIFY_SOURCE=2' --with-ld-opt=-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now --with-compat --with-debug --with-file-aio --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-pcre-jit --with-stream --with-stream_geoip_module --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads

Description

Caddy has a feature to detect TLS MITM attacks by comparing manipulated Client Hello messages with the ones used by the browsers. If the MITM does not mirror all properties of the one used by the client, it will be detected.

It would be good to have such a feature in nginx as well as it would be good for some applications if they could reject such a connection.

Source of Caddy:
https://github.com/mholt/caddy/blob/09188981c477e1972012592a5c695ade777770ef/caddyhttp/httpserver/mitm.go

Feature request in the OPNsense plugins repository:
https://github.com/opnsense/plugins/issues/1044

Change History (5)

comment:1 by Maxim Dounin, 6 years ago

I see at least two problems with this:

  1. Detection of various TLS properties as supported by different browsers requires a lot of effort to build and maintain a database of such properties. And such database is highly likely to become stale over time, so it needs to be regularly updated.
  2. The same or similar database can be used by MiTM solutions to better mimic browsers, making the feature useless.

In the past we've tried to implement somewhat similar feature to detect old and modern browsers, browser module. Over time it degraded to unusable state, and the recommended approach now is to use a map-based solutions instead if browser detection is needed.

Probably similar map-based (or script-based, using perl/njs/lua) solution can be implemented for SSL MiTM detection too, using the $ssl_ciphers and $ssl_curves variables.

comment:2 by Fabian Franz BSc, 6 years ago

njs sounds like a good solution so i think it may work as the fingerprints can be created automatically (for example running Firefox / chromium headless and call nginx -> record the $ssl_ciphers value and then export it as a single JSON which can be imported and mapped by njs).

The database may be created in the background by learning which FP is real as if you count the requests per UA and FP, the one with the biggest amount is probably the one not intercepted (typical learning phase of a WAF).

It may also be converted to a map, so no njs is needed (may depend on nested maps)

In any case, thanks for your help. If you don't want to implement it directly in nginx, feel free to close the ticket (I'll try to solve this externally with a helper then).

comment:3 by Fabian Franz BSc, 6 years ago

I got it working in njs:
https://github.com/opnsense/plugins/pull/1070/files

I have not yet integrated this script into the configuration but my local custom build of nginx handles it without any problems. It can set a variable which then can be passed to the upstream.

comment:4 by Fabian Franz BSc, 6 years ago

please close - already implemented in njs.

comment:5 by Maxim Dounin, 6 years ago

Resolution: wontfix
Status: newclosed
Note: See TracTickets for help on using tickets.