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.
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.
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: