Vecteurs d’attaques dans les codes-barres et QRcode

qrcode SQLi
01
avril
2013
  • Google Plus
  • LinkedIn
  • Viadeo
Posted by: Yann C.  /   Category: Vulnérabilités, exploits et PoC   /   Pas de commentaire

Au cours de ma veille quotidienne, je suis tombé sur cet article de Gunter Ollmann qui fait un retour sur les dangers des injections SQL appliquées au monde physique. L’illustration humoristique suivante, qui commence à dater, décrit une des applications possibles des SQLi physiques (bien que ce soit très probablement non fonctionnel) :

SQLi plaque immatriculation

SQLi plaque immatriculation

Ce constat m’a rappelé de vieux souvenirs quant à l’exploitation de vecteurs d’attaques de type XSS/SQLi au travers de représentation non-textuelle. Je me suis donc replongé dans mes archives pour retrouver ces sources documentaires.

Cibles potentielles d’attaques sur codes-barres et QRcode

Les vecteurs d’attaques non-textuels auxquels je fait référence concernent l’exploitation des codes barres en général et plus particulièrement des récents QRcode. L’idée est de générer des codes barres sous une forme valide en vue d’injecter des données arbitraires dans un système. Parmi les systèmes vulnérables à de potentielles attaques sur codes barres on peut citer :

  • Les lecteurs manuels de code barre, généralement utilisé en caisse dans les supermarchés pour enregistrer les produits achetés :
Lecteur portatif de code barre

Lecteur portatif de code barre

  • Les caisses de supermarchés en libre service, très à la mode depuis quelques années et qui assurent un gain de temps en caisse. Beaucoup de supermarchés les ont déployé. A noter que celles-ci embarquent souvent un Windows :
Caisse self-service

Caisse self-service

  • Les bornes informatives des prix, qui commencent à dater. Ces bornes sont souvent présentes dans les grands supermarchés au milieu des rayons. Elles permettent de scanner un code barre afin d’afficher le prix du produit. On peut aisément traduire ce fonctionnement par une simple requête SQL SELECT dans la base des produits du magasin.
Scanner de produit

Scanner de produit

  • Bien évidemment, les caisses de paiement en elles-mêmes disposent d’un lecteur de code barre fixe (pour les codes-barres des produits mais aussi des cartes fidélité) ; ainsi que les systèmes portatif de self-scan que les clients utilisent avec eux dans les magasins :
Self-scan

Self-scan

  • Finalement, je citerai les lecteurs de code-barre et QRcode très présents sur les téléphones portables. Ces lecteurs qui exploitent les caméras des téléphones sont voués à remplacer progressivement tous instruments dédiés dans les grandes surfaces. Ces lecteurs permettent de scanner tous QRcode que l’on peut croiser en abondance dans les nouvelles campagnes publicitaires. Autant dire que ces applications sont elles aussi vulnérables à de potentielles injections.
Lecteur de QRcode sur Smartphone

Lecteur de QRcode sur Smartphone

Exploitation des codes-barres

Plus récemment, et suite au succès des QRcode, de nombreuses applications, API et systèmes logiciels sont apparus pour exploiter ces codes-barres. Comme énoncé précédemment les smartphones en sont quasi-tous équipés ; mais des solutions existent aussi sur PC fixe en exploitant la webcam des ordinateurs.

Parmi ces solutions de reconnaissance de QRcode/codes-barres sur PC on peut citer (par Webcam ou via upload d’image) :

Et bien évidemment, en plus de solution de reconnaissance, il y a celles de génération de code barre dans de nombreux langages :

Type de codes-barres, représentation et caractéristiques

Il existe une multitude de codes-barres. Chacun d’eux à ses spécificités (lecture linéaire en 1 dimension, 2 dimensions…) et prend en compte plus ou moins de caractères.

C’est sur ce dernier point qui concerne le charset exploitable par les codes barres que le type d’injection et sa faisabilité vont se jouer. De plus, la cible envisagée dépend bien évidemment des types de codes-barres supportés.

Il parait logique qu’une injection sera plus complexe voir inefficace si un code-barres n’accepte que des caractères numériques par exemple.

Avant de présenter des vecteurs fonctionnels et de présenter un PoC, voici un état de l’art des types de codes-barres les plus courants et leurs spécifications (source makebarcode.com) :

Barcode Type Character Set Length Checksum Applications
Australia Postal Code

01-australia_postal_example_blue

2D Numbers Only 4 Required Includes error correction
Aztec Code

02-aztec_example_blue

2D Full ASCII; FNC1 and ESI control codes Variable
Min 12
Max 3832
Required Includes error correction; minimum is 15×15 square, largest is 151×151
Codabar

03-codabar_example_blue

1D Numbers: 0-9;
Symbols: – : . $ / +
Start/Stop Characters:
A, B, C, D, E, *, N, or T
Variable None Older code; often used in libraries and blood banks.  See also USD-4, NW-7, 2of7
Code 11

04-code11_example_blue

1D Numbers Only Variable Required Recommend 2nd check digit
Code 128

05-code128_example_blue

1D All ASCII characters
and control codes
Variable Required Widely used; excellent for many applications
Code 39

06-code39_example_blue

1D Uppercase letters A-Z;
Numbers 0-9;
Space – . $ / + %
Variable Optional In very wide use for many types of applications
Extended Code 39

07-ext_code39_example_blue

1D All ASCII characters
and control codes
Variable Optional Uses pairs of  characters to encode non-standard symbols; wasteful of space
Code 93

08-code93_example_blue

1D Uppercase letters A-Z;
Numbers 0-9;
Space – . $ / + %
Variable Optional A more compact cousin of Code 39, not as widely in use
Composite Code

09-composite_example_blue

2D All ASCII characters Variable Required Code comprised of a PDF417 code stacked on top of a Code128; used in UCC/EAN standards
DataMatrix

10-datamatrix_example_blue

2D All ASCII characters Variable Required Includes error correction, up to 2335 ASCII characters
EAN-13

11-ean13_example_blue

1D Numbers Only 13 + check digit
+2 optional
+5 optional
Required Retail product marking  world-wide
EAN-8

12-ean8_example_blue

1D Numbers Only 7 + check digit Required Retail product marking world-wide; compressed code for products with limited label space
EAN Bookland

13-ean13_example_blue

1D Numbers Only 13 + check digit
+2 optional
+5 optional
Required Special use of the EAN-13 symbol to encode ISBN number on books
Industrial 2 of 5

14-industrial_2of5_example_blue

1D Numbers Only Variable None Older type of code
Interleaved 2 of 5

15-itf_example_blue

1D Numbers Only Variable Optional Very compact encodes digits in pairs so total length must be even number of digits
ITF-14

(UPC Ship Container Code)

16-itf-14_example_blue

1D Numbers Only 13 + check digit Required Special use of the Interleaved 2 of 5 code to mark shipping cartons containing UPC encoded products
(see also SCC-14)
LOGMARS

17-code39_example_blue

1D Uppercase letters A-Z;
Numbers 0-9;
Space – . $ / + %
Variable Optional Same as Code 39; this is the US government specification
Maxicode

18-maxicode_example_blue

2D All ASCII characters 93 Required Includes error correction, developed by the United Parcel Service for encoding destination information
MSIMSI Plessey

19-misplessey_example_blue

1D Numbers Only Variable Required Grocery store shelf tags
OPC Optical Industry Assoc.

20-itf_example_blue

1D Numbers Only 9 + check digit Required Special use of Interleaved 2 of 5 for marking retail optical products
PDF-417

20-pdf417_example_blue

2D All ASCII characters Variable Required Includes error correction, up to about 1850 ASCII or 2725 numeric characters
Plessey

21-misplessey_example_blue

1D Numbers Only Variable Required Grocery store shelf tags
Postnet

22-postnet_example_blue

2D* Numbers Only 5 + check digit
+4 optional
+6 optional
Required USA postal code
(ZIP code)
QR Code

23-qrcode_example_blue

2D All ASCII Characters Variable Required Includes error correction, up to about 1520 ASCII or 2509 numeric charcters
SCC-14

(UCC/EAN Ship Cont. Code)

24-UCCEAN-SCC-14_example_blue

1D Numbers Only 13 + checksum Required Special use of Code 128 to mark shipping cartons containing UPC encoded products
(see also ITF-14)
Standard 2 of 5

25-industrial_2of5_example_blue

1D Numbers Only Variable None Also called Industrial 2 of 5.
UCC/EAN-128

26-UCCEAN128_example_blue

1D All ASCII characters
and control codes
Variable Required Special ise of Code 128 which defines data formats for commerce
UCC/EAN Shipping Container Code
(SCC-14)

28-UCCEAN-SCC-14_example_blue

1D Numbers Only 13 +check digit Required Special use of Code 128 to mark shipping cartons containing UPC encoded products
(see also ITF-14)
UPC Shipping Container Code
(ITF-14)

29-itf-14_example_blue

1D Numbers Only 13 + check digit Required Special use of the Interleaved 2 of 5 code to mark shipping cartons containing UPC encoded products
(see also SCC-14)
UPC-A

30-UPCA_example_blue

1D Numbers Only 11 + check digit
+2 optional
+5 optional
Required Retail product marking in USA and Canada
UPC-E

31-UPCE_example_blue

1D Numbers Only 7 + check digit Required Retail product in USA and Canada; compressed code for products with limited label space

Vecteurs d’attaques de codes-barres

Parmi les codes-barres les plus répandus, les plus utilisés et les plus vulnérables, on dénote le code 93, le code 39 et 39 étendu, le code 128 A, B et C, et bien évidemment les QRcode. Ces codes disposent tous de charsets exploitables relativement complets (avec gestion de symboles) et peuvent représenter des chaînes de caractères assez importantes. Il suffit d’encoder un vecteur usuel d’attaque (XSS, SQLi…) sous sa forme de codes-barres pour évaluer la résistance d’un lecteur quelconque.

Code 93

  • XSS standard alert()
code93 XSS

code93 XSS

  • SQLi standard bypass authentification
code93 SQLi

code93 SQLi

Code 39

Version simple avec URLencode

  • XSS standard alert()
code39 XSS

code39 XSS

  • SQLi standard bypass authentification
code39 SQLi

code39 SQLi

Remarques :

  • Le code 39 non-étendu ne permet pas l’utilisation d’un charset de symboles complet. C’est pourquoi les injections au travers de celui-ci peuvent se faire avec un encodage URLencode pour tous les caractères non pris en comptes.

Version étendue

  • XSS standard alert()
code39e XSS

code39e XSS

  • SQLi standard bypass authentification
code39e SQLi

code39e SQLi

Code 128 version A, B ou C

  • XSS standard alert()
code128 XSS

code128 XSS

  • SQLi standard bypass authentification
code128 SQLi

code128 SQLi

QRcode

  • XSS standard alert()
qrcode XSS

qrcode XSS

  • SQLi standard bypass authentification
qrcode SQLi

qrcode SQLi

Génération de vecteurs personnalisés

L’ensemble des codes-barres précédents ont été réalisés à l’aide de l’outil en ligne d’irongeek. Il est possible d’y générer des codes-barres personnalisés, embarquant des vecteurs d’attaques destinés à des audits/pentest de votre choix.

Démonstration et PoC

Il ne m’est pas possible de faire une démonstration d’un de ces vecteurs d’attaques via les équipements de lecture de codes-barres présentés plus haut. Toutefois, pour illustrer le contenu de cet article dans un PoC fonctionnel, nous allons nous intéresser à la solution ScriptCam. Cette solution, sous forme d’un plugin JavaScript JQuery permet d’utiliser la webcam des ordinateurs communs à des fins de lecteur de codes-barres et en particulier de QRcode.

Le fonctionnement de ce plugin JQuery est de charger un module Flash qui peut interagir avec la webcam de l’utilisateur, afin de récupérer des images et d’en extraire des informations par la suite.

ScriptCam permet diverses manipulations de webcams, et l’analyse de codes-barres/QRcode n’est qu’une de ses fonctionnalités. Une page de démonstration de cette analyse est disponible sur le site officiel. Il suffit d’autoriser l’application flash à utiliser la webcam, présenter un QRcode à la caméra puis de cliquer sur « Decode image » pour visualiser le texte du QRcode juste à côté (sur l’exemple suivant, c’est l’url du site dans le QRcode) :

demo scriptcam

demo scriptcam

Imprimons et testons avec un QRcode exploitant un code JavaScript XSS (celui présenté un peu plus haut) :

PoC XSS ScriptCam

PoC XSS ScriptCam

Le vecteur d’attaque XSS renfermé dans le QRcode s’injecte bien dans l’application et est interprété comme tel. Il est alors possible d’imaginer toutes sortes de scénarios d’attaques pour tout équipement qui peut lire des codes barres. Dans l’exemple, seule une alertbox est générée. Mais il aurait été possible de concevoir une injection Javascript qui automatiserait toutes les N secondes la prise d’une photo de la webcam, et de l’envoie de celle-ci sur un serveur annexe par exemple ; ou tout simplement la prise de contrôle du navigateur victime par le framework BeEF.

Conclusion et perspectives

Injection SQL, XSS, corruption de données, plantage de système… Les codes barres ont été sous-estimés comme vecteur d’injection, et le nettoyage (sanitization) des données extraites de ces codes bien trop souvent oublié.

Avec l’avènement du QRcode et son utilisation de plus en plus courante au travers des smartphones, les injections et attaques avec ces mécanismes se répandent de plus en plus. Il est nécessaire de prendre en compte ces considérations.

Les codes-barres et QRcode ne sont qu’un moyen d’appliquer des attaques informatiques sur des équipements physiques. Comme énoncé en introduction, d’autres équipements comme les caméras d’autoroute sont susceptibles d’être corrompues par des vecteurs d’attaques similaires. Bien d’autres applications au monde réel peuvent être exploitées ; à vous de les imaginer !

Edits

J’ai contacté le support de ScriptCam le 3 avril 2013 au matin pour les prévenir de cette petite injection XSS dans leur page de démonstration, bien qu’elle n’engendre pas un réel danger.  En l’espace de 15 minutes ils ont corrigé la vulnérabilité et m’ont fait un feedback de remerciement. Je retire mon chapeau quant à leur réactivité ! Le PoC précédent n’est donc plus exploitable à titre de démonstration sur ScriptCam.

Pour information, la correction portait sur la réinjection dans la page du contenu décodé du QRcode. Ils utilisaient la méthode html() de JQuery, qui interprète le contenu, plutôt que la méthode text().

Avant correction :

<button class='btn btn-small' id='btn1' onclick="$('#decoded').html($.scriptcam.getBarCode());">Decode image</button>

Après correction :

<button class='btn btn-small' id='btn1' onclick="$('#decoded').text($.scriptcam.getBarCode());">Decode image</button>

Sources & ressources

  • Google Plus
  • LinkedIn
  • Viadeo
Yann C.

About the Author : Yann C.

Consultant en sécurité informatique et s’exerçant dans ce domaine depuis le début des années 2000 en autodidacte par passion, plaisir et perspectives, il maintient le portail ASafety pour présenter des articles, des projets personnels, des recherches et développements, ainsi que des « advisory » de vulnérabilités décelées notamment au cours de pentest.