В наших периодических проверках безопасности наши экземпляры HAProxy всегда указываются как уязвимость, связанная с раскрытием версии. При дальнейшем осмотре выясняется, что ни в одном ответе нет баннеров с версиями и что Nmap отвечает за обнаружение HAProxy на основе какого-то типа отпечатков пальцев.
Наши экземпляры HAProxy будут автономно перенаправлять HTTP на HTTPS, при этом проксируя трафик SSL на разные серверные системы. Раскрытие версии сообщается только по порту HTTP (80), но не по порту HTTPS (443).
Вот пример вывода Nmap, иллюстрирующий проблему:
$ nmap -sV --script=http-headers example.com
PORT STATE SERVICE VERSION
80/tcp open http-proxy HAProxy http proxy 1.3.1 or later
| http-headers:
| Content-length: 0
| Location: https://example.com/
| Connection: close
|
|_ (Request type: GET)
443/tcp open ssl/http nginx
| http-headers:
| Server: nginx
| Content-Type: application/json
| Transfer-Encoding: chunked
| Connection: close
| Cache-Control: no-cache
| Date: Thu, 06 Sep 2018 14:46:47 GMT
| X-Frame-Options: SAMEORIGIN
| X-Xss-Protection: 1; mode=block
| X-Content-Type-Options: nosniff
| Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
| Strict-Transport-Security: max-age=16000000; includeSubDomains; preload;
| X-Forwarded-Proto: https
|
|_ (Request type: GET)
|_http-server-header: nginx
Service Info: Device: load balancer
Как nmap точно отпечатывает HAProxy, если нет баннера / заголовка, чтобы показать его присутствие? Я предполагаю, что Nmap будет рассматривать конкретную полезную нагрузку 301 или какой-то отпечаток TCP, который является уникальным для HAProxy.
И главный вопрос: как мне вообще предотвратить обнаружение HAProxy с помощью Nmap?
Nmap идентифицирует HAProxy на основе того, какие версии добавили заголовки к ответу. Линии совпадений находятся в nmap-service-probes
файл в исходном коде Nmap. Вот несколько избранных комментариев из файла, чтобы проиллюстрировать, как это было достигнуто:
# HAProxy responses are mostly from http_err_msgs, HTTP_401_fmt, and HTTP_407_fmt in
# http://git.haproxy.org/?p=haproxy.git;a=blob;f=src/proto_http.c
# Only statuses 200, 403, and 503 are likely to result from from GetRequest;
# other probes can match via fallbacks.
match http-proxy m|^HTTP/1\.0 200 OK\r\nCache-Control: no-cache\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n<html><body><h1>200 OK</h1>\nHAProxy: service ready\.\n</body></html>\n$| p/HAProxy http proxy/ v/before 1.5.0/ d/load balancer/ cpe:/a:haproxy:haproxy/
# Statuses 400, 401, 403, 408, 500, 502, 503, and 504 gained "Content-Type: text/html" in v1.3.1.
# http://git.haproxy.org/?p=haproxy.git;a=commitdiff;h=791d66d3634dde12339d4294aff55a1aed7518e3;hp=b9e98b683612b29ef939c10d3d00be27de26534a
match http-proxy m|^HTTP/1\.0 400 Bad request\r\nCache-Control: no-cache\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n<html><body><h1>400 Bad request</h1>\nYour browser sent an invalid request\.\n</body></html>\n$| p/HAProxy http proxy/ v/1.3.1 or later/ d/load balancer/ cpe:/a:haproxy:haproxy/
# Statuses 400, 401, 403, 408, 500, 502, 503, and 504 gained "Content-Type: text/html" in v1.3.1.
# http://git.haproxy.org/?p=haproxy.git;a=commitdiff;h=791d66d3634dde12339d4294aff55a1aed7518e3;hp=b9e98b683612b29ef939c10d3d00be27de26534a
match http-proxy m|^HTTP/1\.0 400 Bad request\r\nCache-Control: no-cache\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n<html><body><h1>400 Bad request</h1>\nYour browser sent an invalid request\.\n</body></html>\n$| p/HAProxy http proxy/ v/1.3.1 or later/ d/load balancer/ cpe:/a:haproxy:haproxy/
Вы не можете предотвратить это, не используя какой-либо обратный прокси-сервер, и даже он, скорее всего, будет считываться отпечатком пальца. Найдите способ задокументировать это как ложное срабатывание или принятый риск: этого нельзя избежать, так как это не настраивается.