Il faut d'abord que je commente le mot bricker
dans le titre
de cette entrée. C'est un anglicisme (l'anglais
est to brick, c'est-à-dire que le nom
commun brick a été sauvagement verbé), mais je ne
crois pas qu'il existe de mot français : on peut écrire bricker
en important le mot anglais, ou bien briquer
en reproduisant la
même construction qu'en anglais (ce verbe existe déjà en français avec
un sens différent — frotter pour faire briller — mais je ne trouve pas
que la confusion soit problématique, et à la limite ça peut marcher de
façon humoristique). Quelqu'un m'a proposé pétrifier
, ce qui
est effectivement astucieux pour rendre le sens de ce dont je veux
parler ici, et du coup je vais l'utiliser dans la suite.
De quoi s'agit-il ? Je définirais ce mot de la manière suivante : rentre, généralement par accident, un appareil électronique inutilisable (aussi utile qu'une brique, donc), en abîmant non pas le matériel lui-même, mais le logiciel qui sert à démarrer.
Expliquons un peu, pour ceux qui ont besoin de plus de précisions. De nos jours, énormément de gadgets électroniques (en gros, tout ce qui est plus complexe qu'une télécommande) sont, en fait, de petits ordinateurs dédiés, dits aussi « embarqué ». Autrefois, un téléviseur (par exemple), c'était de l'électronique spécialisée, maintenant c'est un ordinateur embarqué qui sait décoder la TNT et parle à l'écran LCD ; il en va de même, par exemple, des voitures (et d'ailleurs ça me fait très peur vu le niveau général catastrophique de la sécurité informatique et vu que les constructeurs n'auront aucune obligation à maintenir ad vitam æternam le logiciel). Énormément d'entre ces gadgets, soit dit en passant, tournent sous Linux (tous les téléphones ou tablettes Android, bien sûr, mais aussi les MachinBox qui servent de modem-routeur ADSL ou fibre, et je soupçonne, beaucoup de télévisions, de magnétoscopes, etc.), vu que Linux est très commode pour avoir rapidement un système standardisé sur un matériel à peu près quelconque. Je pense que Madame Michu serait très étonnée de savoir combien de systèmes Linux elle a chez elle.
Certains appareils (montres, frigos, fours, machines à laver) sont encore dans une phase où coexistent plusieurs versions sur le marché : purement électroniques, les véritables ordinateurs embarqués, et quelque chose d'intermédiaire comme un microcontrôleur. Mais avec l'Internet of Things (également appelé, la catastrophe de sécurité informatique qui va nous fondre dessus), les frigos, fours et machines à laver seront aussi de plus en plus souvent de véritables ordinateurs, capables de parler au réseau (et de se faire attaquer par lui). Ironiquement, maintenant, même les périphérique des ordinateurs sont souvent des ordinateurs eux-mêmes : les disques durs modernes, par exemple, ont un véritable ordinateur à l'intérieur (typiquement un processeur ARM), pour pouvoir mener toutes les choses complexes qu'un disque dur est censé faire (positionner les tête, contrôler les sommes de contrôle sur les données lues, analyser sa propre santé et la rapporter à l'ordinateur hôte, etc.).
L'avantage des ordinateurs par rapport à l'électronique pure
(par électronique
, je veux dire qu'il n'y a pas de puce
généraliste, microprocesseur ou microcontrôleur, même si évidemment
les frontières ne sont pas parfaitement bien définies), c'est qu'ils
permettent de faire des choses beaucoup plus complexes de façon plus
simple, et globalement ils sont plus flexibles. L'inconvénient, le
pendant du généralisme, c'est qu'un microprocesseur seul ne sait rien
faire : il lui faut un logiciel, un programme, également appelé du
« code », pour faire quoi que ce soit, et notamment quoi que ce soit
d'utile. Dans le cadre d'un ordinateur embarqué ou de périphériques
d'un ordinateur, ce logiciel s'appelle
souvent firmware (intermédiaire
entre hardware, le matériel,
et software, le logiciel sous-entendu de plus
haut niveau).
On peut imaginer que ce firmware soit fixé une fois pour toutes :
stocké en ROM (mémoire en
lecture seule), gravé dans le marbre pour toute la vie de l'appareil.
On se rapproche de l'électronique (une fois que l'électronique est
câblée, plus moyen de changer). Mais cela signifie qu'en cas de
problème, il sera impossible de corriger le bug ou le trou de
sécurité. Du coup, ces appareils prévoient souvent un moyen de mettre
à jour leur firmware : on utilise souvent le terme de flasher
le firmware, parce qu'il est typiquement contenu dans une mémoire
persistante appelée mémoire flash. Et c'est là que les ennuis
commencent : parce que la mise à jour du firmware est à la fois une
réponse à toutes sortes de problèmes (comme des trous de sécurité) et
la cause de toutes sortes de problèmes (comme des trous de sécurité !
car si un attaquant modifie le firmware, il prend durablement contrôle
de l'appareil, c'est plus grave que si le firmware n'était pas
modifiable).
La modification du firmware est elle-même une opération qui nécessite l'éxcution de code, ce faisant partie du firmware, et c'est là qu'on comprend que les ennuis commencent vraiment. Parce que si l'opération échoue pour une raison ou une autre (bug, fausse manip', coupure de courant au mauvais moment) et qu'on se retrouve avec du firmware qui ne marche plus, on n'a plus de moyen de remettre en état le firmware : on se retrouve avec une brique : l'appareil ne marche plus, faute de firmware, et il n'y a pas de moyen, ou en tout cas pas de moyen simple, de remettre le firmware en état.
On peut bien sûr imaginer toutes sortes de façons de régler quand même le problème, et de rendre une machine impossible à pétrifier. Discutons un peu ces différentes approches.
La façon la plus évidente, comme je l'ai dit, c'est que le firmware ne soit pas du tout modifiable. Sur certains appareils (mais ce n'est pas courant), il faut actionner un interrupteur mécanique, ou décaler un jumper, ou quelque chose comme ça, avant de pouvoir flasher le firmware (si on ne le fait pas, la mémoire n'est pas modifiable) : ceci évite au moins les modifications malencontreuses dues à un bug ou une attaque, mais ça n'empêche pas qu'on puisse pétrifier la machine en cas de problème lors d'une mise à jour légitime (l'interrupteur étant donc actionné). Une autre solution consiste à avoir deux versions du firmware sur l'appareil, l'une dans une mémoire flash qu'on peut mettre à jour, l'autre dans une ROM inaltérable (en fait, probablement, une mémoire flash dont les pattes servant à réécrire le contenu n'ont pas été câblées) : un petit interrupteur permet de choisir — au niveau purement électronique — la version utilisée, on choisira normalement la première, mais en cas de problème on pourra démarrer sur la seconde, qui est capable de reflasher la première. Ceci permet bien d'avoir un appareil « impétrifiable » dont le firmware peut cependant être mis à jour. Astucieux. Je crois que ma carte mère a quelque chose du genre (un firmware/BIOS alternatif, non modifiable, du moins j'espère, accessible en appuyant sur un bouton, et qui est simplement capable d'aller lire un fichier sur une clé USB qui doit être branchée sur un port précis, et de reflasher le firmware/BIOS principal avec son contenu), mais les explications du manuel ne sont pas un modèle de clarté donc je ne suis pas sûr.
On peut imaginer d'autres moyens de rendre un appareil
impétrifiable. Par exemple, si le firmware est flashable depuis
un autre ordinateur, on pourra ranimer la brique tant qu'on
dispose d'un ordinateur fonctionnel. Une idée serait d'avoir un
firmware contenu dans une simple clé USB : pour le
flasher, il suffirait de mettre un fichier différent sur cette
clé USB. Malheureusement, la simple opération de lire
une clé USB nécessite elle-même du code, donc un
firmware, et on a un problème de bootstrap si on
veut mettre le firmware sur clé USB
(bootstrap
fait référence à un épisode où
le baron de
Münchhausen se sort de l'eau en tirant sur les languettes de ses
bottes). Mais on peut contourner ce problème de différentes façons.
Par exemple, avoir un firmware zéro qui sait simplement lire un
firmware sur clé USB, puis l'exécuter et décider que ce
firmware zéro sera gravé en ROM donc impossible à
modifier (c'est une solution raisonnable, et elle se rapproche de ce
que je raconte ci-dessus à propos de ma carte mère). À défaut de
clé USB, le firmware peut être contenu dans une puce
détachable et on peut vendre un gadget (USB par exemple)
permettant d'en modifier le contenu depuis un autre ordinateur. Ou
encore, il peut y avoir un tel gadget intégré dans l'appareil
lui-même : si on branche une connexion USB et qu'on
allume l'appareil d'une certaine manière (peut-être en appuyant sur un
bouton), on pourra flasher le firmware depuis un autre ordinateur, par
pure électronique.
Les petits systèmes embarqués que j'utilise comme routeurs chez moi et chez mes parents, des DreamPlugs (ce sont des ordinateurs ARM), ont une petite mémoire flash (NOR) de 2Mo qui suffit à stocker un code de démarrage (bootloader, en l'occurrence U-Boot) capable de charger autre chose par Ethernet, USB ou eSATA, en ce qui me concerne un noyau Linux. On peut reflasher la mémoire NOR en passant par Linux ou depuis le bootloader U-Boot lui-même ; mais si l'opération échoue pour une raison ou une autre et que le DreamPlug est pétrifié ? Alors il faut utiliser une autre approche, qui consiste à prendre le contrôle du processeur et de la mémoire du DreamPlug depuis un autre ordinateur, en passant par une interface JTAG côté DreamPlug (et reliée de l'autre côté à un petit boîtier lui-même relié par USB à l'ordinateur qui contrôle) : de cette manière, on peut utiliser le programme OpenOCD pour mettre un U-Boot frais quelque part dans la mémoire du DreamPlug, démarrer dessus, et s'en servir pour reflasher la mémoire NOR. En théorie, c'est très bien. En pratique, il y a quantité de problèmes : la connexion JTAG n'est pas très stable, parfois elle ne marche pas du tout, parfois il faut réessayer plusieurs fois avant qu'elle marche ; en plus, OpenOCD version ≥0.8.0 ne fonctionne plus avec mon boîtier de contrôle JTAG, bref, ce n'est pas la joie. Mais au moins sur le principe, mes DreamPlugs sont « impétrifiables ». On ne peut pas en dire autant de la plupart des téléphones mobiles.
Beaucoup de fabricants de gadgets électroniques ont essayé
l'approche suivante, qui ne sert pas seulement à éviter que le gadget
soit pétrifié, mais aussi à ce que le le fabricant garde un contrôle
sur le code qui tourne dessus : avant que le firmware accepte de
flasher un nouveau firmware, il vérifie que celui-ci est acceptable,
généralement au sens où il a été signé (par une signature
électronique) par le fabricant. Malheureusement, cette approche est
condamnée à l'échec pour toutes sortes de raisons, elle n'empêche pas
la pétrification et elle pose toutes sortes de problèmes, ce qui
n'empêche pas les fabricants de l'aimer. Une raison pour laquelle
cette approche n'empêche pas la pétrification, c'est qu'il n'y a rien
de magique dans le firmware de démarrage : s'il est capable de flasher
la mémoire persistante, un autre bout de code en est aussi capable,
donc dès que l'appareil présente un trou de sécurité quelque part
(i.e., toujours), l'attaquant risque de pouvoir s'en servir
pour reflasher le firmware, et l'approche choisie rend alors quasiment
impossible de remettre les choses en état. (The
major difference between a thing that might go wrong and a thing that
cannot possibly go wrong is that when a thing that cannot possibly go
wrong goes wrong it usually turns out to be impossible to get at or
repair.
— Douglas Adams, Mostly
Harmless) Une autre raison qui fait que l'approche ne marche
pas, c'est que la crypto est souvent mauvaise, par exemple au lieu
d'utiliser une signature à clé publique, ce qui est possiblement lourd
sur un appareil embarqué, on va parfois utiliser
un MAC,
dont la clé (symétrique) est alors forcément contenue dans le
firmware, et qui va donc forcément fuiter. Encore une autre raison
est qu'il y a un intervalle de temps entre le moment où le firmware
vérifie la signature et le moment où il se reflashe, et il est parfois
possible d'exploiter astucieusement cet intervalle pour changer le
contenu sous ses pieds (on lui fait croire que la signature est bonne
en vérifiant un « bon » nouveau firmware, mais au moment où il flashe
la mémoire, c'est autre chose qui se présente). Toutes ces attaques
sont menées soit par des attaquants malicieux qui veulent prendre le
contrôle de l'appareil à l'insu de son propriétaire, soit par les
propriétaires eux-mêmes qui veulent prendre le contrôle de leur propre
gadget dont le fabricant essaie de limiter l'usage. Dans les deux
cas, la pétrification est un résultat accidentel, mais qui se produit
néanmoins dans une certaine proportion des cas.
Pourquoi les fabricants ont-ils si souvent recours à la méthode « vérification du firmware avant de le flasher » (dont je viens de parler) si elle ne marche pas vraiment ? Parce que cette méthode leur garantit — dans la mesure où elle marche, tant qu'elle marche — un certain contrôle sur l'appareil, à l'encontre de son propriétaire/utilisateur. On pourra l'empêcher d'utiliser cet appareil pour autre chose que ce pour quoi il a été prévu, et ce peut être le départ d'une chaîne de sécurité qui interdit certaines choses à l'utilisateur (qui, même s'il est censé être propriétaire de l'appareil, ne l'est alors jamais vraiment), par exemple de copier certaines données dans un sens ou dans l'autre. A contrario, certains des dispositifs qui empêchent la pétrification empêchent le fabricant de se réserver ce contrôle sur l'appareil.
Toujours est-il qu'il existe bien des moyens pour rendre un appareil impétrifiable. Je trouve que cela devrait être une obligation du fabricant de s'assurer qu'un de ces moyens existe (par exemple : si l'appareil est pétrifié, le fabricant aurait l'obligation légale de le rembourser au prix du neuf — une telle mesure augmenterait énormément la motivation à mettre en place des moyens pour éviter cet écueil). Un autre problème est qu'il n'est pas toujours évident de savoir ce qu'il en est, avant d'acheter l'appareil, ou même une fois qu'on l'a. Est-ce que mon téléphone Nexus 5 est pétrifiable, par exemple ? Je ne sais pas vraiment, je pense que oui, mais je n'ai pas franchement envie d'essayer pour vérifier ma sécurité de ce point de vue-là.
Je raconte tout ça parce que j'ai récemment mis à jour le noyau sur mes routeurs DreamPlugs (j'étais coincé depuis une éternité sur la branche 3.2.x du noyau Linux, avec toute une série de patchs, et pour la quitter j'ai dû mettre à jour U-Boot pour pouvoir passer au noyau un device tree, et avant de faire tout ça j'ai dû réapprendre la manière de réparer les choses en cas de pétrification accidentelle — dont je ne pouvais pas négliger les risques, même si au final tout s'est bien passé ; ceux qui veulent en savoir plus peuvent consulter cette page, récemment mise à jour, où je raconte les détails). J'envisage d'acheter d'autres gadgets pour remplacer ces DreamPlugs, par exemple ce truc-là, et une des choses que je cherche systématiquement à savoir c'est qu'elle garantie d'impétrificabilité(?) j'aurai (sur le produit précis que je viens de mentionner, il semble que ce soit bon, mais c'est rarement parfaitement clair).