Firewall Piercing/Beispiele/OpenSSH via HTTPS-Proxy als SOCKS Proxy verwenden

Aus UUGRN
< Firewall Piercing‎ | Beispiele
Version vom 27. August 2011, 22:52 Uhr von Rabe (Diskussion | Beiträge) (Konkretes Beispiel, wie man mit Bordmitteln über einen HTTPS-Proxy und einem SSH-Daemon auf Port 443 aus einem gut gesicherten System ausbrechen kann.)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

Dieses Beispiel beschreibt den Ausbruch aus einem System, welches nur via HTTPS-Proxy auf das freie Internet zugreifen kann. Darüber hinaus soll die initiale SSH-Verbindung gleichzeitig einen SOCKS-Proxy anbieten, der dann für weitere SSH-Sessions verwendet werden kann.

Voraussetzungen für dieses Beispiel

Das Rhein-Neckar-Wiki läuft in einem Jail auf dem Server der Stadtwiki Gesellschaft e.V. (rnw.stwserv.de). Die Wiki-Jails sind aus Sicherheitsgründen per Firewall von extern nur auf 80/tcp und 443/tcp erreichbar und können selbst nur über einen Proxy-Server (relay.stwserv.de) mit der Aussenwelt kommunizieren. Der Proxy-Server ist ein HTTP-Proxy und erlaubt zusätzlich die für HTTPS erforderliche CONNECT-Methode auf Port 443/tcp (https)

Ferner existiert ein Shell-Account auf shell.uugrn.org. Der dortige OpenSSH-Daemon läuft zusätzlich zum Standardport 22/tcp auch auf 443/tcp.

Es soll zu Demonstrationszwecken gezeigt werden, wie man unter diesen Voraussetzungen mit OpenSSH und BSD-netcat als Hilfstool eine SSH-Verbidung auf einen mehr oder weniger beliebigen Server im Internet herstellen kann, sofern man dort grundsätzlich Login-Rechte hat.

SSH-Client Konfiguration

zumächst legen wir volgende ~/.ssh/config an (oder ergänzen die vorhandene entsprechend):

[rabe@rnw ~]$ cat .ssh/config 
Host shell443
        HostName shell.uugrn.org
        Port 443
        User rabe
        TCPKeepAlive yes
        DynamicForward 127.0.0.1:1080
        ProxyCommand /usr/bin/nc -X connect -x relay.stwserv.de:3128 %h %p


Host rabe.socks
        Hostname rabe.uugrn.org
        Port 22
        User rabe 
        ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:1080 %h %p

Das Profil ssh443 ist so angelegt, dass der Benutzer rabe sich auf shell.uugrn.org auf Port 443/tcp einloggt. Dabei wird mit dem ProxyCommand eine HTTPS-Proxy-Connection über relay.stwserv.de:3128 aufgebaut. Die so aufgebaute SSH-Session soll ausserdem einen SOCKS-Proxy auf 127.0.0.1:1080 bereitstellen.

Das Profil rabe.socks ist so angelegt, dass es auf rabe@rabe.uugrn.org:22 einloggt unter Verwendung des SOCKS(5)-Proxys auf 127.0.0.1:1080.


Initialer Verbindungsaufbau

nach shell.uugrn.org via HTTPS-Proxy
[rabe@rnw ~]$ ssh -N -f shell443 
The authenticity of host '[shell.uugrn.org]:443 (<no hostip for proxy command>)' can't be established.
DSA key fingerprint is c4:2e:90:bc:76:b7:ca:6e:69:fd:54:c8:21:4c:97:b8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[shell.uugrn.org]:443' (DSA) to the list of known hosts.
Password:
[rabe@rnw ~]$

Durch die Optionen -N und -f sorgen wir dafür, dass nach dem Verbindungsaufbau auf dem Zielsystem kein Kommando ausgeführt wird und sich der SSH-Client als Daemon weg-forkt. Wir landen daher wieder auf unserer lokalen Shell.

nach rabe.uugrn.org via SOCKS-Proxy
[rabe@rnw ~]$ ssh rabe.socks 
The authenticity of host 'rabe.uugrn.org (<no hostip for proxy command>)' can't be established.
DSA key fingerprint is 5b:13:fa:16:78:93:be:e9:5c:84:33:d3:63:b6:c1:9f.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'rabe.uugrn.org' (DSA) to the list of known hosts.
Password:

[rabe@rabe ~]$ 

Dieser Verbindungsaufbau liefert uns eine normale, interaktive Shell auf rabe.uugrn.org.

Spuren
  • Im Proxy-Logfile auf relay.uugrn.org erscheint hier lediglich ein CONNECT auf shell.uugrn.org:443 und die Anzahl der übertragenen Bytes. Allerdings erst, wenn die Verbindung zu shell.uugrn.org:443 abgebaut wird:
    1314483856.709 1579602 195.49.138.74 TCP_MISS/200 26199 CONNECT shell.uugrn.org:443 - DIRECT/195.49.138.100 -
  • Aus Sicht von shell.uugrn.org erfolgt der SSH-Login von relay.stwserv.de aus, d.h. es ist nicht sichtbar, dass der SSH-Client in Wirklichkeit auf rnw.stwserv.de läuft.
  • Aus Sicht von rabe.uugrn.org erfolgt der SSH-Login von shell.uugrn.org aus. Hier ist nichteinmal erkennbar, dass der Client ganz woanders läuft.


Ad-hoc

Man will möglicherweise nicht für jeden einzelnen Zielrechner, auf den man per SSH ausbrechen will erst in der ~/.ssh/config anlegen. Die erforderlichen Direktiven kann man auch mit -o 'Direktive Parameter' als Kommandozeilenparameter für den OpenSSH-Client angeben.

Beispiel

Es soll Ad-hoc unter Verwendung des SOCKS-Proxys auf sigsys.de zugegriffen werden und dort 'hostname ; echo $SSH_CLIENT' ausgeführt werden:

[rabe@rnw ~]$ ssh -o 'ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:1080 %h %p' rabe@sigsys.de 'hostname ; echo $SSH_CLIENT'
The authenticity of host 'sigsys.de (<no hostip for proxy command>)' can't be established.
DSA key fingerprint is df:ff:2a:d7:af:4e:99:44:ad:0d:9f:81:28:96:83:de.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'sigsys.de' (DSA) to the list of known hosts.
Password:
sigsys.de
195.49.138.100 55726 22
Zu sehen
der Login erfolgt tatsächlich auf sigsys.de und laut $SSH_CLIENT kommt die SSH-Verbindung auch via shell.uugrn.org (195.49.138.100) rein.
Nicht zu sehen
Es gibt es keinen Rückschluss auf rnw.stwserv.de oder relay.stwserv.de bzw. dass der SSH Client über einen SOCKS-Proxy via shell.uugrn.org reinkommt.

SOCKS Proxy funktioniert nicht

Versucht man einen nicht mehr vorhandenen SOCKS-Proxy zu verwenden, erhält man folgende Meldung:

ssh_exchange_identification: Connection closed by remote host

Schaut man genauer hin, findet man leider keine genaueren Infos, insbesondere nicht, dass netcat (nc) ein Problem hat:

[rabe@rnw ~]$ ssh -vvv -o 'ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:1080 %h %p' rabe@sigsys.de 'hostname ; echo $SSH_CLIENT' 
OpenSSH_5.1p1 FreeBSD-20080901, OpenSSL 0.9.8e 23 Feb 2007
debug1: Reading configuration data /home/rabe/.ssh/config
debug1: Reading configuration data /etc/ssh/ssh_config
debug2: ssh_connect: needpriv 0
debug1: Executing proxy command: exec /usr/bin/nc -X 5 -x 127.0.0.1:1080 sigsys.de 22
debug1: permanently_drop_suid: 1001
debug1: identity file /home/rabe/.ssh/identity type -1
debug1: identity file /home/rabe/.ssh/id_rsa type -1
debug1: identity file /home/rabe/.ssh/id_dsa type -1
ssh_exchange_identification: Connection closed by remote host


Idle-Timeout

Im gezeigten Setup wird der HTTPS-Proxy die Verbindung zwangsweise nach einer gewissen Zeit trennen, wenn keine Daten übertragen wurden (idle timeout). Das betrifft primär die Verbindung zu shell.uugrn.org:443, die als SOCKS-Proxy fungiert. Die Direktive TCPKeepAlive yes sorgt hier nicht dafür, dass Payload-Daten übertragen werden, entsprechend wird eine andere Methode benötigt.

Mit ServerAliveInterval und ServerAliveCountMax veranlasst man den OpenSSH Client, regelmäßig Alive-Messages mit dem OpenSSH Server auszutauschen. Hierbei werden innerhalb der SSH-Verbindung Daten übertragen. Wenn mehr als ServerAliveCountMax Messages fehlschlagen, erklärt der SSH-Client die Verbindung für abgebrochen und beendet sich.

Wir nutzen dieses Feature, um regelmäßig Payload-Daten zu übertragen und somit dem Idle-Timeout durch den HTTPS-Proxy vorzubeugen.

ssh_config(5)
     ServerAliveCountMax
             Sets the number of server alive messages (see below) which may be
             sent without ssh(1) receiving any messages back from the server.
             If this threshold is reached while server alive messages are
             being sent, ssh will disconnect from the server, terminating the
             session.  It is important to note that the use of server alive
             messages is very different from TCPKeepAlive (below).  The server
             alive messages are sent through the encrypted channel and there-
             fore will not be spoofable.  The TCP keepalive option enabled by
             TCPKeepAlive is spoofable.  The server alive mechanism is valu-
             able when the client or server depend on knowing when a connec-
             tion has become inactive.

             The default value is 3.  If, for example, ServerAliveInterval
             (see below) is set to 15 and ServerAliveCountMax is left at the
             default, if the server becomes unresponsive, ssh will disconnect
             after approximately 45 seconds.  This option applies to protocol
             version 2 only.

     ServerAliveInterval
             Sets a timeout interval in seconds after which if no data has
             been received from the server, ssh(1) will send a message through
             the encrypted channel to request a response from the server.  The
             default is 0, indicating that these messages will not be sent to
             the server.  This option applies to protocol version 2 only.

Der Standardwert für ServerAliveCountMax 3 ist für unseren Anwendungsfall ausreichend, als ServerAliveInterval benötigen wir einen Wert, der definitiv geringer ist als der Timeout vom HTTPS-Proxy. Auf der sicheren Seite sind wir bei 5 min oder 300 sec.

Die Datei ~/.ssh/config sollte daher mindestens um ServerAliveInterval 300 ergänzt werden:

Host shell443
        HostName shell.uugrn.org
        Port 443
        User rabe
        TCPKeepAlive yes
        ServerAliveInterval 300
        DynamicForward 127.0.0.1:1080
        ProxyCommand /usr/bin/nc -X connect -x relay.stwserv.de:3128 %h %p