TRITON : retour sur une attaque des systèmes de contrôle industriel qui a sérieusement perturbé l’exploitation d’une infrastructure critique

Introduction

Mandiant est récemment intervenu sur un incident touchant une infrastructure dite "critique". En cause : un malware conçu pour manipuler les systèmes de sécurité industrielle. Les systèmes ciblés assuraient des fonctions d’arrêt d’urgence aux processus industriels de l’entreprise. Selon nous, l’attaquant a probablement stoppé accidentellement les opérations alors qu’il se préparait à causer des dégâts matériels sur l’infrastructure infiltrée. Il a pour cela utilisé un malware que nous avons baptisé TRITON. Il s’agit d’un framework d’attaque conçu pour interagir avec les contrôleurs du système instrumenté de sécurité (SIS) de Triconex. Bien que nous n’ayons pas pu attribuer l’incident à un attaquant particulier, tout porte à croire qu’un État était à la manœuvre en préparation d’une attaque.

TRITON fait donc partie de ces quelques familles de malwares publiquement identifiés qui ciblent les systèmes de contrôle industriel (ICS). Il succède à Stuxnet, utilisé contre l’appareil nucléaire iranien en 2010, et à Industroyer qui, selon nous, a été déployé par l’équipe Sandworm contre l’Ukraine en 2016. Tout comme ces attaques avant lui, TRITON est parvenu à prévenir le déclenchement des dispositifs de sécurité, causant au passage des dégâts matériels importants.

Famille de malwares

Modules principaux

Description

TRITON

trilog.exe

Principal fichier exécutable qui exploite library.zip

library.zip

Bibliothèque de communications personnalisées pour les interactions avec les contrôleurs Triconex

Tableau 1 : Description du malware TRITON

Résumé de l’incident

L’attaquant a pu accéder à distance à un poste de travail technique du SIS, puis a déployé le framework d’attaque TRITON afin de reprogrammer les contrôleurs SIS. Pendant l’incident, certains contrôleurs SIS ont déclenché leur système de sécurité, avec pour conséquence l’arrêt automatique du processus industriel et l’alerte du responsable des équipements pour investigation. Ainsi, l’enquête a révélé que les contrôleurs SIS avaient déclenché la procédure d’arrêt d’urgence au moment où le code applicatif entre des unités de traitement redondantes avait échoué à un contrôle de validation – avec comme résultat un message de défaillance diagnostique des MP.

Selon nous, l’attaquant a probablement stoppé accidentellement les opérations alors qu’il se préparait à causer des dégâts physiques sur l’infrastructure infiltrée. Explications :

  • La modification du SIS risque d’empêcher son bon fonctionnement, ce qui augmente les chances de défaillance avec des répercussions matérielles.
  • TRITON a servi à modifier la mémoire applicative des contrôleurs SIS dans l’environnement, ce qui aurait pu conduire à un échec du contrôle de validation.
  • La défaillance est survenue pendant l’utilisation de TRITON.
  • Il est peu probable que des conditions externes ou préexistantes aient pu, en vase clos, causer une panne au cours de l’incident.

Auteur

FireEye n’a attribué cette activité à aucun groupe de cybercriminels actuellement sur son radar. Toutefois, selon nous, le commanditaire était probablement une puissance étrangère. Ciblage d’une infrastructure critique, persévérance des pirates, absence de visées financières évidentes et moyens techniques déployés pour la création d’un tel framework : tout porte en effet à croire que le groupe agissait pour le compte d’un État.  Les faits sont là :

Si l’attaquant a ciblé le système SIS, c’est qu’il cherchait certainement à provoquer des dégâts matériels. Les cybermafias motivées par l’appât du gain ne se livrent généralement pas à ce genre d’activité.

L’attaquant a déployé TRITON aussitôt après avoir accédé au système SIS. Il avait donc développé et testé l’outil à l’avance, ce qui requiert un accès à des matériels et logiciels peu répandus. TRITON est également conçu pour communiquer via TriStation, un protocole propriétaire dont le code n’a pas été rendu public. Tout semble donc indiquer que l’attaquant a procédé lui-même à la rétroingénierie de ce protocole.

Les attaques visant à perturber, dégrader voire détruire des infrastructures critiques ne sont pas sans rappeler des actions perpétrées par les services d’États comme la Russie, l’Iran, la Corée du Nord, les États-Unis et Israël. Les intrusions de cette nature n’indiquent pas toujours une volonté immédiate de perturber les systèmes ciblés, mais plutôt la préparation d’un plan de contingence.

Tour d’horizon des systèmes instrumentés de sécurité (SIS) et de contrôle des processus


Figure 1 : Architecture de référence d’un ICS

Les systèmes actuels d’automatisation et de contrôle des processus industriels s’appuient sur une grande variété de fonctions de sécurité et de systèmes de contrôle avancés. Souvent, ces systèmes et fonctions portent le nom de systèmes de contrôle industriel (ICS) ou de technologies opérationnelles (OT).

Un système de contrôle distribué (DCS) permet à des opérateurs humains de suivre et contrôler un processus industriel à distance. Ce système de contrôle informatisé se compose d’ordinateurs, d’applications logicielles et de contrôleurs. Un poste de travail technique désigne un ordinateur utilisé pour la configuration, la maintenance et le diagnostic des applications et autres équipements des systèmes de contrôle.

Quant au SIS, il s’agit d’un système autonome qui surveille l’état du processus sous son contrôle. Si ce processus dépasse un certain seuil de risque, le SIS peut soit tenter de le ramener en-dessous de ce seuil, soit déclencher l’arrêt automatique du processus. En cas d’échec des contrôles SIS et DCS, tout ne dépend plus que des dispositifs en place sur l’installation industrielle. Cet ultime rempart comprend des protections mécaniques des équipements (par ex., disques de rupture), des alarmes physiques, des procédures d’intervention d’urgence et d’autres mécanismes d’atténuation des situations dangereuses.

Les responsables recourent à différentes approches pour interfacer le 'DCS et le SIS. L’approche traditionnelle repose sur les principes de séparation des infrastructures de communication et stratégies de contrôle. Toutefois, depuis au moins 10 ans, l’intégration des DCS et SIS a le vent en poupe. Ses avantages : baisse des coûts, simplicité d’utilisation et échange d’informations directs entre le DCS et le SIS. Selon nous, TRITON apporte la preuve du risque que représente cette intégration, dans la mesure où elle autorise des communications bidirectionnelles entre les hôtes réseau du DCS et du SIS.

Modélisation de la menace et scénarios d’attaque contre les systèmes instrumentés de sécurité (SIS)


Figure 2 : Relation temporelle entre cybersécurité et sûreté

Le cycle de vie des attaques contre les systèmes ICS suit celui d’autres types de cyberattaques, à quelques distinctions près. Premièrement, l’attaquant a pour mission de perturber un processus opérationnel, plutôt que de faire main basse sur des données. Deuxièmement, il doit avoir effectué un travail de repérage préalable et posséder une maîtrise suffisante des processus industriels en question pour parvenir à les manipuler.

La figure 2 représente les relations entre la cybersécurité et les contrôles de sûreté dans un environnement de contrôle des processus. Même en cas d’échec des mesures de cybersécurité, les contrôles de sûreté visent à prévenir des dégâts matériels. Pour accroître l’impact physique de son attaque, un cybercriminel doit donc également déjouer ces dispositifs.

La modélisation de la menace ci-dessous met en lumière certaines des options à la disposition d’un attaquant qui est parvenu à compromettre un SIS.

Option d’attaque 1 : utilisation du SIS pour stopper le processus

  • L’attaquant peut reprogrammer la logique du SIS afin de causer la défaillance apparente et l’arrêt d’un processus qui, en réalité, est en parfait état de marche. En d’autres termes, le pirate va déclencher un faux positif.
  • Répercussions : pertes financières liées à l’interruption du processus et procédure complexe de redémarrage des équipements.

Option d’attaque 2 : reprogrammation du SIS pour autoriser un état de fonctionnement à risque

  • L’attaquant peut reprogrammer la logique du SIS afin d’autoriser le maintien d’un processus dans des conditions risquées.
  • Répercussions : risque accru de situation dangereuse pouvant causer des dégâts matériels (impact sur les équipements, le produit, l’environnement, la sécurité des personnes, etc.) du fait de l’absence de fonctionnalités SIS.

Option d’attaque 3 : reprogrammation du SIS pour autoriser un état de fonctionnement risqué – avec exploitation du DCS pour la génération de cet état ou d’un danger

  • Depuis le système DCS, l’attaquant peut conduire le processus jusqu’à un état de fonctionnement risqué tout en empêchant sa mise à l’arrêt par le SIS.
  • Répercussions : impact sur la sécurité des personnes, l’environnement ou les équipements. L’ampleur des dommages dépendra des contraintes physiques du processus et du modèle conceptuel de l’usine ou la centrale.

Analyse des intentions de l’attaquant

Selon nous, l’attaquant avait pour objectif à terme de développer une force de frappe susceptible de causer des dégâts matériels. Nous basons cette hypothèse sur le fait qu’il était déjà bien infiltré dans le système DCS et qu’il aurait pu tenter de manipuler le processus ou de provoquer l’arrêt des équipements. Au lieu de cela, il a entrepris de compromettre le système SIS. Or, en compromettant à la fois le DCS et le SIS, il aurait pu lancer une attaque beaucoup plus dévastatrice que seuls les systèmes de protection physique et mécanique en place auraient pu arrêter.

Une fois sur le réseau SIS, le pirate a utilisé son framework d’attaque TRITON pour interagir avec les contrôleurs SIS via le protocole TriStation. Il aurait alors pu émettre une commande d’arrêt ou uploader intentionnellement du code défectueux sur le contrôleur SIS pour provoquer une panne. Il n’en a rien été. Il a préféré tenter à plusieurs reprises de développer et de déployer une logique de contrôle opérationnelle sur les contrôleurs SIS de l’environnement cible. Malgré l’échec apparent de ces tentatives dû à l’une des vérifications conditionnelles des scripts de l’attaque, l’attaquant a persévéré. On peut donc supposer qu’il poursuivait un objectif bien spécifique, qui ne se limitait pas au simple arrêt d’un processus.

Autre fait intéressant, nous avons découvert plusieurs signes d’intrusions de longue date dans le système ICS, sans qu’aucune interruption ou perturbation des opérations n’ait été perpétrée. Dans la même veine, on sait désormais que le groupe russe Sandworm a compromis les ICS d’installations dans des pays occidentaux pendant des années, sans pour autant causer la moindre perturbation.

Synthèse des fonctionnalités du malware

L’outil d’attaque TRITON intègre des fonctionnalités de lecture et d’écriture de programmes et de fonctions individuelles, mais aussi de requête de l’état du contrôleur SIS. Or, l’échantillon de trilog.exe n'a exploité qu’une partie de ces fonctionnalités (par ex., l’attaquant n’a pas utilisé toutes les capacités de repérage de TRITON).

Le malware TRITON avait la capacité de communiquer avec les contrôleurs Triconex SIS (envoi de commandes spécifiques : arrêt , lecture de leur mémoire, etc.) et de les reprogrammer à l’aide d’un payload défini par le pirate. Son échantillon analysé par Mandiant ajoutait un programme fourni par l’attaquant à la table d’exécution du contrôleur Triconex. Il ne supprimait aucun des programmes en place afin que le contrôleur continue de fonctionner sans aucune faute ni exception. En cas de panne de ce dernier, TRITON tentait de le remettre en marche. Si toutes les tentatives de redémarrage échouaient dans un laps de temps défini, l’échantillon étudié écrasait le programme malveillant avec des données non valides afin de couvrir ses traces.

Recommandations

Pour se prémunir contre les dangers observés lors de cet incident, les responsables d’installations industrielles doivent envisager les contrôles suivants :

  • Si cela est techniquement faisable, séparez les réseaux de vos systèmes de sûreté de ceux de vos systèmes d’information et de contrôle des processus. N’établissez aucune liaison double entre vos postes de travail techniques capables de programmer les contrôleurs SIS et d’autres réseaux des systèmes d’information et de contrôle des processus DCS.
  • Exploitez les fonctionnalités de vos équipements qui permettent un contrôle physique des capacités de programmation des contrôleurs de sécurité. Il s’agit généralement de commutateurs opérables à l’aide d’une clé physique. Sur les contrôleurs Triconex, la clé ne devrait être en position PROGRAM que lors des opérations de programmation planifiées.
  • Mettez en place des procédures de gestion des changements pour toute modification de position de la clé. Auditez régulièrement la position actuelle de la clé.
  • Préférez une passerelle unidirectionnelle aux connexions réseau bidirectionnelles pour toutes vos applications dépendantes des données fournies par le SIS.
  • Implémentez un contrôle strict des accès et établissez une whitelist des applications sur tous les serveurs et postes de travail reliés au système SIS via des protocoles TCP/IP.
  • Surveillez le trafic réseau du système ICS afin de détecter tous les flux de communication imprévus et autres activités anormales.


Figure 3 : Commutateur à clé Triconex (source)

Annexe : Analyse technique


Figure 4 : Architecture et scénario d’attaque de TRITON

TRITON a été déployé sur un poste de travail du SIS sous Microsoft Windows. Le nom du malware lui permettait de se faire passer pour l’application légitime Triconex Trilog. Partie intégrante de la suite TriStation, cette application a pour but d’examiner les logs. Le malware a infiltré le réseau sous la forme d’un script Python compilé avec Py2EXE, qui reposait sur un fichier ZIP contenant des bibliothèques Python standard, des bibliothèques open source, ainsi que le framework d’attaque de Triconex développé par l’attaquant pour interagir avec les contrôleurs Triconex. Hormis le fichier exécutable, deux fichiers binaires, inject.bin (code de fonction malveillant) et imain.bin (logique de contrôle malveillante), ont été déployés comme payload du contrôleur. Les noms de ces fichiers étaient codés en dur dans le script Python compilé avec Py2EXE.

Trilog.exe a sélectionné une option de la ligne de commande, soit une seule adresse IP de l’équipement Triconex cible. Au lieu d’exploiter les fonctionnalités de la bibliothèque TRITON sous-jacente pour la découverte de l’équipement Triconex, l’attaquant a invoqué une instance de trilog.exe séparément pour chaque contrôleur cible de l’environnement. Une fois invoqué, trilog.exe a vérifié l’état du contrôleur, avant de lire les informations de configuration exposées par le protocole TriStation. Si le contrôleur était en cours d’exécution, trilog.exe codait les deux payloads inject.bin et imain.bin avant de les transférer aux bibliothèques de communication pour leur ajout à la mémoire du programme et à la table d’exécution du contrôleur Triconex.

Une fois les payloads en mémoire, le script démarrait un compte à rebours afin de vérifier régulièrement l’état du contrôleur. En cas d’erreur détectée, la méthode de la bibliothèque de communication SafeAppendProgramMod tentait de rétablir le contrôleur à son état antérieur à l’aide d’une commande du protocole TriStation. En cas d’échec, trilog.exe essayait à son tour d’écrire un petit programme factice en mémoire. Selon nous, il s’agissait d’une technique d’effacement de traces destinée à dissimuler la présence du code de l’attaquant sur le contrôleur Triconex.

En collaboration avec le responsable des équipements infectés, Mandiant a exécuté trilog.exe en laboratoire avec un contrôleur Triconex valide. Nous avons alors découvert que le malware contenait une vérification conditionnelle qui prévenait la persistance du payload dans l’environnement. Après suppression de cette vérification dans le script d’attaque, Mandiant a pu constater que le payload subsistait dans la mémoire du contrôleur. Le contrôleur s’exécutait alors sans interruption.

Pour configurer les contrôleurs, TRITON implémente le protocole TriStation, utilisé par l’application légitime TriStation.

TsHi désigne l’interface créée par les auteurs du malware. Elle permet aux pirates d’implémenter des scripts d’attaque à l’aide du framework TRITON. Elle expose les fonctions de reconnaissance et d’attaque. Ces fonctions acceptent généralement des données binaires de l’utilisateur et gèrent la "signature" de code et les empreintes avant de transférer les données aux bibliothèques subsidiaires pour leur sérialisation et leur transport sur le réseau.

TsBase, autre module développé par l’attaquant, contient les fonctions appelées par TsHi, qui traduisent les intentions du pirate au code de fonction correspondant du protocole TriStation. Pour certaines fonctions, il procède également au remplissage et au packaging des données au bon format.

TsLow désigne un autre module de l’attaquant qui implémente le protocole de la couche de transport UDP de TriStation. La bibliothèque TsBase dépend avant tout de la méthode ts_exec. Cette méthode prend le code de fonction et le code de réponse attendu, puis sérialise le payload des commandes sur UDP. Il compare la réponse du contrôleur à la valeur attendue et renvoie une structure de données indiquant une réussite ou un objet de valeur fausse, synonyme d’échec.

TsLow expose également la méthode de connexion utilisée pour vérifier la connectivité au contrôleur cible. Dans le cas d’une invocation sans cible, il exécute la fonction de découverte d’équipements detect_ip. Celle-ci s’appuie sur un message "ping" sur le protocole TriStation et sur la diffusion IP pour trouver les contrôleurs accessibles via un routeur depuis l’emplacement d’invocation du script.

Indicateurs

Nom de fichier

Hachage

trilog.exe

MD5 : 6c39c3f4a08d3d78f2eb973a94bd7718
SHA-256 :
e8542c07b2af63ee7e72ce5d97d91036c5da56e2b091aa2afe737b224305d230

imain.bin

MD5 : 437f135ba179959a580412e564d3107f
SHA-256 :
08c34c6ac9186b61d9f29a77ef5e618067e0bc9fe85cab1ad25dc6049c376949

inject.bin

MD5 : 0544d425c7555dc4e9d76b571f31f500
SHA-256 :
5fc4b0076eac7aa7815302b0c3158076e3569086c4c6aa2f71cd258238440d14

library.zip

MD5 : 0face841f7b2953e7c29c064d6886523
SHA-256 :
bef59b9a3e00a14956e0cd4a1f3e7524448cbe5d3cc1295d95a15b83a3579c59

TS_cnames.pyc

MD5 : e98f4f3505f05bf90e17554fbc97bba9
SHA-256 :
2c1d3d0a9c6f76726994b88589219cb8d9c39dd9924bc8d2d02bf41d955fe326

TsBase.pyc

MD5 : 288166952f934146be172f6353e9a1f5
SHA-256 :
1a2ab4df156ccd685f795baee7df49f8e701f271d3e5676b507112e30ce03c42

TsHi.pyc

MD5 : 27c69aa39024d21ea109cc9c9d944a04
SHA-256 :
758598370c3b84c6fbb452e3d7119f700f970ed566171e879d3cb41102154272

TsLow.pyc

MD5 : f6b3a73c8c87506acda430671360ce15
SHA-256 :
5c776a33568f4c16fee7140c249c0d2b1e0798a96c7a01bfd2d5684e58c9bb32

sh.pyc

MD5 : 8b675db417cc8b23f4c43f3de5c83438
SHA-256 :
c96ed56bf7ee85a4398cc43a98b4db86d3da311c619f17c8540ae424ca6546e1

Détection

rule TRITON_ICS_FRAMEWORK
{
      meta:
          author = "nicholas.carr @itsreallynick"
          md5 = "0face841f7b2953e7c29c064d6886523"
          description = "Framework TRITON récupéré lors de l’intervention de Mandiant sur l’incident d’un système ICS"
      strings:
          $python_compiled = ".pyc" nocase ascii wide
          $python_module_01 = "__module__" nocase ascii wide
          $python_module_02 = "<module>" nocase ascii wide
          $python_script_01 = "import Ts" nocase ascii wide
          $python_script_02 = "def ts_" nocase ascii wide  

          $py_cnames_01 = "TS_cnames.py" nocase ascii wide
          $py_cnames_02 = "TRICON" nocase ascii wide
          $py_cnames_03 = "TriStation " nocase ascii wide
          $py_cnames_04 = " chassis " nocase ascii wide  

          $py_tslibs_01 = "GetCpStatus" nocase ascii wide
          $py_tslibs_02 = "ts_" ascii wide
          $py_tslibs_03 = " sequence" nocase ascii wide
          $py_tslibs_04 = /import Ts(Hi|Low|Base)[^:alpha:]/ nocase ascii wide
          $py_tslibs_05 = /module\s?version/ nocase ascii wide
          $py_tslibs_06 = "bad " nocase ascii wide
          $py_tslibs_07 = "prog_cnt" nocase ascii wide  

          $py_tsbase_01 = "TsBase.py" nocase ascii wide
          $py_tsbase_02 = ".TsBase(" nocase ascii wide 
         
          $py_tshi_01 = "TsHi.py" nocase ascii wide
          $py_tshi_02 = "keystate" nocase ascii wide
          $py_tshi_03 = "GetProjectInfo" nocase ascii wide
          $py_tshi_04 = "GetProgramTable" nocase ascii wide
          $py_tshi_05 = "SafeAppendProgramMod" nocase ascii wide
          $py_tshi_06 = ".TsHi(" ascii nocase wide  

          $py_tslow_01 = "TsLow.py" nocase ascii wide
          $py_tslow_02 = "print_last_error" ascii nocase wide
          $py_tslow_03 = ".TsLow(" ascii nocase wide
          $py_tslow_04 = "tcm_" ascii wide
          $py_tslow_05 = " TCM found" nocase ascii wide  

          $py_crc_01 = "crc.pyc" nocase ascii wide
          $py_crc_02 = "CRC16_MODBUS" ascii wide
          $py_crc_03 = "Kotov Alaxander" nocase ascii wide
          $py_crc_04 = "CRC_CCITT_XMODEM" ascii wide
          $py_crc_05 = "crc16ret" ascii wide
          $py_crc_06 = "CRC16_CCITT_x1D0F" ascii wide
          $py_crc_07 = /CRC16_CCITT[^_]/ ascii wide  

          $py_sh_01 = "sh.pyc" nocase ascii wide  

          $py_keyword_01 = " FAILURE" ascii wide
          $py_keyword_02 = "symbol table" nocase ascii wide  

          $py_TRIDENT_01 = "inject.bin" ascii nocase wide
          $py_TRIDENT_02 = "imain.bin" ascii nocase wide  

      condition:
          2 of ($python_*) and 7 of ($py_*) and filesize < 3MB
}