A Tale of Practical Keylogger Forensics

On a recent engagement, an interesting hardware side quest popped up. A client had found a keylogger and, naturally, we wanted to know what the adversary had seen and if we could gather any useful traces towards the perpetrator.

Since our analysis included some twists, we decided to document parts of our process to perform a forensic analysis on a keylogger. We hope to shed some light on the forensic possibilities and encourage others to expirement with similar hardware.

Passive Reconnaissance

Hardware keyloggers come in various shapes and sizes. The one we got, that was yanked from a computer in a public area, was no larger than a fingernail. To some surprise it was 3D printed, as the layers were visible.

Of course, our first goal was be to identify the device in front of us. What is it capable of? Is there any sort of documentation we can leverage? And although it looks just like any other keylogger, we started with some passive reconnaissance to confirm our first assumption.

To our amusement, finding the exact model and documentation was just a single image search away. Simply taking a picture and using reverse image search, we immediately identified the „KeyGrabber Air“.

At this point we had a rough idea of what this device could do. Most notably, it could be used for:

  • Capturing and storing keystrokes (no injection)
  • Open a WLAN to host a web interface that shows settings and keystrokes
  • Connect to a WLAN to send keystrokes via FTP or SMTP

Active Reconnaissance

After powering on the device via the USB port, we noticed a new WLAN appear with the SSID „AP001“. This matched the documentation we found earlier. However, the network required a password and it was neither a common password such as „password“ or any other default credential we could find in the documentation. We also could not identity any sort of key combination (such as K+B+S) that would grant us administrative access, as it has been the case with other keyloggers.

Hence, we asked for permission to apply some more intrusive techniques. Once we received a thumbs up from the client, we opened the case and got to the circuitry.

As the figure above shows, there are only two core components on the board. On the bottom left you can see an ATMEL AT91SAM7S32 MU and on the right an ESP8285. The data lines from the USB ports are directly connected to the AT91SAM7S32, which indicates that this chip may be responsible for parsing the differential signals and extracting the key values. Of more interest to us is the ESP8285 which is a common chip for wireless applications and also connects to a small antenna on the PCB.

Unfortunately, neither the connectors (golden circles) in the middle, nor a direct connection with a Sensepeek PCBite to the ESP gave us access to the chip. Our assumption is that the passive components and connections on the board interfered with our attempts to communicate with the ESP8285 directly.

Our goal was to hook up to UART, the debug interface of the chip, to dump its memory. Thus, we once again asked for permission to proceed and were given the green light to desolder the ESP. Word of caution: make sure to check the datasheet of the components you want to desolder for allowed temperatures in advance to avoid the risk of damaging anything. A small nozzle and a rather low airflow prevents the passive components on the side from getting blown away. I can also recommend preheating the board, to heat large ground pads.

Since the ESP is tiny and needs some passive components to function, we decided that it would be easiest to just install it on a developer board for easy access. Thus, we got ourselves a cheap dev-kit like this:

This set exposes the UART interface (board on the right) and includes a UART to USB converter (left).

We desoldered the original chip, replaced it with the one we got from the keylogger and connected the board to a computer. Now, we could use esptool to finally dump the memory of the ESP. Note that the ESP8285 has an internal flash memory. Other chips may use an external flash chip, so you may be able to access the storage directly and don’t need to deal with the ESP/esptool.

With esptool we need the Baudrate (115200 is the default for this chip), the path to the USB device, the command (read_flash), a start address (0), the amount of bytes to read (in case of the ESP8285 flash that is 1 Megabyte) and a filename to store the contents.

$ esptool -b 115200 --port /dev/ttyUSB0 read_flash 0x0 0x100000 flash_1M_esp.bin
espool.py v4.7.0
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... Unsupported detection protocol, switching and trying again
Connecting...
Detecting chip type... ESP8266
Chip is ESP8285H16
Features: WiFi, Embedded Flash
Crystal is 26MHz
Uploading stub...
Running stub...
Stub running...
315392 (30%)

When esptool finished without errors, we had the entire flash content in a file.

Analysing the dump

As with any other binary file, we can save ourselves alot of trouble by just extracting all readable strings and start analysing them, before doing any reversing. However, the strings output on the binary showed tons of:

[N][+N][+N][+N]´[+N]´[+N][+N]´[+N][+N][+N][+N][+N]dckjhe^[+N]´x[+N]´[+N]´c[+N]´[+N]´[+N][+N][+N]a,[+N][F5]x[+N][+N][+N][+N]a,bsc[+N]a,[+N][+N][+N][+N]a,a,[+N][+N][+N][+N]a,[+N]c´[+N][+N][+N][+N]e^dc[+N][+N][+N][+N]´[+N][+N][+N][+N][+N][+N][+N][+N][+N][+N][+N]xx´[+N][+N][+N]bs[+N]a,a,[+N]c[+N][+N][+N]a,[+N][+N]c[+N][+N]a,[+N]bsa,[+N]´[+N]´[+N][+N]´[+N]´´[+N][+N][+N][+N][+N][+N]a,[+N][+N][+N]bsa,a,[+N]a,[+N][+N][+N][+N][+N]a,[+N]a,[+N][+N][+N]´[+N][+N][+N][+N]´[+N]´[+N]´[+N][+N]bsa,[+N]´[+N][+N][+N][+N]´[+N][+N][+N][+N][+N][+N]´[+N]a,[+N][+N][+N][+N]´[+N][+N][+N][+N][+N][+N]a,[+N][+N][+N][+N][+N][+N][+N][+N][+N]a,[+N][+N]´[+N][+N][+N][+N][+N][+N][+N][+N][+N][+N][+N][+N][+N][+N][+N][+N][+N][+N]
[+N]x[PUp][+N][+N][+N][+N]bsa,bs[+N][+N]a,bs[+N]c[+N][+N]´[+N][+N]´[+N][+N][+N]a,[+N]ca,

At first we were optimistic. There were strings like [LCtrl][Rgh]cbscbs[+N][LCtrl] which seemed like valid keystrokes. But the longer we studied the output, we could only make less and less sense of it. We thought, maybe the contents were encoded or maybe the memory got corrupted along the way.

The initial feeling of success was followed by the depressing realisation that the output was useless. However, motivation quickly came back when we found the following intact and readable configuration in the strings output:

ap_name
AP001
ap_password
*******[redacted]

Unfortunately, it did not appear as if the adversary had specified any FTP or SMTP credentials. This could have been a great finding and a hint towards the identity of the perpetrator. However, equipped with the WiFi password, we would finally be able to access the keylogger dashboard.

Beware of rabbit holes. For quite some time we believed that the ESP firmware may hold some value and potentially we could decode the magic log strings when we just reversed the application. We would just have to convert the binary back to an ELF and then apply Ghidra. In hindsight, that step was completely unnecessary and although we learned quite a bit about ESPs and ELFs, it was not nearly as efficient as what we did next.

Put everything back together

We desoldered the ESP from the dev-board and put it back on the keylogger. At last, we successfully connected to the WLAN of the keylogger. Following another quick read of the documentation, we navigated to http://192.168.5.1 and finally:

This was not what we anticipated. Either we had corrupted the filesystem or something weird was going on. Every page of logged keystrokes contained nothing but nonsense. However, the configuration we extracted was intact. And indeed, the dashboard displays all data as we would expect.

Even the keyboard language was setup correctly. Still, apart from the WiFi password, we had no valuable insights for the investigation. And then a random idea struck. What if the adversary had mixed up the USB devices and plugged in a mouse instead of a keyboard?

So we placed the keylogger in a test environment, plugged in a keyboard and to our surprise it was logging without a single fault. Even bigger was the relief, when we plugged in a mouse – moved and clicked it a few times – and looked at the logs again:

Only for the last two lines, we plugged in the mouse. And the output we see (notably lots of [LCtrl] and [+N]) shows significant similarities to the entire previous log.

At this point, we assessed, that the perpetrator most likely did not exfiltrate any useful information this way. Instead, with a high chance the keylogger was plugged in to USB device other than an ordinary keyboard.

Key Learnings

Keylogger forensics could uncover valuable information. Additionally, the process can be fairly straight forward. In this scenario we did not have to circumvent any physical protection mechanisms.

  • Keep it simple (reverse image searching for a simple photo of the keylogger led us straight to the relevant documentation)
  • Even though the default password was changed, retrieving it from the keylogger was as easy as running strings on the memory dump
  • Dumping the memory also allowed us to extract unencrypted log files and keylogger settings immediately
  • The keylogger configuration may contain some interesting information such as credentials for SMTP, FTP or a WiFi hotspot that could lead you straight to the adversary
  • Adversaries make mistakes too, for example placing a keylogger between a computer and the mouse cable

Schwachstelle öffnet Türen in mehr als 3.000 Hotels

Es mag bequem klingen: Die Zimmertür im Hotel lässt sich ganz ohne Schlüssel oder Karte vom Smartphone aus entriegeln. Doch was passiert, wenn die Logik eines solchen Systems nicht ausreichend abgesichert ist?

Zimmertüren von Hotels aus über 25 Ländern ließen sich mit einer neu entdeckten Schwachstelle öffnen. Bequem? Ja, über das Internet und ohne Zugangsdaten. Dazu konnten sämtliche Reservierungsinformationen (u. a. Name, E-Mail, Reservierungszeitraum und Raumnummer) eingesehen werden. Doch wie kam es dazu?

Zusammenfassung

Die Firma straiv ist ein innovativer und digitaler Begleiter für Hotelbranchen. Als solcher bieten sie unter anderem Online-Check-ins und digitale Türöffnungen an. Was den Sicherheitsforschern Björn Brauer, Deniz Adrian und David Mathiszik bei einem Hotelbesuch jedoch auffiel: Angreifenden wäre es dank einer fehlerhaften Zugangskontrolle in der API möglich, den Check-in und das Öffnen von Türen auch ohne Autorisierung über das Internet zu bedienen.

Im Rahmen einer vertraulichen Offenlegung (engl. Responsible Disclosure oder auch Coordinated Vulnerability Disclosure – CVD) wurden die technischen Details daraufhin direkt an den Hersteller übermittelt. straiv reagierte zeitnah und behob die Sicherheitslücke in ihrer Anwendung umgehend.


Dank ihres Software-as-a-Service-Ansatzes konnte das Unternehmen das Sicherheitsrisiko zeitgleich für alle Kunden mitigieren. Es wird daher auch keine CVE-ID für diese Schwachstelle vergeben. Die Veröffentlichung der Schwachstelle erfolgt in Abstimmung mit dem Hersteller frühestens einen Monat nach der erfolgreichen Behebung.

Die Ursache: Broken Access Control

Broken Access Control belegt aktuell Platz 1 unter den beliebtesten (lies: häufigsten) Schwachstellen in Webanwendungen (siehe: A01:2021 – OWASP Top 10). Auch hier war eine fehlerhafte Zugriffskontrolle die Ursache.

Für gewöhnlich erhalten Gäste eine E-Mail mit einem Link zu ihrer Reservierung. Über diesen werden sie auf die Webanwendung von straiv weitergeleitet. Dort können Buchungsinformationen, die Reisedaten und alle Begleiterprofile eingesehen werden. Ein weiterer Menüreiter führt zu den digitalen Zimmerschlüsseln. Darüber kann die Zimmertür während des eigenen Buchungszeitraums gesteuert werden. Dies geschieht über die API von straiv.io.

Normale API-Anfragen schienen mindestens durch einen HTTP-Header (X-Token), einen Code (cryptcode) und die Reservierungsnummer (reservation) geschützt zu werden. Wurde auch nur einer der Werte verändert, so wurde der Zugriff erwartungsgemäß verwehrt. Fehlten jedoch alle Werte gleichzeitig, wurde nur noch die Reservierungsnummer interpretiert.

In der folgenden beispielhaften Anfrage wurden sämtliche Authentifizierungsparameter, bis auf die Reservierungsnummer, leer gelassen und die API antwortete dennoch mit Informationen zur Reservierung.

POST /api/v2/auth HTTP/2
Host: start.straiv.io
X-Token:
X-Code:
X-Version: 12.3.0
Content-Type: application/json
{
    "cryptcode":"",
    "platform":"linux",
    "browser":"Firefox",
    "version":"115.0",
    "tokens":[],
    "reservation":"3XXXXX"
}

Das Ergebnis enthielt neben anderen Informationen auch einen validen token, der für weitere API-Anfragen genutzt werden konnte.

So lieferte der folgende API-Aufruf noch mehr Kundendetails:

GET /api/v2/vblo/pms/reservation?reservation_id= HTTP/2
Host: start.straiv.io
Accept: application/json, text/plain, */
X-Token: sXXXXXXXXXXXXXXXXXXXh
X-Code: XXXX
X-Version: 12.3.0

Statt die API zu verwenden, kann auch die remote_url aus der Antwort der ersten API-Anfrage verwendet werden, um bequem über die Webanwendung auf die Reservierung zuzugreifen:

HiSolutions hat keine Enumeration von Nutzerdaten durchgeführt und über das Abschätzen der Auswirkungen dieser Schwachstelle hinaus nicht mit der API oder den Buchungen interagiert. Prinzipiell standen alle Funktionalitäten des legitimen Benutzers uneingeschränkt zur Verfügung.

Mitigation

Für die Kunden von straiv bestand kein weiterer Handlungsbedarf. Die Sicherheitslücke wurde von den Entwicklern ernst genommen und umgehend geschlossen.

Grundsätzlich lassen sich Fehler dieser Art durch folgende allgemeine Empfehlungen verhindern:

  • Vertrauen Sie keinen Nutzereingaben – validieren Sie diese.
    Verlassen Sie sich nie auf die Gültigkeit von jeglichen Werten, die von den Endbenutzern beeinflusst werden können. Dazu gehören auch Cookie-Werte, Anfragenparameter und HTTP-Header. Auch auf serverseitig gespeicherte Informationen sollte nich blind in allen Kontexten vertraut werden.
  • Überprüfen Sie Gültigkeit aller Werte serverseitig. Weisen Sie leere oder ungültige Authentifizierungsinformationen zurück. Achten Sie bei der Implementierung von Tests auf eine vollständige Abdeckung aller Randszenarien (ein, mehrere oder auch alle Werte sind unerwartet, NULL, nicht definiert, vom falschen Typ, etc.).
  • Verwenden Sie starke Authentifizierungsmethoden.
    Implementationen sind stets abhängig von der Anwendung und dem Kontext. Greifen Sie, wenn möglich, auf bewährte und praxiserprobte Bibliotheken und Authentifizierungslösungen zurück. Verwenden Sie besonders in Bezug auf sensitive Informationen Zwei-Faktor-Authentifizierung. Stellen Sie zudem sicher, dass alle automatisch generierten Schlüssel, Codes und Token nicht leicht zu erraten und somit vor Brute-Force-Angriffen geschützt sind (vgl. UUID v4).
  • Durchsatzbegrenzung (engl. Rate Limiting) der API-Anfragen:
    Begrenzen Sie die mögliche Anzahl der Anfragen von einzelnen Systemen, um dem Missbrauch, wie der schnellen Enumeration von gültigen Reservierungen, vorzubeugen.

In ihrem Update hat straiv mindestens eine Anfragenbegrenzung aktiviert und Reservierungsnummern auf ein nicht-erratbares Format geändert.

Wie HiSolutions helfen kann

HiSolutions bietet spezialisierte Penetrationstests für Webanwendungen und Infrastrukturen an. Hierbei greifen wir auf langjährige Erfahrung zurück und kombinieren die Fähigkeiten modernster Scantechnologien mit manuellen Prüfverfahren, um die bestmögliche Testabdeckung zu gewährleisten.

Stellen Sie sicher, dass Schwachstellen gefunden und behoben werden, bevor Sie ausgenutzt werden können und kontaktieren Sie uns unter +49 30 533 289 0 oder dem Kontakformular für ein kostenloses Erstgespräch.

Koordinierte Veröffentlichung

  • 22.05.2024 HiSolutions sammelt Details zur Schwachstelle.
    Finder: Björn Brauer, Deniz Adrian & David Mathiszik
  • 23.05.2024 HiSolutions informiert betroffene Hotelkette und wird an straiv weitergeleitet.
  • 25.05.2024 straiv vereinbart einen Termin für die Übermittlung aller Details.
  • 04.06.2024 HiSolutions teilt alle Details mit straiv.
  • 06.06.2024 straiv veröffentlicht ein Update und HiSolutions bestätigt den Fix.

CVE-2024-24272 – DualSafe Password Manager Leaks Credentials

During an investigation, HiSolutions discovered a credential leak of a password manager that was installed as browser extension. After reporting the vulnerability, the vendor was quick to respond and implemented a fix.

Summary

The DualSafe Password Manager by iTop before version 1.4.24 leaks credentials as plaintext in a log file that can be accessed by the local user without knowledge of the master secret (CWE-532). This vulnerability was assigned CVE-2024-24272.

Update to the newest version (at least 1.4.24) as soon as possible and replace potentially leaked credentials.

Vulnerability Details

The following details were produced in a test setup with the vulnerable version 1.4.21 of the DualSafe Password Manager installed in Chrome. After storing and using several credential pairs via the blue extension icon on the top right corner, the log file started showing some entries that contain the plaintext credentials.

Logging is done via a text file in the directory of the browser extension, in this case: C:\Users\User\AppData\Local\Google\Chrome\User Data\Default\Local Extension Settings\lgbjhdkjmpgjgcbcdlhkokkckpjmedgc\000003.log (file name may vary).

The following image depicts the credential pair stored in DualSafe (right) as well as the log file that contains the same password as plaintext (left).

DualSafe password manager and its log file. Cleartext credentials are marked in the log file.
DualSafe Password Manager leaks plaintext password in log file.

One interesting thing to note is that, while the log file contains some credentials as plaintext in a structure like this one: cacheTabinfoes1_1Þ{"[...]":{"confirmItem":{"pwd":"<password>",[...], "type":"login","uname":"<user>","uri":["<url>"]}}}, there are also similar structures with the key pwd but their value is encrypted. Though the observed log events did not indicate the exact trigger for an entry with a plaintext password, passwords could already be extracted after just a few login attempts.

Usually, the password manager requires a master secret to unlock and access the stored credentials. This vulnerability allows an attacker to harvest stored credentials from the log file without knowing the master secret.

Remediation

iTop announced a fix in version 1.4.24.

Shortly after reporting the vulnerability details to iTop, a fix was implemented and rolled out across Firefox, Edge, and Chrome. Update to the newest version as soon as possible and check for potentially leaked passwords in the described location (the exact path depends on the browser).

Should passwords have been leaked this way, rotate them after updating the extension.

Responsible Disclosure Timeline

  • 04.01.2024 – HiSolutions contacts iTop
  • 30.01.2024 – HiSolutions contacts iTop again after no response
  • 31.01.2024 – iTop responds and requests vulnerability details
  • 31.01.2024 – HiSolutions provides all vulnerability details
  • 01.02.2024 – iTop announces that a fix has been implemented and will be published soon
  • 02.02.2024 – iTop requests a delay before publication to roll out the fix
  • 05.02.2024 – iTop releases 1.4.24 on Firefox and Edge
  • 15.02.2024 – iTop releases 1.4.24 on Chrome
  • 12.03.2024 – HiSolution requests green light for publication
  • 13.03.2024 – iTop accepts and states that 1.4.24 fixes the vulnerability

Credits

This vulnerability was discovered by Paula T., Joshua Z. and Pascal B. (HiSolutions AG). We also thank iTop for their swift response and remediation regarding this vulnerability.