Blog | Pradeo

L’authentification par SMS : Pas aussi sécurisée qu’elle n’y paraît

Rédigé par Roxane Suau | 17 févr. 2020 08:11:03

La plupart des transactions en ligne font appel à un processus d’authentification en deux étapes. L’envoi d’un SMS contenant un code temporaire (One-Time-password, OTP) constitue généralement la seconde étape de cette procédure. L’utilisation d’un OTP a pour objectif de prévenir les fraudes bancaires en s’assurant que la personne qui effectue la transaction est bien propriétaire de la carte bancaire utilisée. Pour ce faire, un code temporaire est automatiquement envoyé par SMS au numéro de téléphone associé au compte bancaire.

Une fois l’OTP reçu, l’utilisateur le tape dans l’interface où la transaction s’effectue, ce qui lui permet de finaliser son achat. Mais le terminal mobile (tablette ou smartphone) utilisé pour envoyer et recevoir un SMS est-il digne de confiance ? Malheureusement, pas toujours. Ce qui représentait une authentification forte il y a quelques années est maintenant facilement contourné par les applications mobiles.

Notre équipe a identifié deux types d’applications mobiles interceptant les SMS contenant des codes temporaires : les applis légitimes qui utilisent cette technique pour faciliter les transactions et les applis malveillantes qui l’utilisent pour commettre des fraudes bancaires.

 

Des objectifs différents, le même mécanisme

 

Des permissions identiques

Lorsqu’une application demande beaucoup de permissions, elle paraît suspecte. Une interception OTP ne requiert que deux permissions pour s’exécuter, dont l’une (accès internet) est très courante. En conséquence, une application disposant d’un mécanisme d’interception OTP à des fins malveillantes n’affiche rien de suspect à première vue.

  • Permission d’intercepter des SMS : 'android.permission.RECEIVE_SMS'
  • Permission pour envoyer le contenu, via internet ou SMS : 'android.permission.INTERNET' ou 'android.permission.SEND_SMS'

 

Un challenge pour les boutiques d’applis

Les boutiques Google Play et App Store réalisent des vérifications pour garder les malwares hors de leurs plateformes. Cependant, le manque de profondeur de ces tests de sécurité laisse souvent passer des applications malveillantes au travers des mailles du filet. C’est encore plus le cas lorsque la partie la plus visible d’une application, à savoir les permissions qu’elle demande et ses fonctionnalités, ne donne aucune indication reflétant sa vraie nature.

Un mécanisme d’interception OTP peut être aussi bien utilisé par des applications légitimes que par des malwares. Par conséquent, il a la capacité de déjouer les tests de sécurité basiques.

 

Etude de cas

Nom de l'appli : Postbank Finanzassistent (Un clone de l'application German PostBank)

sha1: 32f85c91e5a1437e93128203c27cd8eeb8bbea19

 

La récuperation des sms entrant se fait en deux temps :

1- L'interception des sms se fait via l'implementation d'un android.content.BroadcastReceiver (org.slempo.service.MessageReceiver)

2- L'envoi des data est réalisé via un service (Lorg/slempo/service/MainService) et plus precisément via un java.lang.Runnable (org.slempo.service.a.a$1)

 

1 - Interception via le BROADCAST RECIEVER

Permission requise : 'android.permission.RECEIVE_SMS'

Un Broadcast Receiver (MessageReceiver ) est utilisé pour intercepter les SMS entrants, par l’utilisation de la méthode 'onReceive'.

Nom du Broadcast Receiver :

.class public Lorg/slempo/service/MessageReceiver;
.super Landroid/content/BroadcastReceiver;

Méthode :

.method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V

Description :

(*) Cette méthode fait appel à a(Landroid/content/Intent;)Ljava/util/Map qui se charge de recuperer les sms.


invoke-static {p2}, Lorg/slempo/service/MessageReceiver;->a(Landroid/content/Intent;)Ljava/util/Map;


(*) puis fait appel à la methode b(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V
qui formate l'information (au format JSON).

invoke-static {p1, v1, v0}, Lorg/slempo/service/a/f;->b(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V


(-) methode qui appelle le constructeur <init>(Ljava/lang/String;Lorg/slempo/service/a/a$a;Landroid/content/Context;)V qui sauvegarde l'info dans un field: Lorg/slempo/service/a/a;->a:Ljava/lang/String;

invoke-direct {v0, v1, v2, p0}, Lorg/slempo/service/a/a;-><init>(Ljava/lang/String;Lorg/slempo/service/a/a$a;Landroid/content/Context;)V

 


2 - Envoi des données

Nom du service :

.class public Lorg/slempo/service/MainService;
.super Landroid/app/Service;


Méthode:

.method public onCreate()V

Cette methode instancie le Runnable MainService$1


(*) creation de Lorg/slempo/service/MainService$1

new-instance v1, Lorg/slempo/service/MainService$1;
invoke-direct {v1, p0},
Lorg/slempo/service/MainService$1;-><init>(Lorg/slempo/service/MainService;)V


Nom du Runnable :

.class Lorg/slempo/service/MainService$1
.implements Ljava/lang/Runnable;


Nom de la méthode :

.method public run()V

L'appel suivant est effectué dans la methode run()
(*) invoke-static {v0}, Lorg/slempo/service/a/f;->a(Landroid/content/Context;)V
(-) Lorg/slempo/service/a/a;->a()V qui lance Runnable Lorg/slempo/service/a/a$1


Nom du Runnable :

.class Lorg/slempo/service/a/a$1;

.implements Ljava/lang/Runnable;


Nom de la méthode :

.method public run()V


(*) Envoi via http

Permission: 'android.permission.INTERNET'

invoke-static {v0, v2, v3, v4},
Lorg/slempo/service/a/a;->a(Lorg/slempo/service/a/a;Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)Lorg/apache/http/HttpResponse;


(*) Envoi via sms invisible

Permission: 'android.permission.SEND_SMS'

invoke-static {v0, v2},
Lorg/slempo/service/a/h;->a(Ljava/lang/String;Ljava/lang/String;)Z

 

Découvrez la suite de solutions Pradeo Security: