A number of Android mobile phones from a specific manufacturer (Samsung) have been found to log NFC traffic, which can be exported using the Android Dumpsys command. The data for these logs is encrypted, but the key used is static across a number of tested phone models and Android versions from the same manufacturer (leading to understanding that this would be a global issue across all phones from this manufacturer), and so easily decrypted. Logs hold all NFC traffic, including traffic for provisioning and use of Samsung Pay transactions. Logs are rolled using a rotation of five log files, with a total of 250Kbytes of storage between them.
Gaining access to the logs requires an application or shell with ‘dump’ privileges, which can be gained through local access to activate ADB. Alternatively, if an RCE exploit is found in an existing app with such privileges, exploitation can occur directly through that application. Root privilege is not required for log access.
This vulnerability was disclosed to Samsung in late 2019, and patched in the April security update as SVE-2019-16359. We have given additional time from this patch release to our detailed public disclosure to allow for the distribution and installation of the patch on end user devices.
As an adjunct to this research, we have also found that ‘dump’ privileges are sometimes provided to system applications including the remotely accessible services such as Bluetooth, implying that an RCE in the Bluetooth stack would enable remote capture of NFC traffic from these devices.
Details of NFC logging issue
Modern communications can be very complicated, and communications bugs can be intermittent and difficult to diagnose. For these reasons it is common for developers to put logging in to help understand issues after they have occurred. Logging is often included in production software, although it is usually sanitized to prevent the leakage of sensitive information.
On Android there are two main sources of log information – logcat and dumpsys. Both commands are used from the command line, which require that Developer Options and USB debugging has been enabled to get access to a suitably privileged shell. Logcat is commonly used by application developers and well understood, and is not the focus of this blog. The utility dumpsys, which is our focus, is primarily designed to get state information about system processes but is also often used to maintain some history of activities. For example ‘dumpsys input’ outputs details of the state of the input handler (mostly touch events for an Android phone) as well as the last 10 touch events.
Stock Android includes a shell command ‘dumpsys nfc’ which outputs information regarding the NFC service. In a ‘vanilla’ Android implementation, this contains a log of NFC traffic, but that log is sanitized to remove the payloads of each datagram – so you get to see the traffic between the phone and the external device communicating over the NFC interface, but you don’t get a log of the actual information passed between them. However, when this command was exercised on a Samsung A20 phone to see what information was readily accessible, a difference from the standard Android implementation was noted. A sample log is displayed below.
There are three main sections in the file. The first part (highlighted in orange) contains state information, including routing information and settings. The second part (highlighted in green) is titled ‘DEBUG LOG’ and contains plaintext timestamped entries. Review of this log did not find any sensitive information. The final part (highlighted in blue) is titled ‘PERSIST LOG’ which was encoded and warranted further investigation. This blob appears to be Base64 encoded, and was passed through the Linux utility base64 for decoding. The binary output file was checked using hexdump.
The output was found to be data without obvious structure or patterns. The Linux utilities ‘file’ and ‘binwalk’ were unable to categorize the file, so another approach was needed.
Two processes on the phone were observed to run as the ‘nfc’ user. One process was called com.android.nfc from the package /system/app/NfcNci/NfcNci.apk. This package was copied from the phone and the classes.dex loaded into Ghidra. A function from this, called ‘com.android.nfc.NfcService.dump’, was decompiled as shown below.
This code suggests the log is encrypted, using a key loaded in the function this.loadKey()
From this code it was found that the key is stored Base64 encoded on the data partition. The data partition is writable, so the next question was how was this key generated? The rest of the code in this NfcNci.apk package was searched but there were no other references to this key path. Native libraries and the other executable was also searched for without success.
Using a rooted phone, a brute force search for “data/nfc/Key” was performed over all files in the filesystem. This search identified the source of the key as coming from /system/etc/nfc_key
As files on the /system partition are world readable, the key was easily retrieved and found to be static / hardcoded across different phones and Android versions for this manufacturer. With this key information now in hand, a program was made to decode the contents of the PERSIST LOG. The decrypted log is ascii formatted as shown below.
These messages look to be NCI messages, which are the low messages sent between the main processor and the NFC controller.
This particular phone had been used to read a credit card, so a search was performed using the known PAN, which was successful as shown below (the actual PAN is masked below, but it contained the full PAN data in the raw dump).
This confirmed that the log contains full data logs of interactions on the NFC interface, including any contactless account details which were processed by payment applications on the phone. A further test was performed by enrolling the card in Samsung pay and using it to perform a test payment.
The log was then dumped, decrypted and a search made for the tokenized PAN shown in the Samsung Pay app. This showed that PAN data was being stored in the log even for Samsung Pay transactions (note that the impact here is reduced somewhat by the tokenization of the PAN).
The phone used for testing was a Samsung Galaxy A20. Similar results were observed on a Galaxy A8 and Galaxy S9.
When a dump is requested, entries in logcat show the logs are retrieved from /data/vendor/nfc/nci_log1[-5]. Reversing the code showed the NCI messages are cached in memory and written to disk when the cache exceeds 0xC7FF (51,199) bytes (nfc_nci_sec.so: persistent_log_write()). The cache is then written to the next file in the rotation (nfc_nci_sec.so: store_log()). No expiry or deletion of NCI logs is noted.
Testing found that each log file held around four payment transactions, but five logs are maintained meaning overall storage is expected to hold approximately twenty complete transactions.
Access to the dump is protected by the android.permission.DUMP permission which has been granted to the shell app (ADB). Other apps may ask for the DUMP permission, and it can be granted via adb, meaning any person with local unlocked access to the phone could install an app which retrieves the NCI logs. There are also a few factory installed apps (including the Google Play Store, Samsung SoundAlive and Samsung Game Optimizing Service) which have been granted this permission. Vulnerabilities in any of these apps may allow an attacker to recover sensitive account data without using ADB.
Modified privileges in Samsung applications
Exacerbating the issue with the storage of logs was the fact that many of the applications and services that are pre-loaded with Samsung mobile phones are provided with additional privileges when compared to default Android settings – and this includes the android.permission.DUMP which is required for the exploitation of this vulnerability. Review of a single Samsung phone in the laboratory during the testing of this vulnerability indicated that remotely accessible services, such as Bluetooth and Internet services, are provided with this permission.
However, it was also found that logging of touch events, which occurs in default Android implementations, was not present in the Samsung devices tested. This prevents the exploitation of a Bluetooth RCE from gaining full NFC and touch data, which would expose both card and PIN data during payments.
Recommendations and further research
Phone and OS vendors are recommended to be very careful when changing default privilege levels, or adding additional applications which have system privileges. Operating systems dump and logging commands should be limited to the context and operation of the application calling those commands – access to all touch events, NFC traffic, etc., should not be possible without root privileges (however, such access without root is possible in current Android implementations). Consideration is recommended for the approval of Android implementations, such as through the Android Compatibility Test Suite (CTS), to include security aspects such as privilege levels of installed system applications.
Researchers and penetration testers are recommended to investigate dumpsys operation on platforms they are testing; default Android behavior is no guarantee of actual behavior on any specific device, and the power of dumpsys operation to log global details without root privileges should not be ignored. Any RCE vulnerability found should be further investigated to expose and allow for consideration of exploitation of dumpsys on devices where this is found to be possible.