Was macht Analyse von Lieferketten-Malware-Artefakten?
Übersicht
Lieferkettenangriffe kompromittieren legitime Softwareverteilungskanäle, um Malware über vertrauenswürdige Update-Mechanismen zu liefern. Bekannte Beispiele sind SolarWinds SUNBURST (2020, über 18.000 Kunden betroffen), 3CX SmoothOperator (2023, ein kaskadierender Lieferkettenangriff, der von Trading Technologies ausging) und zahlreiche npm-/PyPI-Paketvergiftungskampagnen. Die Analyse umfasst den Vergleich trojanisierter Binärdateien mit legitimen Versionen, die Identifizierung von injiziertem Code in Build-Artefakten, die Untersuchung von Code-Signing-Anomalien und die Rückverfolgung der Infektionskette von der ersten Kompromittierung bis zur Payload-Zustellung. Im Jahr 2025 machen Lieferkettenangriffe 30% aller Sicherheitsverletzungen aus, ein Anstieg von 100% gegenüber den Vorjahren.
Wann verwenden
- Bei der Untersuchung von Sicherheitsvorfällen, die eine Analyse von Lieferketten-Malware-Artefakten erfordern
- Beim Erstellen von Erkennungsregeln oder Bedrohungsjagdabfragen für diesen Bereich
- Wenn SOC-Analysten strukturierte Verfahren für diesen Analysetyp benötigen
- Bei der Validierung der Sicherheitsüberwachungsabdeckung für verwandte Angriffstechniken
Voraussetzungen
- Python 3.9+ mit
pefile,ssdeep,hashlib - Binäre Diff-Tools (BinDiff, Diaphora)
- Code-Signing-Verifizierungstools (sigcheck, codesign)
- Software Composition Analysis (SCA)-Tools
- Zugriff auf legitime Softwareversionen für Vergleichszwecke
- Paket-Repository-Überwachung (npm, PyPI, NuGet)
Arbeitsablauf
Schritt 1: Binärvergleichsanalyse
#!/usr/bin/env python3
"""Vergleiche trojanisierte Binärdatei mit legitimer Version."""
import hashlib
import pefile
import sys
import json
def compare_pe_files(legitimate_path, suspect_path):
"""Vergleiche PE-Dateistrukturen zwischen legitimen und verdächtigen Versionen."""
legit_pe = pefile.PE(legitimate_path)
suspect_pe = pefile.PE(suspect_path)
report = {"differences": [], "suspicious_sections": [], "import_changes": []}
# Abschnitte vergleichen
legit_sections = {s.Name.rstrip(b'\x00').decode(): {
"size": s.SizeOfRawData,
"entropy": s.get_entropy(),
"characteristics": s.Characteristics,
} for s in legit_pe.sections}
suspect_sections = {s.Name.rstrip(b'\x00').decode(): {
"size": s.SizeOfRawData,
"entropy": s.get_entropy(),
"characteristics": s.Characteristics,
} for s in suspect_pe.sections}
# Neue oder geänderte Abschnitte finden
for name, props in suspect_sections.items():
if name not in legit_sections:
report["suspicious_sections"].append({
"name": name, "reason": "Neuer Abschnitt, nicht in legitimer Version",
"size": props["size"], "entropy": round(props["entropy"], 2),
})
elif abs(props["size"] - legit_sections[name]["size"]) > 1024:
report["suspicious_sections"].append({
"name": name, "reason": "Abschnittsgröße deutlich geändert",
"legit_size": legit_sections[name]["size"],
"suspect_size": props["size"],
})
# Importe vergleichen
legit_imports = set()
if hasattr(legit_pe, 'DIRECTORY_ENTRY_IMPORT'):
for entry in legit_pe.DIRECTORY_ENTRY_IMPORT:
for imp in entry.imports:
if imp.name:
legit_imports.add(f"{entry.dll.decode()}!{imp.name.decode()}")
suspect_imports = set()
if hasattr(suspect_pe, 'DIRECTORY_ENTRY_IMPORT'):
for entry in suspect_pe.DIRECTORY_ENTRY_IMPORT:
for imp in entry.imports:
if imp.name:
suspect_imports.add(f"{entry.dll.decode()}!{imp.name.decode()}")
new_imports = suspect_imports - legit_imports
if new_imports:
report["import_changes"] = list(new_imports)
# Code-Signing prüfen
report["legit_signed"] = bool(legit_pe.OPTIONAL_HEADER.DATA_DIRECTORY[4].Size)
report["suspect_signed"] = bool(suspect_pe.OPTIONAL_HEADER.DATA_DIRECTORY[4].Size)
return report
def hash_file(filepath):
"""Berechne mehrere Hashes für eine Datei."""
hashes = {}
with open(filepath, 'rb') as f:
data = f.read()
for algo in ['md5', 'sha1', 'sha256']:
h = hashlib.new(algo)
h.update(data)
hashes[algo] = h.hexdigest()
return hashes
if __name__ == "__main__":
if len(sys.argv) < 3:
print(f"Verwendung: {sys.argv[0]} <legitime_binärdatei> <verdächtige_binärdatei>")
sys.exit(1)
report = compare_pe_files(sys.argv[1], sys.argv[2])
print(json.dumps(report, indent=2))
Validierungskriterien
- Trojanisierte Komponenten durch Binärdifferenzierung identifiziert
- Injizierter Code isoliert und separat analysiert
- Code-Signing-Anomalien dokumentiert
- Infektionszeitstrahl aus Build-Artefakten rekonstruiert
- Auswirkungsbereich nachgelagerter Systeme bewertet
- IOCs für Erkennung und Blockierung extrahiert