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