In our previous blog, we explored the hidden risks in IoT companion apps and their three-tiered architecture. We identified key vulnerabilities, including insecure communications, hard-coded credentials, vulnerable dependencies, and insecure data storage. As promised, this blog examines one specific recurring vulnerability in detail: insecure data storage.

I. The Silent Data Leak
IoT companion applications act as the bridge between connected devices and end users. While developers focus on securing network communications and API endpoints, the security of data at rest on mobile devices tend to receive less attention. A silent data leak occurs when sensitive information, such as device credentials, authentication tokens, or access code, is stored insecurely within local storage. This vulnerability's impact extends beyond privacy concerns as many tend to argue. In fact, in IoT ecosystems, compromised data can enable unauthorized access, surveillance, or even life-threatening actions. These leaks often remain unnoticed until a user, another app, or an attacker retrieves unprotected files, logs, or backups from the device.
You will find here a conceptual, yet technical understanding of insecure data storage in a specific IoT companion app. Our aim is to explain why such leaks occur; how they are introduced in the app's architecture and code.

II. The Role of Storage in IoT Mobile Architectures
IoT companion apps persist sensitive data locally to ensure continuous operation during offline periods. This includes:
- Device identify and pairing data: Bluetooth pairing keys for local device communication and WiFi credentials for direct device access.
- Authentication credentials: API access tokens (JWT, OAuth, bearer tokens) and user authentication state.
- Operational data: Sensor readings, historical logs, and automation configurations
- Device access credentials: Smart lock PIN codes, camera stream credentials, and security system access codes.

Android devices provide multiple storage mechanisms for IoT companion apps to persist data locally, each serving distinct functional purposes with different security characteristics. When improperly implemented, these mechanisms become sources of silent data leakage.
1. SharedPreferences located at /data/data/[package]/shared_prefs/ stores settings, tokens, and configuration values. Associated risks: XML-based plaintext key-value storage despiteMODE_PRIVATE:0600 permissions.
2. SQLite Database located at /data/data/[package]/databases/ store device lists, relational data, and logs. Associated risks: unencrypted binary format by default with broader 0660 permissions, adding group-level access to the existing apps' level permissions.
3. Internal file storage located at /data/data/[package]/files/ stores configuration files and certificates. Associated risks: developer-defined formats without enforced encryption despite 0600 application level permissions.

III. Insecure Data Storage in Practice: Smart Lock Companion App Use Case
Let's analyze vulnerabilities across three local storage mechanisms through representative implementation examples.

Figure 1: Typical Smart Lock Companion App architecture

Example 1: Vulnerable SharedPreferences implementation.
Android code and corresponding XML file.

public void saveDeviceCredentials(Context context, String apiToken, String pin) {
    SharedPreferences prefs = context.getSharedPreferences("device_prefs", Context.MODE_PRIVATE);
    prefs.edit()
        .putString("api_token", apiToken)
        .putString("unlock_pin", pin)
        .apply();
}
<map>
    <string name="api_token">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...</string>
    <string name="unlock_pin">987654</string>
</map>

The vulnerabilities include: plaintext ASCII/UTF-8 encoding token, and a readable XML structure exposing data relationships.

Example 2: vulnerable implementation of SQLite Database storage

public class DeviceDatabaseHelper extends SQLiteOpenHelper {
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE devices (" +
            "id TEXT PRIMARY KEY, " +
            "bluetooth_key TEXT, " +
            "wifi_password TEXT)");
    }
}

The vulnerabilities include: standard SQLite format which is readable by any SQLite client, exposed historical access patterns, and absence of authentication mechanisms at the database layer.

Example 3: vulnerable implementation of file storage

public void saveDeviceConfig(Context context, JSONObject config) throws IOException {
    File configFile = new File(context.getFilesDir(), "device_config.json");
    FileOutputStream fos = new FileOutputStream(configFile);
    fos.write(config.toString().getBytes(StandardCharsets.UTF_8));
    fos.close();
}

The vulnerabilities manifest as plaintext JSON with device keys, API endpoints, and credentials.

IV. Conclusion
In this post, we examined insecure data storage through a smart lock companion app case study, analyzing three vulnerable implementation patterns. We found that these vulnerabilities stem from a common architectural flaw: treating the app sandbox as sufficient protection. In a future post, we'll explore secure implementation alternatives to mitigate these risks.

References:
1. Images from Freepik
2. Ongoing research findings