Bereits eine Weile verfolgen die ESET-Forschenden die Aktivitäten der Winnti-Gruppe, die seit mindestens 2012 aktiv ist. Die Cybergang ist für Supply-Chain-Angriffe auf hochkarätige Ziele in der Software- und Videospieleindustrie verantwortlich. Vor Kurzem wurde eine noch nicht dokumentierte Backdoor gefunden, die es auf Microsoft SQL (MSSQL) abgesehen hat. Durch die Kompromittierung gelingt es Eindringlingen, einen permanenten offenen Zugang in Unternehmen zu schaffen. Die Backdoor weist einige Ähnlichkeiten zur PortReuse-Hintertür auf, die ESET auch erst diesen Monat analysierte. Gleichartig sind beispielsweise die Verwendung desselben Packers oder des VMProtected Launchers. Wir ordnen die neue Backdoor ebenfalls der Winnti-Gruppierung zu.

Anfang dieses Jahres erhielten wir ein Muster, das die Malware-Entwickler skip-2.0 tauften. Die Backdoor zielt auf die MSSQL-Server Versionen 11 und 12 ab und ermöglicht einem Angreifer, unter Verwendung eines „magischen“ Kennworts, eine getarnte Verbindung zu jedem MSSQL-Account herzustellen. Den Logs bleibt diese Verbindung verborgen. Mit Hilfe der Backdoor können Angreifer, Datenbankinhalte heimlich kopieren,  ändern oder löschen.

Das kann beispielsweise dazu genutzt werden, In-Game Währungen zu manipulieren, um daraus Profit zu schlagen. Solche Spielwährungs-Manipulationen gab es bereits früher. Unseres Wissens ist skip-2.0 die erste öffentlich dokumentierte MSSQL-Server-Backdoor. Die MSSQL-Server 11 und 12 sind zwar nicht die aktuellsten Versionen (veröffentlicht im Jahr 2012 bzw. 2014), nach Angaben von Censys jedoch die am häufigsten verwendeten Versionen.

Erst vor Kurzem veröffentlichten wir ein aufklärendes Whitepaper, in dem wir über das Update des Arsenals von Winnti berichteten. Dabei ging es in erster Linie um die bereits erwähnte PortReuse-Backdoor. Diese verwendet eine Payload, wie die in den kompromittierten Videospielen eingebettete, welche von ESET im März 2019 analysiert wurde. Der VMProtected-Launcher, der die PortReuse-Backdoor löscht, wurde auch zum Starten neuerer ShadowPad-Versionen verwendet. In diesem Zusammenhang konnten wir ein neues Tool finden, das die Malware-Entwickler skip-2.0 nennen.

Dieser Artikel konzentriert sich auf die technischen Details und Funktionen der MSSQL-Server-Backdoor sowie auf die Analyse der technischen Ähnlichkeiten von skip-2.0 im Vergleich mit bereits bekannter Winnti-Malware - insbesondere PortReuse-Backdoor und ShadowPad. Im Whitepaper erklären wir auch, warum wir uns für die Bezeichnung Winnti entschieden haben.

VMProtected Launcher

Eigentlich suchten wir nach VMProtected Launchern, dessen Payload meist aus PortReuse oder ShadowPad besteht. Zufällig entdeckten wir dabei die skip-2.0-Malware.

Eingebettete Nutzlast (Payload)

Wie bei den verschlüsselten PortReuse- und ShadowPad-Payloads ist skip-2.0 in das Overlay des VMProtected-Launchers eingebettet, wie in Abbildung 1 dargestellt:

Abbildung 1: Header des VMProtected-Launchers. Die Payload ist in das PE-Overlay eingebettet.

Abbildung 1: Header des VMProtected-Launchers. Die Payload ist in das PE-Overlay eingebettet.

Verschlüsselung

Die Payload-Verschlüsselung ist identisch zu der in anderen VMProtected Launchern verwendeten. Es handelt sich dabei um eine RC5-Verschlüsselugn mit einem Schlüssel, der von der VolumeID und dem String „f@Ukd!rCto R$.“ abgeleitet ist.

Persistenz

Wie im Fall von PortReuse und ShadowPad erlangt der Launcher möglicherweise Persistenz durch das Ausnutzen einer DLL-Hijacking-Sicherheitslücke, wenn unter C:\Windows\System32\TSVIPSrv.DLL installiert. Das führt dazu, dass die DLL beim Systemstart vom standardmäßigen Windows SessionEnv-Dienst geladen wird.

Winntis spezieller Packer

Nach der Entschlüsselung ist die eingebettete Payload gleich der benutzerdefinierte Packer der Winnti Cybergang. Der Shellcode wurde bereits in unserem vorherigen Artikel und Whitepaper dokumentiert. Der Code wird verwendet, um die PortReuse-Backdoor sowie die in den gefährdeten Videospielen eingebettete Payload zu packen.

Packer-Konfiguration

Wie in unserem zurückliegenden Artikel beschrieben, enthält die Packer-Konfiguration den Entschlüsselungsschlüssel der gepackten Binary sowie ihren ursprünglichen Dateinamen, ihre Größe und den Ausführungstyp (.exe oder .dll). Die Packer-Konfiguration der Nutzlast ist in Tabelle 1 dargestellt.

Parent SHA-1 Payload SHA-1 RC4 key Filename Launch type
9aafe81d07b3e5bb282608f0a2a4656eb485b7c9 a2571946ab181657eb825cde07188e8bcd689575 163716559 Inner-Loader.dll 2

Tabelle 1. Payload Packer-Konfiguration

Aus der Packer-Konfiguration geht hervor, dass man den Payload als Inner-Loader bezeichnet. Das ist der Name eines Injectors, der Teil des Winnti Cyber-Arsenals ist und zum Einschleusen der PortReuse-Backdoor in Ports-überwachende Prozesse verwendet wird. Abgesehen vom identischen Namen scheint es sich um eine andere Variante des Inner-Loader-Injectors zu handeln.

Inner-Loader Injector

Diese Variante von Inner-Loader sucht nach einem Prozess namens sqlserv.exe (konventioneller Prozess-Name von MSSQL-Servern). Das geschieht, anstatt nach einem Prozess zu suchen, der einen bestimmten Port überwacht, wie im Fall des Einschleusens der PortReuse-Backdoor.

Wird sqlserv.exe gefunden, schleust Inner-Loader eine Payload in diesen Prozess. Die Nutzlast wurde auch mit dem oben erwähnten Packer gepackt. Die Packer-Konfiguration ist in Tabelle 2 aufgeführt.

Parent SHA-1 Payload SHA-1 RC4 key Filename Launch type
a2571946ab181657eb825cde07188e8bcd689575
60b9428d00be5ce562ff3d888441220290a6dac7 923567961 skip-2.0.dll 2

Tabelle 2. Packer-Konfiguration der im Inner-Loader eingebetteten Payload

Der ursprüngliche Dateiname dieser eingeschleusten Nutzlast lautet skip-2.0.dll.

Skip-2.0

Nachdem der Inner-Load skip-2.0 einschleuste und startete, überprüft skip-2.0 nun, ob es auch tatsächlich im sqlserv.exe-Prozess ausgeführt wird. Dazu ruft es den Handle für sqllang.dll ab. Anschließend sucht und bindet es mehrere Funktionen in diese DLL ein. Abbildung 2 zeigt die Kette der Kompromittierung durch skip-2.0.

Abbildung 2: Entpacken und Einschleusen von skip-2.0

Abbildung 2: Entpacken und Einschleusen von skip-2.0

Einbinden von sqllang.dll

Der Einbindungsprozess von skip-2.0 ähnelt dem von NetAgent. Dabei handelt sich um das PortReuse-Modul, dass verantwortlich für das Installieren des Netzwerk-Hooks ist. Die Hooking-Bibliothek basiert auf dem Open-Source-Disassembler von Distorm, der von mehreren Open-Source-Hooking-Frameworks verwendet wird. Insbesondere wird eine Disassembly-Bibliothek benötigt, um die Größe der einzuhängenden Anweisung korrekt zu bestimmen. In Abbildung 3 erkennt man, dass die von NetAgent und skip-2.0 verwendeten Hook-Prozesse nahezu identisch sind.

Abbildung 3: Hex-Rays Output-Vergleich zwischen dem NetAgent-Hooking (links) und dem Skip-2.0-Hooking (rechts)

Abbildung 3: Hex-Rays Output-Vergleich zwischen dem NetAgent-Hooking (links) und dem Skip-2.0-Hooking (rechts)

Es gibt einen deutlichen Unterschied: Die Hooking-function von skip-2.0 verwendet die Adresse des zu installierenden Hooks als Argument, während diese bei NetAgent fest im Code verankert ist.

Das liegt an der Tatsache, dass skip-2.0 mehrere Funktionen in sqllang.dll einhängen muss, um korrekt zu funktionieren. NetAgent zielt hingegen nur auf eine einzige Funktion ab.

Um jede zu verknüpfende sqllang.dll-Funktion zu lokalisieren, ruft skip-2.0 zuerst die Größe der DLL ab, die einmal in den Speicher geladen wurde (d. H. ihre virtuelle Größe). Dafür analysiert die Malware die PE-Header. Anschließend wird ein in sqllang.dll abzugleichendes Byte-Array, wie in Abbildung 4 dargestellt, initialisiert. Sobald die Adresse des ersten Vorgangs gefunden wurde, das mit dem Byte-Array übereinstimmt, wird der Hook mithilfe der in Abbildung 3 dargestellten Prozedur installiert.

Abbildung 4: Hex-Rays Output des Prozesses, der das Byte-Array für die Übereinstimmung mit sqllang.dll initialisiert

Abbildung 4: Hex-Rays Output des Prozesses, der das Byte-Array für die Übereinstimmung mit sqllang.dll initialisiert

Der Erfolg der Hook-Installation wird dann im Klartext in einer Protokolldatei festgehalten. Diese Logdatei befindet sich unter dem fest vorgegebenen Pfad C:\Windows\Temp\TS_2CE1.tmp – wie in Abbildung 5 dargestellt.

Abbildung 5: Während der Hook-Installation angelegtes Protokoll.

Abbildung 5: Während der Hook-Installation angelegtes Protokoll.

Wird die anvisierte Funktion nicht gefunden, sucht der Hook-Installer nach einer Fallback-Funktion mit einem anderen Set von Bytemustern.

Das Übereinstimmen einer Bytes-Sequenz, um die Adresse einer anvisierten Funktion, anstatt mit eines Offsets zu lokalisieren, erlaubt skip-2.0 eine höhere Resilienz gegenüber MSSQL- und potenziellen sqllang.dll-Updates.

Das magische Passwort

Die skip-2.0-Malware hat es vor allem auf Funktionen abgesehen, die in Verbindung mit Event-Logging und Authentifizierung stehen. Die anvisierten Funktionen umfassen:

  • CPwdPolicyManager::ValidatePwdForLogin
  • CSECAuthenticate::AuthenticateLoginIdentity
  • ReportLoginSuccess
  • IssueLoginSuccessReport
  • FExecuteLogonTriggers
  • XeSqlPkg::sql_statement_completed::Publish
  • XeSqlPkg::sql_batch_completed::Publish
  • SecAuditPkg::audit_event::Publish
  • XeSqlPkg::login::Publish
  • XeSqlPkg::ual_instrument_called::Publish

Die wohl interessanteste Funktion ist die erste (CPwdPolicyManager::ValidatePwdForLogin), welche für die Validierung des von einem Benutzer eingegebenen Passworts verantwortlich ist. Eingeschleuster Code überprüft, ob das Benutzer-Passwort mit dem „magischen“ Passwort übereinstimmt. Ist das der Fall, wird die originale Funktion nicht aufgerufen, stattdessen wird der Wert 0 ausgegeben. Das erlaubt eine Verbindung, obwohl das eigentlich richtige Anmelde-Passwort gar nicht übergeben wurde. Dann setzt die Malware ein global Flag, das von den anderen eingeschleusten Funktionen überprüft wird. Die entsprechende Prozedur ist in Abbildung 6 dargestellt. Wenn das Flag gesetzt ist, bleiben die eingeschleusten Protokollierungsfunktionen im Standby, wie auch die korrespondierenden originalen Funktionen. Ein Logging findet also nicht statt. Wird allerdings ein anderes Passwort, als das „magische“, dem System übergeben, werden alle originalen Funktionen aufgerufen.

Abbildung 6: Hex-Rays Output der Prozedur, die für den Kennwort-Abgleich verantwortlich ist.

Abbildung 6: Hex-Rays Output der Prozedur, die für den Kennwort-Abgleich verantwortlich ist.

Eine ähnliche, auch auf vorprogrammierten Passwörtern beruhende Backdoor-Technik entdeckten die ESET-Forschenden vor gut einem Jahr. Dabei handelte es sich um 21 weitgehend unbekannte oder undokumentierte Linux-Backdoors auf der Grundlage von OpenSSH. Der Unterschied zu skip-2.0 besteht darin, dass die sshd-Executable vor der Ausführung noch modifiziert wurde – skip-2.0 installiert sich direkt in-memory.

Außerdem wird CSECAuthenticate::AuthenticateLoginIdentity von innerhalb des eingeschleusten Codes aufgerufen, aber der Hook wird immer „0“ zurückgeben. Falls das magische Passwort zum Anmelden verwendet wurde, werden die ReportLoginSucess und die IssueLoginSuccessReport Hooks nicht die originalen Funktionen aufrufen. Das Gleiche gilt auch für FEExecuteLogonTriggers. Im selben Szenario sind auch alle Logging-Funktionen wie XeSqlPkg::sql_statement_completed::Publish oder XeSqlPkg::sql_batch_completed::Publish deaktiviert. Mehrere Überwachungsfunktionen wie SecAuditPkg::audit_event::Publish, XeSqlPkg::login::Publish und XeSqlPkg::ual_instrument_called::Publish sind ebenfalls inaktiv.

Diese ganze Reihe von Hooks ermöglicht Angreifern unter Verwendung eines bestimmten Kennworts nicht nur die Persistenz auf MSSQL-Servern, sondern mit Hilfe von deaktivierten Protokoll- und Ereignisanzeigen auch lange unentdeckt zu bleiben.

Wir testeten skip-2.0 gegen mehrere MSSQL-Server Versionen. Es stellte sich heraus, dass man sich mit dem „magischen“ Passwort auf MSSQL-Server der Versionen 11 und 12 erfolgreich anmelden konnte.

Wir erstellten YARA-Regeln, damit man überprüfen kann, ob bestimmte sqllang.dll-Versionen durch skip-2.0 angesprochen werden. Die Regeln haben wir auch in unserem GitHub-Repo hochgeladen.

Verbindung zwischen skip-2.0 und der Winnti Cybergang

Unsere Untersuchungen förderten mehrere Ähnlichkeiten zwischen skip-2.0 und anderen Cybertools der Winnti-Gang zu Tage. Der VMProtected Launcher, der Custom Packer, der Inner-Loader Injector und das Hooking-Framework gehören zum bereits bekannten Toolset der Winnti-Cybergruppierung. Aus diesem Grund vermuten wir, dass auch skip-2.0 zu Winntis Tools gehört.

Fazit

Die Winnti-Gruppe erweiterte ihre Cybertools mit skip-2.0. Die Backdoor weist viele Ähnlichkeiten zu bereits vorhandenen Winnti-Tools auf. Angreifern ermöglicht das Hintertürchen Persistenz auf älteren, aber oft eingesetzten MSSQL-Servern. Angesichts der Tatsache, dass zum Installieren der Hooks Administratorrechte erforderlich sind, muss skip-2.0 aber auf bereits kompromittierten MSSQL-Servern zum Einsatz kommen.

Wir behalten die Winnti Cybergang weiter im Auge und veröffentlichen Neuigkeiten wie immer hier auf welivesecurity.de. Fragen und Anregungen bitte an threatintel@eset.com senden.

Indicators of Compromise (IoCs)

Component SHA-1 ESET detection name
VMP Loader 18E4FEB988CB95D71D81E1964AA6280E22361B9F
4AF89296A15C1EA9068A279E05CC4A41B967C956
Win64/Packed.VMProtect.HX
Inner-Loader injector A2571946AB181657EB825CDE07188E8BCD689575 Win64/Injector.BS
skip-2.0 60B9428D00BE5CE562FF3D888441220290A6DAC7 Win32/Agent.SOK
Known targeted sqllang.dll files (non-exhaustive list) 4396D3C904CD340984D474065959E8DD11915444
BE352631E6A6A9D0B7BBA9B82D910FA5AB40C64E
D4ADBC3F77ADE63B836FC4D9E5915A3479F09BD4
0BBD3321F93F3DCDD2A332D1F0326142B3F4961A
FAE6B48F1D6EDDEC79E62844C444FE3955411EE3
A25B25FFA17E63C6884E28E96B487F58DF4502E7
DE76419331381C390A758E634BF2E165A42D4807
ED08E9B4BA6C4B5A1F26D671AD212AA2FB0874A2
1E1B0D91B37BAEBF77F85D1B7C640B8CC02FE11A
59FB000D36612950FEBC36004F1317F7D000AA0B
661DA36BDD115A1E649F3AAE11AD6F7D6FF2DB63
N/A

MITRE ATT&CK techniques

Tactic ID Name Description
Execution T1035 Service Execution skip-2.0 is started with the SessionEnv service
Persistence T1038 DLL Search Order Hijacking skip-2.0 probably uses a DLL hijacking technique against the SessionEnv service
T1179 Hooking skip-2.0 hooks multiple functions in sqllang.dll service to bypass authentication and maintain stealth
Defense Evasion T1054 Indicator Blocking skip-2.0 blocks event logging
T1045 Software Packing skip.2-0 and Inner-Loader are packed using Winnti's custom packer. Further, the launcher is VMProtected.
Discovery T1057 Process Discovery Inner-Loader lists running processes in order to find the process running MSSQL Server
Impact T1485 Data Destruction skip-2.0 allows unauthorized access to MSSQL databases, allowing data destruction or tampering
T1494 Runtime Data Manipulation skip-2.0 manipulates event logging at runtime
T1492 Stored Data Manipulation skip-2.0 allows unauthorized access to MSSQL databases, allowing manipulation of stored data