GitHub Security Advisory: GHSA-hqjr-43r5-9q58
Package: mobsf (PIP)
Severity: MODERATE (CVSS 5.3)
CWE: CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
Vulnerable versions: <= 4.4.5
Patched in: 4.4.6

Summary: MobSF has SQL Injection in its SQLite Database Viewer Utils

Details:
## Description

MobSF's `read_sqlite()` function in `mobsf/MobSF/utils.py` (lines 542-566) uses Python string formatting (`%`) to construct SQL queries with table names read from a SQLite database's `sqlite_master` table. When a security analyst uses MobSF to analyze a malicious mobile application containing a crafted SQLite database, attacker-controlled table names are interpolated directly into SQL queries without parameterization or escaping.

This allows an attacker to:

1. **Cause Denial of Service** -- A malicious table name causes the database viewer to crash, preventing the analyst from viewing ANY data in the SQLite database. A malicious app can use this to hide sensitive data (C2 server URLs, stolen credentials, API keys) from MobSF's analysis.

2. **Achieve SQL Injection** -- The `SELECT * FROM` query on line 557 is provably injectable via `UNION SELECT`, allowing attacker-controlled data to be returned in query results. The current code structure (a `PRAGMA` statement that runs first on line 553) limits the full exploitation chain, but the underlying code is verifiably injectable.

## Root Cause

The vulnerable code in `mobsf/MobSF/utils.py:542-566`:

```python
def read_sqlite(sqlite_file):
    """Sqlite Dump - Readable Text."""
    table_dict = {}
    try:
        con = sqlite3.connect(sqlite_file)
        cur = con.cursor()
        cur.execute('SELECT name FROM sqlite_master WHERE type=\'table\';')
        tables = cur.fetchall()
        for table in tables:
            table_dict[table[0]] = {'head': [], 'data': []}
            cur.execute('PRAGMA table_info(\'%s\')' % table)    # <-- INJECTION POINT 1
            rows = cur.fetchall()
            for sq_row in rows:
                table_dict[table[0]]['head'].append(sq_row[1])
            cur.execute('SELECT * FROM \'%s\'' % table)         # <-- INJECTION POINT 2
            rows = cur.fetchall()
            for sq_row in rows:
                tmp_row = []
                for each_row in sq_row:
                    tmp_row.append(str(each_row))
                table_dict[table[0]]['data'].append(tmp_row)
    except Exception:
        logger.exception('Reading SQLite db')
    return table_dict
```

**Lines 553 and 557** use `%` string formatting to interpolate `table` (a tuple from `sqlite_master`) directly into SQL strings. The `table` value is attacker-controlled when the SQLite database originates from a malicious application being analyzed.

## Attack Vector

The `read_sqlite()` function is called from two locations:

1. **Dynamic Analysis File Viewer** (`mobsf/DynamicAnalyzer/views/common/device.py:64`):
   - Triggered when an analyst clicks to view a `.db` file in device data
   - Applies to both Android and iOS dynamic analysis

2. **iOS Static Analysis File Viewer** (`mobsf/StaticAnalyzer/views/ios/views/view_source.py:123`):
   - Triggered when an analyst clicks to view a `.db` file during iOS static analysis

### Attack Scenario

1. Attacker creates a malicious Android A