Skip to content

Latest commit

 

History

History

LEAK_CVE-2017-1000250

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

Remote leak heap data from linux devices with bluetooth opened and discoverabled

Cibles uniquement OS Linux

Usage et Sources

Challenge: 
gcc -o chall1 challenge_leak.c -lbluetooth
sudo ./chall1 [Addr_BT_Target] [Leak_Offset]

Correction: 
gcc -o leak answers_leak.c -lbluetooth
sudo ./leak [Addr_BT_Target] [Leak_Offset]

Lien vers le papier de recherche expliquant la vulnérabilité du code SDP: Armis BlueBorne Technical Paper

Lien vers le code Bluez avec la fonction SDP vulnérable service_search_attr_req

Copie du code Bluez avec la partie vulnérable en surlignée:

} else {
/* continuation State exists -> get from cache */
sdp_buf_t *pCache = sdp_get_cached_rsp(cstate);
if (pCache) {
uint16_t sent = MIN(max, pCache->data_size - cstate->cStateValue.maxBytesSent);
pResponse = pCache->data;
memcpy(buf->data, pResponse + cstate->cStateValue.maxBytesSent, sent);
buf->data_size += sent;
cstate->cStateValue.maxBytesSent += sent;
if (cstate->cStateValue.maxBytesSent == pCache->data_size)
cstate_size = sdp_set_cstate_pdu(buf, NULL);
else
cstate_size = sdp_set_cstate_pdu(buf, cstate);

Quelques informations sur les fonctions utilisées dans le code C:

Explications de la vulnérabilité

Le Session Description Protocol (SDP) est un protocole de communication de description de paramètres d'initialisation d'une session de diffusion en flux (streaming).

Pour découvrir des services, un client SDP envoie une SDP request et attends le retour d'une réponse appropriée du serveur SDP. Le protocol SDP dispose d'un méchanisme de fragmentation pour les SDP responses retournées par un serveur SDP. Ce méchanisme de fragmentation appelé SDP Continuation fonctionne de manière un peu différente d'un méchanisme de fragmentation "normal":

  1. Le client envoie une SDP request
  2. Si la réponse dépasse la MTU définie lors de la connections L2CAP (672 par défault), un premier fragment de la réponse est retourné dans lequel est ajouté la structure continuation state.
  3. Pour recevoir les fragments restatns, le client SDP doit re-envoyer la même SDP request en y ajoutant cette fois le continuation state qu'il a reçu lors de la précedente réponse. Ce type de requête est appelé continuation request.
  4. Le serveur SDP envoie alors le fragment de réponse suivant.

Il est possible d'abuser de ce méchanisme de continuation state du fait que le client est libre de modifier ses valeurs à chaque continuation request .

“The format of the continuation information is not standardized among SDP servers. Each continuation state parameter is meaningful only to the SDP server that generated it.” Bluetooth Specification v5.0, Vol 3, Part B, page 1926

SDP Continuation Struct, as defined in BlueZ (src/sdpd-request.c):

typedef struct {
  uint32_t timestamp;
  union {
    uint16_t maxBytesSent;
    uint16_t lastIndexSent;
  } cStateValue;
} sdp_cont_state_t;

Cette structure permet aisément de récuper le timestamp de la machine cible, permettant au serveur SDP d'entrer dans certaines partie de code (il va utiliser des données mis en cache lorsqu'il voit un paquet SDP avec le même timestamp).

Et comme un attaquant peut contrôler facilement la structure du continuation state envoyé à chaque requêtes, il peut modifier ses valeurs, notamment l'index maxBytesSent que l'on va utiliser comme un pointeur d'adresse pour fuire des données.

Excerpt from SDP Search Attribute Request handler - service_search_attr_req (src/sdpd-request.c):

...
} else {
/* continuation State exists -> get from cache */
sdp_buf_t *pCache = sdp_get_cached_rsp(cstate);
if (pCache) {
  uint16_t sent = MIN(max, pCache->data_size - cstate->cStateValue.maxBytesSent);
  pResponse = pCache->data;
  memcpy(buf->data, pResponse + cstate->cStateValue.maxBytesSent, sent);
  buf->data_size += sent;
  cstate->cStateValue.maxBytesSent += sent;
  if (cstate->cStateValue.maxBytesSent == pCache->data_size)
    cstate_size = sdp_set_cstate_pdu(buf, NULL);
  else
    cstate_size = sdp_set_cstate_pdu(buf, cstate);
} ...

Ci-dessus, la partie du code vulnérable dans Bluez SDP Server. On remarque que ce code situé dans la fonction service_search_attr_req de sdpd-request.c. ne valide pas correctement le maxByteSent provenant du cstate et permet alors d'utiliser le memcpy pour copier des données au-delà de la taille allouée par pResponse en utlisant cette valeur de maxByteSent comme pointeur des données à faire fuire.

La seule chose qu'un attaquant doit réaliser pour réussir ce leak est d'empêcher la validation des données à envoyer (maxByteSent == data_size), ce qu'il peut faire facilement car il contrôle la valeur de maxByteSent.

La valeur de pResponse étant stoquée sur la Heap, cette fuite d'information peut permettre à l'attaquant d'y trouver d'autres données sensibles comme des clés de chiffrement utilisées dans les protocoles de communication, etc...

Explication du Challenge

Ce challenge consiste uniquement en la modification de 4 lignes de code du script challenge_leak.c. Il repose surtout sur la compréhension du méchanisme de fragmentation, en l'observation du paquets SDP avec une capture Wireshark et en la compréhension de la vulnérabilité de sdp-request.c et de son exploitation. Ce challenge tuto est donc purement éducatif, il n'y aura donc pas de flag à trouver.

Nous n'allons pas nous interresser à la Part1 du main (ni tout ce qui le précède) qui consiste à créer la socket de communication Bluetooth, y associer les différentes addresses MAC Bluetooth et innitier la connection.

La Part2 consiste à l'envoie d'un paquet SDP auquel on y ajoute manullement certaines données.

char sdp_1_data[] = "\x35\x03\x19\x01\x00" 			// L2CAP PATTERN
                           "\x00\x10" 	 			// max attribute byte count
 	                   "\x35\x05\x0a\x00\x00\xff\xff" 	//attribute id list
                           "\x00"; 				//continuation state

Le but de l'envoie de l'envoie de ce paquet et de forcer le retour d'une réponse fragmentée dans laquelle nous allons pouvoir récupérer le timestampsitué dans le continuation state.

Question 1 Pour celà, il va falloir que vous récupéreriez cette valeur de timestamp dans la réponse reçu recv_sdp_2 en Part3. Pour comprendre le code plus facilement, je l'ai instrumenté de façon à afficher les paquets SDP envoyés et reçus. Ainsi il est assez simple de retrouver ces paquets dans la capture Wireshark sur l'interface de Bluetooth utilisée.

Rappel:

typedef struct {
  uint32_t timestamp;
  union {
    uint16_t maxBytesSent;
    uint16_t lastIndexSent;
  } cStateValue;
} sdp_cont_state_t;

alt text

Question 2 Dans la Part4, vous devez retrouver comment acceder à la partie du code vulnérable (expliquée ci-dessus) continuation State exists -> get from cache grâce à la question précédente.

alt text

Question 3 Toujours grâce aux explications précédentes de la vulnérabilité, vous devez trouver comment pointer les données à fuire grâce à la structure continuation state. Ces données seront ensuite ajoutées au paquet sdp_3 que l'on envoie à la machine victime pour provoquer la fuite de données.

alt text

Question 4 Enfin, en Part5 vous devez retrouver l'information que vous aurez réussi à faire fuire dans la seconde réponse SDP recv_sdp_4.

alt text