Accès aux fichiersRéseauExécution
QuarantineEventsV2 et xattr de quarantaine sous macOS
QuarantineEventsV2 et l'attribut com.apple.quarantine indiquent quoi a été téléchargé, depuis quelle URL, par quelle app et quand, même après suppression.
- Emplacement
- ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2
- Prouve
- Quels fichiers un utilisateur a téléchargés, depuis quelle URL et quelle page d'origine, avec quelle application, et quand
- Horodatages
- Base : temps absolu Mac (UTC) ; xattr : secondes Unix en hexadécimal (UTC)
- Accès
- Utilisateur propriétaire ou root ; accès complet au disque recommandé pour l'outil de collecte
- Rétention
- Jusqu'à suppression ou effacement (aucune purge automatique documentée)
- Collecte
- Aftermath, mac_apt, UAC, Velociraptor
Outils
Comparer tous les outils- Quarantine ParserNavigateur
- mac_aptCLI · open source
- PlasoCLI · open source
- VelociraptorPlateforme · open source
- sqlite3CLI · intégré à macOS
Ce que c'est
Deux artefacts liés enregistrent les téléchargements sous macOS. Lorsqu'une application qui adhère à la mise en quarantaine des fichiers (navigateurs, Mail, Messages, AirDrop, applications sandboxées) écrit un fichier, macOS lui attache l'attribut étendu com.apple.quarantine. Launch Services écrit aussi une ligne dans une base SQLite propre à l'utilisateur, QuarantineEventsV2, qui contient l'URL de téléchargement, la page d'origine et l'agent de téléchargement.
Le xattr voyage avec le fichier ; la ligne de la base reste en place quand le fichier est supprimé. Ensemble, ils constituent le moyen standard de répondre à la question « d'où vient ce fichier ? ».
Où il se trouve
| Artefact | Chemin | Remarques |
|---|---|---|
| Base de quarantaine | ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2 | Une par utilisateur, SQLite, table unique LSQuarantineEvent |
| xattr de quarantaine | com.apple.quarantine sur le fichier lui-même | Stocké dans des fichiers AppleDouble ._ sur les volumes sans xattr natifs |
| Dernier rejet Gatekeeper | /private/var/db/SystemPolicyConfiguration/.LastGKReject sur les macOS actuels ; /private/var/db/.LastGKReject sur les versions plus anciennes | Écrit par syspolicyd ; mac_apt QUARANTINE ne cherche que l'ancien chemin dans une image, donnez-lui directement le fichier actuel |
La base a conservé ce nom et cet emplacement sur les versions modernes de macOS. Elle est lisible par son propriétaire ; collectez-la en root pour tous les utilisateurs, avec l'accès complet au disque accordé à l'outil de collecte.
Ce qu'il prouve
- Qu'une URL a été téléchargée par un agent nommé (
com.apple.Safari,com.google.Chrome,com.apple.mail) à un moment donné. - La page qui a mené au téléchargement (
LSQuarantineOriginURLString) et, pour le courrier, l'expéditeur. - Qu'un fichier précis sur disque provient d'un téléchargement précis (l'UUID du xattr est égal à
LSQuarantineEventIdentifier). - Si un fichier en quarantaine a été ouvert et approuvé via Gatekeeper (drapeau d'approbation utilisateur dans le xattr).
Elle n'enregistre pas le chemin d'enregistrement local ni le nom du fichier, et ne couvre pas les téléchargements effectués avec curl, wget, scp, git ou d'autres outils qui n'adhèrent pas au mécanisme. L'absence d'enregistrement est une preuve faible.
Champs clés
Table LSQuarantineEvent :
| Colonne | Signification |
|---|---|
LSQuarantineEventIdentifier | UUID (clé primaire), correspond au dernier champ du xattr |
LSQuarantineTimeStamp | Heure de l'événement, temps absolu Mac (REAL) |
LSQuarantineAgentBundleIdentifier | Bundle ID de l'application de téléchargement |
LSQuarantineAgentName | Nom affiché de l'agent |
LSQuarantineDataURLString | URL des données téléchargées |
LSQuarantineOriginURLString | Page référente ou d'origine |
LSQuarantineOriginTitle | Titre de l'origine, lorsqu'il est enregistré |
LSQuarantineSenderName, LSQuarantineSenderAddress | Expéditeur, renseigné par des agents comme Mail |
LSQuarantineTypeNumber | Type de quarantaine Launch Services (téléchargement web, pièce jointe, etc.) |
LSQuarantineOriginAlias | Blob d'alias, en général vide |
Valeur du xattr flags;timestamp;agent;UUID, par exemple 0083;66f7c2a1;Safari;<UUID>. Les bits de drapeaux documentés par les chercheurs (Apple ne les documente pas publiquement) incluent 0x0001 téléchargement, 0x0002 sandbox, 0x0004 quarantaine stricte et 0x0040 approuvé par l'utilisateur.
Horodatages
LSQuarantineTimeStamp: temps absolu Mac, secondes depuis le 2001-01-01 00:00:00 UTC. Ajoutez978307200pour obtenir un temps Unix.- Horodatage du xattr : secondes Unix en hexadécimal, UTC.
SELECT datetime(LSQuarantineTimeStamp + 978307200, 'unixepoch') AS event_utc,
LSQuarantineAgentBundleIdentifier, LSQuarantineDataURLString,
LSQuarantineOriginURLString, LSQuarantineEventIdentifier
FROM LSQuarantineEvent ORDER BY LSQuarantineTimeStamp;
xattr -p com.apple.quarantine ./sample.dmg
date -u -r $((16#66f7c2a1))
Rétention
Aucune purge automatique n'est documentée : les enregistrements s'accumulent en général pendant toute la vie du profil utilisateur, ce qui les rend précieux une fois le fichier téléchargé supprimé. Les utilisateurs, les outils de nettoyage et les attaquants peuvent supprimer des lignes avec sqlite3, ou supprimer le fichier entier. Le xattr est perdu lorsqu'il est retiré avec xattr -d/xattr -c, lorsqu'un fichier est copié vers un système de fichiers ou un service qui abandonne les attributs étendus, ou lorsqu'une archive est extraite par un outil qui ne propage pas la quarantaine.
Collecte
# Every user's database (root, collector with Full Disk Access)
for u in /Users/*; do
f="$u/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2"
[ -f "$f" ] || continue
d="./case/qe_$(basename "$u")"
mkdir -p "$d" && sudo cp -p "$f"* "$d/"
done
# Preserve xattrs when copying suspect files
ditto --extattr ./suspect.pkg ./case/files/
- Aftermath collecte la base LSQuarantine.
- UAC :
files/system/quarantine_events.yaml(base par utilisateur). - Velociraptor :
MacOS.System.QuarantineEvents. - Analyse à froid : copiez depuis le volume Data monté ; calculez d'abord les empreintes, travaillez sur des copies.
Analyse
- sqlite3 avec la requête ci-dessus.
- Plugin
QUARANTINEde mac_apt (base et.LastGKReject) :python mac_apt.py -o out MOUNTED /Volumes/evidence QUARANTINE. - Plugin
ls_quarantinede Plaso :log2timeline.py --parsers 'sqlite/ls_quarantine' --storage-file qe.plaso ./case. - Relier un fichier à son enregistrement :
SELECT * FROM LSQuarantineEvent
WHERE LSQuarantineEventIdentifier = '<UUID from xattr>';
Quarantine Parser lit dans le navigateur QuarantineEventsV2 avec son -wal (et récupère les lignes supprimées), les listings de l'xattr com.apple.quarantine et .LastGKReject, et relie chaque fichier sur disque à son enregistrement de téléchargement ; rien n'est envoyé.
Conseils d'investigation
- Un binaire suspect sans xattr de quarantaine mais avec un enregistrement correspondant dans la base suggère que l'attribut a été retiré délibérément.
- Une seconde charge récupérée avec
curlne laisse aucune trace de quarantaine ; poursuivez vers l'historique du shell, les Unified Logs et FSEvents. - Rapprochez les URL de données de l'historique Safari ou de Chrome/Firefox, et de
kMDItemWhereFromsdans le magasin Spotlight. - Le passage du drapeau de
0083à00c3active0x0040(approuvé par l'utilisateur) : l'élément a été ouvert et autorisé. Traitez la signification des drapeaux comme un élément de preuve complémentaire. - Des trous dans une chronologie par ailleurs dense, ou une base bien plus petite que ne le laisserait penser l'historique du navigateur, peuvent indiquer un effacement manuel ; vérifiez le WAL et les pages libres.
- Confondre les époques du xattr (Unix, hexadécimal) et de la base (temps absolu Mac) produit des erreurs de 31 ans.
- Pour les décisions Gatekeeper qui suivent le téléchargement, voir Gatekeeper et XProtect et le guide quarantaine et Gatekeeper.
Voir aussi
Artefacts liés
Guides détaillés
Glossaire
- Quarantine Attribute (com.apple.quarantine)Anglais
- GatekeeperAnglais
- Mac Absolute TimeAnglais