HSC
Cabinet de consultants en sécurité informatique depuis 1989 - Spécialisé sur Unix, Windows, TCP/IP et Internet
Mode texte : accès au contenu de la page
Hervé Schauer Consultants
Vous êtes ici : Accueil > Ressources > Brèves > Analyse du protocole Microsoft SSTP
Accéder au : Site HSC des formations
Recherche :  
English version
   Services   
o Domaines de compétences
o Conseil & Expertise
o Prestations ISO 27001
o Veille en vulnérabilités
o Audit & Évaluation
o Tests d'intrusion
o Tests de vulnérabilités (TSAR)
o Analyse Forensique
o Certification ARJEL
o Formations
o E-learning
   Conférences   
o Agenda
o Interventions passées
o Tutoriels
   Ressources   
o Index thématique
o Brèves
o Présentations
o Cours
o Articles
o Outils (téléchargement)
o Veille en vulnérabilité
   Société   
o Hervé Schauer
o Equipe
o Offres d'emploi
o Références
o Historique
o Partenariats
o Associations
   Presse et
 communication
 
 
o Newsletter HSC
o Revue de presse
o Communiqués de presse
o Publications
   Contacts   
o Coordonnées
o Requêtes particulières
o Accès à nos locaux
o Hôtels proches de nos locaux
|>|Analyse du protocole Microsoft SSTP  

par Christophe Alladoum (12/07/11)



---------------------[ Analyse du protocole Microsoft SSTP ]--------------------


---[ Résumé ]-------------------------------------------------------------------
Cette brève analyse le protocole SSTP, le nouveau protocole de VPN de Microsoft
supporté par les OS à partir de NT 6.0. Au cours de cette brève, nous évoquerons
la nature et le fonctionnement global de SSTP; fonctionnement qui a amené la
création d'un client SSTP pour les systèmes d'exploitation Linux, nommé
SSToPer. Enfin, une dernière partie évoque des perspectives intéressantes dans
l'optique de la sécurité du protocole.


---[ 1. Introduction ]----------------------------------------------------------
A partir de Windows Server 2008, Microsoft intègre un nouveau mécanisme
d'établissement de connexion VPN. L'objectif de ce nouveau protocole, nommé SSTP
- pour Secure Socket Tunneling Protocol - est d'établir une connexion PPP
encapsulée dans une couche SSL assurant confidentialité et intégrité. SSTP a
pour vocation de faciliter grandement la création de tunnel VPN, pouvant
être véhiculé via des serveurs HTTP mandataires (proxy Web), mais également de
pouvoir passer plus facilement les pare-feu, puisqu'il se fait passer pour une
pseudo connexion HTTP.

SSTP fonctionne par la création d'un tunnel HTTP sur SSL et se rapproche
beaucoup du fonctionnement de SSLTunnel [SSLTUNNEL], SSTP n'est donc pas en
soit un protocole de VPN, il facilite uniquement, via l'encapsulation dans du
HTTPS, la création d'une connexion VPN par le protocole PPP.

Cette brève revient sur le fonctionnement détaillé du protocole SSTP, notamment
son établissement de connexion à partir d'une simple connexion SSL, jusqu'à
l'ouverture d'une session PPP.
La deuxième partie explique l'utilisation du client Linux développé pour SSTP,
SSToPer.
La troisième partie aborde les aspects sécurité du protocole, et comment les
implémentations dans 2008/Vista/Seven se protègent de certaines attaques
classiques. Toutefois, cette brève se limitera à l'étude de la sécurité du
protocole SSTP, et n'évoquera pas des éventuelles attaques possibles sur
l'implémentation (client comme serveur).


---[ 2. Fonctionnement du protocole ]-------------------------------------------
Pour pouvoir passer plus facilement les contraintes des pare-feu, une session
SSTP va s'initier tout d'abord en ouvrant une socket SSL vers le serveur
destination sur le port (par défaut) 443/tcp en simulant une connexion HTTP
spéciale. Une fois faite, la couche SSTP se substituera à HTTP pour encapsuler
les octets PPP.

Cette partie est consacrée au fonctionnement du protocole SSTP, basé sur la
spécification fournie sur le site du MSDN, mais qui s'est toutefois avérée
incomplète sur certains points.

Pour clarifier les explications, le comportement sera étayé d'extrait de sortie
des outils sstoper et pppd. De même, pour ne pas trop alourdir cette brève, il
est laissé à la curiosité du lecteur l'examen des fichiers sources de SSToPer
pour l'implémentation détaillée de la partie cryptographique.


-----[ 2.1 Schéma de la pile SSTP ]---------------------------------------------

   +-------------------+
   |                   |
   |       PPP         |
   |                   |
   +-------------------+
   |                   |
   |       SSTP        |
   |                   |
   +-------------------+
   |                   |
   |       HTTP        |
   |                   |
   +-------------------+
   |                   |
   |       SSL         |
   |                   |
   +-------------------+
   |                   |
   |      TCP/IP       |
   |                   |
   +-------------------+
   
    Pile d'encapsulation
    d'une session SSTP


-----[ 2.2 Négociation HTTP ]---------------------------------------------------
Cette requête possède une structure tout à fait analogue à celle d'une requête
HTTP traditionnelle, et pour cause, la couche SSTP est effectivement encapsulée
dans un tunnel HTTP over SSL (HTTPs) afin de mieux passer les pare-feu. Côté
serveur, IIS associera la gestion d'une ressource un peu spéciale,
/sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/ par défaut, au service SSTP, géré
par la DLL sstpsvc.dll.

Le détail du paquet HTTP initiale est décrit ci-dessous:

- Méthode : SSTP_DUPLEX_POST
- Chemin URI : /sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/
- Version du protocole HTTP : HTTP/1.1
- Host: <nom_du_serveur>**

Cette structure est bien celle d'un entête HTTP. 2 entêtes HTTP supplémentaires
spéciaux viennent se greffer à la requête:
- SSTPCORRELATIONID: {<GUID>}**
- Content-Length: 18446744073709551615

** : champs dynamiques
Le champ Host recevra le nom du serveur (comme une requête HTTP classique), et
le SSTPCORRELATIONID possèdera un identifiant unique de connexion défini par le
client (GUID). Le champ Content-Length contient toujours la valeur
18446744073709551615 qui correspond à la taille d'un champ de type « Unsigned
Long Long ».

Cette unique requête HTTP permettra d'isoler aisément un serveur IIS gérant le
SSTP par son retour(**), à savoir 200 OK; les serveurs n'implémentant pas cette
méthode répondant par des codes divers :
{{{
$ # envoi d'une requête de type SSTP_DUPLEX_POST vers un Apache (Ubuntu)
$ openssl s_client -connect 192.168.51.1:443
SSTP_DUPLEX_POST /sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/ HTTP/1.1
[...]
HTTP/1.1 413 Request Entity Too Large
Date: Sun, 26 Jun 2011 10:14:54 GMT
Server: Apache/2.2.8 (Ubuntu)
[...]

$ # idem vers GFE
HTTP/1.1 405 Method Not Allowed
Date: Sun, 26 Jun 2011 10:24:10 GMT
Server: GFE/2.0
[...]

$ # idem vers nginx
HTTP/1.1 411 Length Required
Server: nginx/0.7.67
Date: Sun, 26 Jun 2011 10:26:42 GMT
[...]
}}}

Les serveurs IIS sachant gérer le SSTP (le service n'étant pas installé par
défaut), seront ensuite en attente de la négociation. SSTP étant prévu pour
fonctionner sur une infrastructure SSL, on trouvera donc souvent le service
"Active Directory Certificate Services" présent. Si ce dernier est présent et
ouvert sur Internet, un simple petit Google-Fu nous permettra de lister les
services CA de MS Windows 2008 accessibles.
{{{
inurl:/certsrv/certrqus.asp
}}}

Puis, on peut fingerprinter un potentiel service HTTP en émettant une requête
d'initialisation SSTP qui nous indiquera la présence ou non d'un service SSTP
derrière.
{{{
$ openssl s_client -connect tweety.looney:443
[...]
> SSTP_DUPLEX_POST /sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/ HTTP/1.1
> Host: tweety.looney
> SSTPCORRELATIONID: {62DFA5C0-E2E0-FD50-D286B00}
> Content-Length: 18446744073709551615


< HTTP/1.1 200
< Content-Length: 18446744073709551615
< Server: Microsoft-HTTPAPI/2.0
< Date: Sun, 26 Jun 2011 13:10:59 GMT
}}}

(**: cette technique est notamment celle utilisée dans le script SSTP_reveal.py
(§7.1) pour détecter un service SSTP actif sur un serveur visé).


-----[ 2.3 Négociation SSTP ]---------------------------------------------------
Comme tout protocole qui se respecte, SSTP fonctionne selon un automate à état
fini.

Deux canaux sont utilisés dans la session:
- un canal de données, encapusulant les octets de la couche PPP;
- un canal de contrôle, effectuant le paramétrage de la couche SSTP. Les paquets
  de contrôle sont caractérisés par un type, et optionnellement un ou plusieurs
  attributs.

Une fois, le tunnel dans HTTPS ouvert, le client envoie un message de contrôle
d'établissement de connexion, SSTP_MSG_CALL_CONNECT_REQUEST, avec un unique
attribut, SSTP_ATTRIB_ENCAPSULATED_PROTOCOL_ID. Cet attribut indiquera que nous
souhaitons communiquer selon le protocole SSTP. Si le serveur n'accepte pas la
connexion, il renverra un SSTP_MSG_CALL_CONNECT_NAK fermant la connexion chez le
client. Autrement, par un message SSTP_MSG_CALL_CONNECT_ACK renvoyé par le
serveur, ce dernier indique accepter la connexion, et fournit un attribut
SSTP_ATTRIB_CRYPTO_BINDING_REQ initiant la phase de "Cryptographic Binding".

Pour cette phase, la main est alors cédée au démon pppd [PPPD] commençant la
négociation PPP, où l'on retrouve les phases d'une authentification classique
avec le protocole MS-CHAPv2. Cette phase doit se dérouler avec succès pour que
l'authentification SSTP puisse être se continuer avec succès. Un client SSTP
doit donc posséder un champ pour stocker l'état de la négociation CHAP; champ à
modifier dès lors que la négociation s'est correctement faite.
{{{
Using interface ppp0
Connect: ppp0 <--> /dev/pts/7
[...]
sent [LCP ConfReq id-0x1 <asyncmap 0x0> <magic 0x81f3d98d> <pcomp> <accomp>]
rcvd [LCP ConfReq id-0x3 <mru 4091> <auth chap MS-v2> <magic 0x20396595> <pcomp> <accomp> <endpoint [local:2a.66.6c.cf.c0.ca.40.98.87.4c.c0.04.cd.c4.bb.7a.00.00.00.00]>]
sent [LCP ConfAck id-0x3 <mru 4091> <auth chap MS-v2> <magic 0x20396595> <pcomp> <accomp> <endpoint [local:2a.66.6c.cf.c0.ca.40.98.87.4c.c0.04.cd.c4.bb.7a.00.00.00.00]>]
rcvd [LCP ConfAck id-0x1 <asyncmap 0x0> <magic 0x81f3d98d> <pcomp> <accomp>]
rcvd [CHAP Challenge id-0x0 <157a62d6f6474e2f6ac71910e4591c1c>, name - "SSTP-Server-2k8"]
sent [CHAP Response id-0x0 <85e8ee288fdbb4c4f2cde1ae4939d5050000000000000000185e54a534398f956b9b0b985526116227a44585f1f9c5c900>, name - "test-sstp"]
rcvd [CHAP Success id-0x0 "S-352FC947B3F000F33B87374DEF9448F7ADD50DEC"]
CHAP authentication succeeded
}}}

La couche SSTP étant située entre PPP et le SSL, il est donc aisé de contrôler
le suivi de l'authentification MS-CHAPv2 dans PPP. Lorsque celle-ci s'achève
avec succès, un paquet de réponse est émis, contenant un champ NT-Response,
comme décrit dans la RFC 2759 [PPPCHAP], sections 4 et 8.
{{{
4.  Response Packet
[...]
16 octets: Peer-Challenge
    8 octets: Reserved, must be zero
   24 octets: NT-Response
    1 octet : Flags
}}}

Le NT-Response est situé à un offset de 24 octets dans le paquet de réponse
(CHAP Response dans le listing précédent).

{{{
[...]
      uint8_t chap_handshake_code = *(uint8_t*)(data + 2);
      
      /* if msg is PPP-CHAP response */
      if (chap_handshake_code == 0x02 )
        {
          memcpy(chap_ctx, data+7, 49);
        }
    }
}}}


A partir du contexte CHAP correctement initié, le client SSTP doit alors
calculer par dérivation 5 clés de session. Ce trousseau de clés est calculé de
façon quasi identique sur le client et le serveur, via des fonctions de
dérivation injectives à partir du contexte CHAP.

Ces clés sont :
- Master Key: cette clé est calculé avec le champ NT-Response issue de la
  négociation MS-CHAPv2 de PPP, ainsi du MD4(MD4(Mot_de_passe_Utilisateur));
  
- Master Send Key (MSK) et Master Receive Key (MRK) toutes deux dérivées de la
  Master Key;
  
- Higher-Layer Authentication Key (HLAK): pour le client, il s'agit de la
  concaténation de la MRK puis MSK(*);
  
- Compound Mac Key (CMK): l'algorithme HMAC-SHAx(**) sera appliquée la chaine
  "SSTP inner method derived CMK", avec comme clé la HLAK;
  
- Compound Mac (CMac): l'algorithme HMAC-SHAx(**) sera appliquée sur le bloc
  SSTP_CALL_CONNECTED_MSG_ZEROED, avec comme clé la CMK. Le bloc
  SSTP_CALL_CONNECTED_MSG_ZEROED correspond au paquet SSTP_CALL_CONNECTED_MSG où
  le champ CMac a été remplacé par des zéros(***).

Le déroulement des calculs des différentes clés suit strictement les étapes
décrites dans [MPPE] section 3, « Deriving Session Keys from MS-CHAPv2
Credentials ».

L'ensemble de ces clés et d'autres éléments seront calculés par le client, et
envoyés au serveur dans un message de contrôle de type SSTP_MSG_CALL_CONNECTED,
avec l'attribut SSTP_ATTRIB_CRYPTO_BINDING.

A partir de ce moment, la session SSTP est correctement établie, et le tunnel IP
dans PPP prêt à communiquer. \o/


*: la spécification SSTP fournie par Microsoft indique que la HLAK est
construite par la concaténation de MSK | MRK, hors l'implémentation de
SSToPer a clairement montré qu'il s'agissait bien de la conténation MRK |
MRK. Ce point a été remontée, mais n'a pas reçu de suite.
**: SSTP supporte actuellement HMAC-SHA1 et HMAC-SHA256, négocié au
préalable. Le HMAC-SHA256 est le mode préféré. La négociation en mode HMAC-SHA1
est identique à celle de HMAC-SHA256, à cela près que HMAC-SHA1 effectuera un
bourrage d'octets à zéro pour être correctement aligné sur 32 bits.
***: cette partie n'est que vaguement documentée par la spécification mais est
nécessaire pour calculer correctement le CMac nécessaire pour
l'authentification. Le lecteur curieux pourra se reporter aux sources de SSToPer
pour davantage d'explication.


-----[ 2.4 Session SSTP ]-------------------------------------------------------
La session connectée de SSTP est quasiment passive, car la couche SSTP ne sert
qu'à relayer les paquets PPP pour les encapsuler dans des paquets de type
SSTP_DATA_PACKET et les transmettre au serveur.
Sur Linux, le démon pppd aura créé une nouvelle interface (par convention nommée
pppX, avec X un entier), qui hébergera le tunnel IP. L'adresse IP de l'interface
sera fournie dans un paquet IPCP comme le montrent les journaux d'événements
pppd. On notera donc qu'on peut également faire de l'IPv6 avec SSTP.
{{{
sent [IPCP ConfReq id-0x3 <addr 192.168.56.196>]
rcvd [IPCP ConfAck id-0x3 <addr 192.168.56.196>]
rcvd [IPCP ConfReq id-0x8 <addr 192.168.56.192>]
sent [IPCP ConfAck id-0x8 <addr 192.168.56.192>]
local  IP address 192.168.56.196
remote IP address 192.168.56.192
}}}

Toutefois, SSTP ne reste pas totalement passif. En effet, le serveur émet toutes
les 70 secondes (par défaut) des paquets SSTP_MSG_ECHO_REQUEST, assimilables aux
ICMP Echo Request. Par conséquent, il sera en attente d'un paquet de réponse
SSTP_MSG_ECHO_REPONSE provenant du client pour garder le tunnel actif. En cas de
timeout, le tunnel sera fermé.

{{{
2011-06-26 14:06:48  [+] <--  8 bytes
2011-06-26 14:06:48  [*]        -> Control packet
2011-06-26 14:06:48  [*]        -> type: SSTP_MSG_ECHO_REQUEST (0x08)
2011-06-26 14:06:48  [*]        -> attribute number: 0
2011-06-26 14:06:48  [*]        -> length: 4

2011-06-26 14:06:48  [+]  --> 8 bytes
2011-06-26 14:06:48  [*]        -> Control packet
2011-06-26 14:06:48  [*]        -> type: SSTP_MSG_ECHO_REPONSE (0x09)
2011-06-26 14:06:48  [*]        -> attribute number: 0
2011-06-26 14:06:48  [*]        -> length: 4
}}}

A l'inverse, le client peut également déclencher ce mécanisme de ping SSTP.


-----[ 2.5 Fermeture de session ]-----------------------------------------------
Que la session SSTP soit établie ou en cours d'établissement, il est possible de
fermer le tunnel et désallouer les ressources allouées via l'émission d'un
message de contrôle de type SSTP_MSG_CALL_DISCONNECT, n'ayant pas
d'attribut.
{{{
2011-06-26 15:14:59  [+]  --> 8 bytes
2011-06-26 15:14:59  [+] Sending SSTP_MSG_CALL_DISCONNECT message.
2011-06-26 15:14:59  [*]        -> Control packet
2011-06-26 15:14:59  [*]        -> type: SSTP_MSG_CALL_DISCONNECT (0x06)
2011-06-26 15:14:59  [*]        -> attribute number: 0
2011-06-26 15:14:59  [*]        -> length: 4
}}}

L'autre bout du tunnel acquittera cette demande en renvoyant un
SSTP_MSG_CALL_DISCONNECT_ACK.


---[ 3. SSToPer ]---------------------------------------------------------------
SSToPer (prononcez «stoppeur») est un client Linux pour le protocole SSTP ou
plus exactement une implémentation de la couche SSTP nécessaire à
l'établissement de la connexion VPN vers un Windows 2008+. SSToPer va donc se
charger de faire tous les mécanismes de négociation SSTP, puis cède la main au
processus pppd(8)[PPPD] en encapsulant les paquets PPP dans des messages
SSTP_DATA_PACKET via un openvty(3).

Pour être exécuté, SSToPer n'a besoin que des identifiant et mot de passe de
l'utilisateur à authentifier, le FQDN du serveur ou son adresse IP, ainsi que
son certificat au format PEM. Ce dernier peut être récupéré par le script
SSTP_reveal.py (§7.1).

SSToPer vérifie le bon passage des paramètres puis initie la négociation HTTP
dans une socket SSL.
{{{
> SSTP_DUPLEX_POST /sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/ HTTP/1.1
> Host: tweety.looney
> SSTPCORRELATIONID: {897950C0-2CD0-D280-20450C00}
> Content-Length: 18446744073709551615
>
>

< HTTP/1.1 200
< Content-Length: 18446744073709551615
< Server: Microsoft-HTTPAPI/2.0
< Date: Fri, 24 Jun 2011 09:06:14 GMT
<
}}}

Le processus décrit en §2.3 va être dérouler par SSToPer qui a perdu tous
ses privilèges (utilisateur nobody). Les parties chiffrement et authentification
NTLM sont également gérées par SSToPer.

Via les options passées à la fois à SSToPer et au démon PPPD, il est possible de
suivre de façon très détaillée les étapes de négociation SSTP.

{{{
2011-06-29 19:13:31  [*] Switch user to 'nobody'
2011-06-29 19:13:31  [+] Initiating SSTP negociation
2011-06-29 19:13:32  [*]      -> Control packet
2011-06-29 19:13:32  [*]      -> type: SSTP_MSG_CALL_CONNECT_REQUEST (0x01)
2011-06-29 19:13:32  [*]      -> attribute number: 1
2011-06-29 19:13:32  [*]      -> length: 10
2011-06-29 19:13:32  [*]         --> Attribute 0
2011-06-29 19:13:32  [*]         --> type: SSTP_ATTRIB_ENCAPSULATED_PROTOCOL_ID (1)
2011-06-29 19:13:32  [*]         --> length: 6
2011-06-29 19:13:32  [+]  --> 14 bytes
2011-06-29 19:13:32  [+] status: CLIENT_CALL_DISCONNECTED (0) -> CLIENT_CONNECT_REQUEST_SENT (0x1)
2011-06-29 19:13:32  [+]  --> 28 bytes
2011-06-29 19:13:32  [+] <--  48 bytes
2011-06-29 19:13:32  [*]      -> Control packet
2011-06-29 19:13:32  [*]      -> type: SSTP_MSG_CALL_CONNECT_ACK (0x02)
2011-06-29 19:13:32  [*]      -> attribute number: 1
2011-06-29 19:13:32  [*]      -> length: 44
2011-06-29 19:13:32  [*]         --> attr_id     SSTP_ATTRIB_CRYPTO_BINDING_REQ (0x04)
2011-06-29 19:13:32  [*]         --> len         40 bytes
2011-06-29 19:13:32  [+] status: CLIENT_CONNECT_REQUEST_SENT (0x1) -> CLIENT_CONNECT_ACK_RECEIVED (0x2)
}}}

A partir de ce moment, SSToPer attend et surveille le bon déroulement de la
négociation MS-CHAPv2. Les options de debug (flag -D DEBUG à la compilation)
permettent également d'afficher les jeux de clés calculés depuis contexte le
MS-CHAPv2.
{{{
2011-06-29 19:20:17  [*] [Crypto debug] Hash algorithm          CERT_HASH_PROTOCOL_SHA256 (0x2)
2011-06-29 19:20:17  [*] [Crypto debug] Nonce                   0xab65ed2e4c5edf8d4e5836033652be32b10d1240a8734dbd4bf6f17b093db62d
2011-06-29 19:20:17  [*] [Crypto debug] CA Hash                 0x69f6c50f7e2647994c2d7dbff1b6beee1f3553daa5a399513a03bfa44e6808bc
2011-06-29 19:20:17  [*] [Crypto debug] T1 msg                  0x555526666726676662667676624442001
2011-06-29 19:20:17  [*] [Crypto debug] H(Password)             0x962af1484337b0ad6
2011-06-29 19:20:17  [*] [Crypto debug] H(H(Password))          0x1bde8c9fe46e33098
2011-06-29 19:20:17  [*] [Crypto debug] NT Response code        0x2965dd5a72ce058248213056f
2011-06-29 19:20:17  [*] [Crypto debug] Master Key              0xee3f85b74647db9f6
2011-06-29 19:20:17  [*] [Crypto debug] Master Send Key         0x84bb3a5db4bc66d58
2011-06-29 19:20:17  [*] [Crypto debug] Master Receive Key      0x68caaa530195c0d1c
2011-06-29 19:20:17  [*] [Crypto debug] HLAK                    0x68caaa530195c0d184bb3a5db4bc66d58
2011-06-29 19:20:17  [*] [Crypto debug] CMac                    0x0786229e78be73d132510996eab9806bb01524340f19bbdb142958c13af62ca1
2011-06-29 19:20:17  [*] [Crypto debug] CMK                     0xd8563831ac0a0e61f969ffc9cfba69f613755a2e6177db09989e36405473d71e
2011-06-29 19:20:17  [*]        -> Control packet
2011-06-29 19:20:17  [*]        -> type: SSTP_MSG_CALL_CONNECTED (0x04)
2011-06-29 19:20:17  [*]        -> attribute number: 1
2011-06-29 19:20:17  [*]        -> length: 108
2011-06-29 19:20:17  [*]           --> Attribute 0
2011-06-29 19:20:17  [*]           --> type: SSTP_ATTRIB_CRYPTO_BINDING (3)
2011-06-29 19:20:17  [*]           --> length: 104
2011-06-29 19:20:17  [+]  --> 112 bytes
}}}

Ici, la connexion est établie et le processus SSToPer agit comme un relai pour
encapsuler les octets provenant de pppd(8) dans des messages de données SSTP
elles-mêmes encapsulées dans du SSL. Le principe de fonctionnement est tout à
fait comparable à celui de l'outil SSLTunnel[SSLTUNNEL], avec en plus la gestion
du mécanisme de ping évoqué en §2.5.

{{{{
2011-06-29 19:13:43  [+] status: CLIENT_CONNECT_ACK_RECEIVED (0x2) -> CLIENT_CALL_CONNECTED (0x3)
2011-06-29 19:13:43  [+] SSTP link established
2011-06-29 19:13:43  [*]        -> Control packet
2011-06-29 19:13:43  [*]        -> type: SSTP_MSG_ECHO_REQUEST (0x08)
2011-06-29 19:13:43  [*]        -> attribute number: 0
2011-06-29 19:13:43  [*]        -> length: 4
2011-06-29 19:13:43  [+]  --> 8 bytes
2011-06-29 19:13:43  [+] <--  32 bytes
2011-06-29 19:13:43  [*]        -> Data packet
2011-06-29 19:13:43  [+] <--  8 bytes
2011-06-29 19:13:43  [*]        -> Control packet
2011-06-29 19:13:43  [*]        -> type: SSTP_MSG_ECHO_REPONSE (0x09)
2011-06-29 19:13:43  [*]        -> attribute number: 0
2011-06-29 19:13:43  [*]        -> length: 4
2011-06-29 19:13:43  [+]  --> 22 bytes
}}}


Enfin, en cas de demande de déconnexion du serveur ou du client, SSToPer envoie
le message SSTP_MSG_CALL_DISCONNECT et attend la bonne fin du processus pppd(8).

Du point de vue d'implémentation, SSToPer n'est destiné qu'aux Linux dotés d'un
noyau 2.6+, car il repose sur les mécanismes des capacités noyau (man
capabilities) pour diminuer ses privilèges au possible. En effet, SSToPer n'a
quasi pas besoin de privilège élevé. Ainsi, il n'est pas nécessaire de lancer sstoper
en tant que root. L'installation par le Makefile se chargera de créer un groupe
dédié, nommé sstoper, et positionnera les capacités adéquat sur le binaire
(comme le fait wireshark par exemple). Lancer sstoper en tant que root
provoquera l'affichage d'un message d'avertissement
{{{
$ sudo ./sstoper -s 172.16.0.3 -U test-sstp -P SSTP_Wins_1234 -c /tmp/2k8r2.cer
2011-06-26 12:42:45  [!] ./sstoper is running as root. This could be potentially dangerous
You should consider using capabilities.
[...]
}}}

Le manuel de sstoper(8) détaille les autres différentes options accessibles.


---[ 4. Sécurité sur SSTP ]-----------------------------------------------------
Conceptuellement, SSTP est supposé résister à certaines attaques bien connues :
- interception SSL : le client natif de Windows Vista/Seven refusera une
  connexion SSL s'il n'est pas capable de valider le certificat du serveur. On
  notera toutefois que ce paramètre (ainsi que tous les paramètres SSTP côté
  client) peut (peuvent) être modifié(s) depuis
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\SstpSvc et
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\SstpSvc\Parameters. Les
  options des clés sont détaillés dans [SSTPOPTIONS].

- Man-In-The-Middle : le mécanisme décrit plus haut, Crypto Binding empêche les
  attaques de type MITM où le serveur validera les informations du côté grâce
  aux clés renvoyées, clés ne pouvant être calculés sans connaissance du mot de
  passe et du code NT-Response de l'authentification MS-CHAPv2.

Autrement dit, une grosse partie de la sécurité du protocole SSTP repose sur
l'infrastructure SSL déployée; les clients inclus dans MS Vista et Seven
requerrant des certificats valides.
Chose curieuse, on notera qu'un serveur SSTP peut délibérément choisir de
désactiver la couche SSL via la base de registre de Windows,  ce qui
rend bien évidemment la communication beaucoup plus vulnérables, mais facilite
grandement son étude avec un sniffer réseau comme Wireshark.


---[ 5. Conclusion ]------------------------------------------------------------
Au cours de cette brève, nous sommes revenus sur son fonctionnement détaillé,
qui a été utilisé pour l'implémentation du client sous Linux, SSToPer; ainsi que
sur les mécanismes de sécurité implémentés.

Même si les technologies employées ne présentent pas de nouveautés (PPP, SSL,
etc.), et que le nombre d'encapsulation diminue le débit utile (ratio du nombre
d'octets effectivement envoyés pour envoyer un octet applicatif), SSTP est tout
de même intéressant dans son fonctionnement facilitant le passage des pare-feu,
et permettant d'être transmis au travers de proxy HTTP.


                                                          -- Christophe Alladoum


---[ 6. Références ]------------------------------------------------------------


[HTTPTUNNEL] - HttpTunnel - http://www.nocrew.org/software/httptunnel.html

[MPPE] - Deriving Keys for use with Microsoft Point-to-Point Encryption - http://tools.ietf.org/search/rfc3079

[PPPCHAP] - Microsoft PPP CHAP Extensions, Version 2 - http://tools.ietf.org/search/rfc2759

[PPPD] - pppd(8) - http://ppp.samba.org/

[SSLTUNNEL] - SSLTunnel - http://www.hsc.fr/ressources/outils/ssltunnel/

[SSTP] - SSTP Protocol Specification - http://msdn.microsoft.com/en-us/library/cc247338(PROT.10).aspx
  
[SSTPOPTIONS] - http://support.microsoft.com/kb/947054


---[ 7. Misc ]------------------------------------------------------------------
Ces snippets sont également fournis dans l'archive TAR de SSToPer, dans le
répertoire misc/.




-----[7.1. SSTP_reveal.py ]-----------------------------------------------------

from socket import socket
from ssl import wrap_socket
from sys import argv
from httplib import HTTPConnection

if len(argv) != 2:
    print("usage: python %s <target_ip_addr>" % argv[0])
    exit(1)
    
HOST = argv[1]
PORT = 443   # SSTP default port
http_neg = """
SSTP_DUPLEX_POST /sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/ HTTP/1.1\r
Host: %s\r
SSTPCORRELATIONID: {62DFA5C0-E2E0-FD50-D286B00}\r
Content-Length: 18446744073709551615\r
\r
""" % HOST

sock = socket()
sock.connect((HOST, PORT))
ssl_sock = wrap_socket(sock)
active = False

if ssl_sock is None:
    print ("[!] Failed to create socket")
    exit(1)

ssl_sock.write(http_neg)
data = ssl_sock.read()

if "HTTP/1.1 200" in data:
    print("[+] SSTP seams active.")
    active = True
else :
    print("[-] No SSTP service detected")
    
if ssl_sock:
    ssl_sock.close()

if not active :
    exit(0)

print("[+] Trying to download certificate")
i = 0
while True:
    http = HTTPConnection(HOST)
    http.request("GET", "/certsrv/certnew.cer?ReqID=CACert&Renewal=%d&Enc=b64" % i)
    resp = http.getresponse()
    
    if (resp.status != 200):
        break
    else :
        data = resp.read()
        if len(data) and data.startswith("-----BEGIN CERTIFICATE-----"):
            print("[+] Found certificate-%d\n" % i)
            print("{0}[ CUT HERE ]{0}\n".format("-"*30) )
            print ("%s" % data)
            print("{0}[ CUT HERE ]{0}\n".format("-"*30) )
        elif not data.startswith("-----BEGIN CERTIFICATE-----"):
            break
    i += 1
exit(0)


Dernière modification le 1 août 2011 à 16:17:10 CET - webmaster@hsc.fr
Informations sur ce serveur - © 1989-2010 Hervé Schauer Consultants