MS Remote Desktop Gateway, HAProxy és jelszó brute force támadás

Barátok, sziasztok!

Számos módszer létezik, hogy otthonról csatlakozzunk a munkahelyhez az irodában. Az egyik lehetőség a Microsoft Remote Desktop Gateway használata. Ez egy RDP HTTP-n keresztül. Nem szeretném itt a RDGW beállításával foglalkozni, és nem akarom mérlegelni, hogy jó vagy rossz, tekintsük ezt az egyik távoli elérési eszköznek. Azt szeretném megvitatni, hogyan védhetjük meg az RDGW szerverünket a gonosz internettől. Amikor beállítottam az RDGW szerveremet, azonnal aggódni kezdtem a védelem miatt, különösen a jelszavak brute force támadása elleni védelem miatt. Meglepett, hogy nem találtam az interneten cikkeket arról, hogyan lehet ezt megtenni. Nos, ezt nekem kell megoldanom.

Magában az RDGW-nak nincsenek védelmi funkciói. Igen, ki lehet venni nyílt interfészen a nyílt hálózatba, és jól fog működni. De egy jó rendszergazda vagy IT biztonsági szakember számára ez szorongást okozhat. Ráadásul elkerülheti azt a helyzetet, amikor a figyelmetlen alkalmazott megjegyzi a vállalati fiókjának a jelszavát otthoni számítógépén, majd megváltoztatja a jelszavát.

Jó módja a belső források védelmének a külső környezettől, ha különböző proxykat, publikáló rendszereket és más WAF-okat alkalmazunk. Ne feledjük, hogy az RDGW végül is http, tehát adódik, hogy egy speciális megoldást helyezünk el a belső szerverek és az internet között.

Tudom, hogy léteznek fantasztikus F5, A10, Netscaler (ADC) rendszerek. Mint e rendszerek egyik adminisztrátora, elmondhatom, hogy a brute force támadások ellen is lehetséges védekezés ezen rendszereken. És igen, ezek a rendszerek emellett meg fognak védeni a különféle syn flood támadásoktól is.

De nem minden cég engedheti meg magának egy ilyen megoldás beszerzését (és egy ilyen rendszer adminisztrátorának megtalálását :), miközben a biztonságról gondoskodhat!

Teljesen lehetséges ingyenes verziónak a HAProxy telepítése egy ingyenes operációs rendszeren. Teszteltem a Debian 10-en, a stabil tárolóban a haproxy verziója 1.8.19. A 2.0.xx verziókat is teszteltem a teszt tárolóból.

A Debian beállítását hagyjuk ki a cikkből. Röviden: a nyílt interfészen zárjunk le mindent, kivéve a 443-as portot, a szürke interfészen pedig — a politikája szerint, például zárjunk le mindent, kivéve a 22-es portot. Csak azt nyissuk meg, ami a működéshez szükséges (például VRRP, a lebegő IP-hez).

Először beállítottam a haproxy-t SSL bridging módban (ez a http mód) és aktiváltam a naplózást, hogy megnézhessem, mi történik belül az RDP-n. Úgy mondanám, hogy belelátok a közepébe. Nos, az összes RDGateway beállítási cikkben megadott útvonal, a /RDWeb hiányzik. Amit ott találunk, az a /rpc/rpcproxy.dll és a /remoteDesktopGateway/. Ehhez nem használnak standard GET/POST kéréseket, saját kérési típust alkalmaznak: RDG_IN_DATA, RDG_OUT_DATA.

Nem sok, de legalább valami.

Tessék, teszteljünk.

Elindítom az mstsc-t, elmegyek a szerverre, a naplókban négy 401-es (unauthorized) hibát látok, majd megadom a felhasználónevet/jelszót és látom a 200-as választ.

Kikapcsolom, újra elindítom, a naplókban ugyanazokat a négy 401-es hibákat látom. Hibás felhasználónév/jelszó megadásakor újra négy 401-es hibát látok. Ez pontosan az, amit keresünk. Ezt fogjuk keresni.

Mivel a bejelentkezési URL-t nem sikerült meghatározni, és azt is, hogy a haproxy-ban hogyan vadászni a 401-es hibára, ezért minden 4xx hibát fogok figyelni (valójában nem vadászni, hanem számolni). Ez is megfelelő a feladat megoldásához.

A védelem lényege az lesz, hogy számolni fogjuk a 4xx hibák számát (a backend-en) egy adott időegység alatt, és ha ez a megadott határérték fölé emelkedik, akkor elutasítjuk (a frontend-en) az összes további kapcsolatot arról az IP-címről a megadott időtartam alatt.

Technikailag ez nem lesz védelem a jelszópróbálkozások ellen, ez egy védelem a 4xx hibák ellen. Például, ha gyakran kérjük egy nem létező URL-t (404), akkor a védelem is életbe lép.

A legegyszerűbb és működő módszer az, hogy a backend-en számolunk, és blokkolunk, ha valami felesleges megjelenik:

frontend fe_rdp_tsc
    bind *:443 ssl crt /etc/haproxy/cert/desktop.example.com.pem
    mode http
    ...
    default_backend be_rdp_tsc


backend be_rdp_tsc
    ...
    mode http
    ...

    #hozzunk létre egy táblázatot, sztring típusú, 1000 elemű, 15 másodperc múlva lejár, számoljuk az elmúlt 10 másodperc hibáit
    stick-table type string len 128 size 1k expire 15s store http_err_rate(10s)
    #jegyezzük meg az IP-t
    http-request track-sc0 src
    #tiltsuk le a 429-es HTTP hibával, ha az utolsó 10 másodpercben több mint 4 hiba történt
    http-request deny deny_status 429 if { sc_http_err_rate(0) gt 4 }
	
	...
    server rdgw01 192.168.1.33:443 maxconn 1000 weight 10 ssl check cookie rdgw01
    server rdgw02 192.168.2.33:443 maxconn 1000 weight 10 ssl check cookie rdgw02

Nem a legjobb megoldás, bonyolítsuk. Számítani fogunk a backend-en, és blokkolni a frontend-en.

A támadóval durván bánunk, TCP kapcsolatot fogunk megszakítani.

frontend fe_rdp_tsc
    bind *:443 ssl crt /etc/haproxy/cert/ertelecom_ru_2020_06_11.pem
    mode http
    ...
    # IP címek táblázat létrehozása, 1000 elem, 15 másodperc után lejár, globális számlálóból megőrizni
    stick-table type ip size 1k expire 15s store gpc0
    # forrás lekérése
    tcp-request connection track-sc0 src
    # TCP kapcsolat elutasítása, ha a globális számláló >0
    tcp-request connection reject if { sc0_get_gpc0 gt 0 }
	
    ...
    default_backend be_rdp_tsc


backend be_rdp_tsc
    ...
    mode http
    ...
	
    # IP címek táblázat létrehozása, 1000 elem, 15 másodperc után lejár, hiba számának megőrzése 10 másodperc alatt
    stick-table type ip size 1k expire 15s store http_err_rate(10s)
    # sok hiba, ha a hibák száma 10 másodperc alatt meghaladja a 8-at
    acl errors_too_fast sc1_http_err_rate gt 8
    # támadás megjelölése a globális számlálóban (számláló növelése)
    acl mark_as_abuser sc0_inc_gpc0(fe_rdp_tsc) gt 0
    # globális számláló nullázása
    acl clear_as_abuser sc0_clr_gpc0(fe_rdp_tsc) ge 0
    # forrás lekérése
    tcp-request content track-sc1 src
    # elutasítás, támadás megjelölése
    tcp-request content reject if errors_too_fast mark_as_abuser
    # engedélyezni, támadás jelzésének törlése
    tcp-request content accept if !errors_too_fast clear_as_abuser
	
    ...
    server rdgw01 192.168.1.33:443 maxconn 1000 weight 10 ssl check cookie rdgw01
    server rdgw02 192.168.2.33:443 maxconn 1000 weight 10 ssl check cookie rdgw02

ugyanaz, de udvariasan, HTTP 429 (Túl sok kérés) hibát fogunk visszaadni

frontend fe_rdp_tsc
    ...
    stick-table type ip size 1k expire 15s store gpc0
    http-request track-sc0 src
    http-request deny deny_status 429 if { sc0_get_gpc0 gt 0 }
    ...
    default_backend be_rdp_tsc

backend be_rdp_tsc
    ...
    stick-table type ip size 1k expire 15s store http_err_rate(10s)
    acl errors_too_fast sc1_http_err_rate gt 8
    acl mark_as_abuser sc0_inc_gpc0(fe_rdp_tsc) gt 0
    acl clear_as_abuser sc0_clr_gpc0(fe_rdp_tsc) ge 0
    http-request track-sc1 src
    http-request allow if !errors_too_fast clear_as_abuser
    http-request deny deny_status 429 if errors_too_fast mark_as_abuser
    ...

Ellenőrzöm: elindítom az mstsc-t, és elkezdem véletlenszerűen beírni a jelszavakat. A harmadik kísérlet után 10 másodperc alatt kirúg, és az mstsc hibát jelez. Ezt a naplóban is látni lehet.

Magyarázatok. Messze nem vagyok a haproxy mestere. Nem értem, hogy például
http-request deny deny_status 429 if { sc_http_err_rate(0) gt 4 }
körülbelül 10 hibát engedélyez, mielőtt aktiválódik.

Zavarban vagyok a számlálókkal. A haproxy mestereit örömmel várom, ha kiegészítenek, javítanak, illetve jobban csinálják.

A megjegyzések között szívesen látnám a RD Gateway védelmének más módjait, érdekes lenne megismerni.

A Windows távoli asztali kliensek (mstsc) esetében meg kell jegyezni, hogy nem támogatják a TLS1.2-t (legalábbis Windows 7 alatt), így a TLS1-et kellett hagynom; nem támogatják a legfrissebb titkosítókat sem, így a régiakat kellett hagynom.

Azok számára, akik még semmit sem értettek meg, csak tanulnak, és már jót akarnak csinálni, minden konfigurációt bemutatok.

haproxy.conf

global
        log /dev/log    local0
        log /dev/log    local1 notice
        chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
        stats timeout 30s
        user haproxy
        group haproxy
        daemon

        # Alapértelmezett SSL anyag helyek
        ca-base /etc/ssl/certs
        crt-base /etc/ssl/private

        # Lásd: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
        #ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
        ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
        ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
        #ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
        ssl-default-bind-options no-sslv3
        ssl-server-verify none


defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        timeout connect 5000
        timeout client  15m
        timeout server  15m
        errorfile 400 /etc/haproxy/errors/400.http
        errorfile 403 /etc/haproxy/errors/403.http
        errorfile 408 /etc/haproxy/errors/408.http
        errorfile 500 /etc/haproxy/errors/500.http
        errorfile 502 /etc/haproxy/errors/502.http
        errorfile 503 /etc/haproxy/errors/503.http
        errorfile 504 /etc/haproxy/errors/504.http


frontend fe_rdp_tsc
    bind *:443 ssl crt /etc/haproxy/cert/dektop.example.com.pem
    mode http
    capture request header Host len 32
    log global
    option httplog
    timeout client 300s
    maxconn 1000

    stick-table type ip size 1k expire 15s store gpc0
    tcp-request connection track-sc0 src
    tcp-request connection reject if { sc0_get_gpc0 gt 0 }

    acl rdweb_domain hdr(host) -i beg dektop.example.com
    http-request deny deny_status 400 if !rdweb_domain
    default_backend be_rdp_tsc


backend be_rdp_tsc
    balance source
    mode http
    log global

    stick-table type ip size 1k expire 15s store http_err_rate(10s)
    acl errors_too_fast sc1_http_err_rate gt 8
    acl mark_as_abuser sc0_inc_gpc0(fe_rdp_tsc) gt 0
    acl clear_as_abuser sc0_clr_gpc0(fe_rdp_tsc) ge 0
    tcp-request content track-sc1 src
    tcp-request content reject if errors_too_fast mark_as_abuser
    tcp-request content accept if !errors_too_fast clear_as_abuser

    option forwardfor
    http-request add-header X-CLIENT-IP %[src]

    option httpchk GET /
    cookie RDPWEB insert nocache
    default-server inter 3s    rise 2  fall 3
    server rdgw01 192.168.1.33:443 maxconn 1000 weight 10 ssl check cookie rdgw01
    server rdgw02 192.168.2.33:443 maxconn 1000 weight 10 ssl check cookie rdgw02


frontend fe_stats
    mode http
    bind *:8080
    acl ip_allow_admin src 192.168.66.66
    stats enable
    stats uri /stats
    stats refresh 30s
    #stats admin if LOCALHOST
    stats admin if ip_allow_admin

Miért két szerver van a backend-en? Mert így lehet megszüntetni az egyetlen hibapontot. A HAProxy is létrehozhat két lebegő fehér IP-t.

Számítási erőforrások: lehet kezdeni a „két gigával, két maggal, játék PC-val”. E szerint a Wikipédiában ez bőven elegendő lesz.

Linkek:

Az rdp-gateway beállítása a HAProxy-tól
Az egyetlen cikk, amelyet megtaláltam, ahol a jelszófeltörés problémájával foglalkoztak.

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster