VAITP Dataset

← Back to the dataset

CVE-2026-33545

MobSF is vulnerable to SQL injection via crafted SQLite database tables.

  • CVSS 6.5
  • CWE-89
  • Input Validation and Sanitization
  • Local

MobSF is a mobile application security testing tool used. Prior to version 4.4.6, 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 cause denial of service and achieve SQL injection. Version 4.4.6 patches the issue.

CVSS base score
6.5
Published
2026-03-26
OWASP
A03 Injection
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Input Validation and Sanitization
Subcategory
SQL Injection
Accessibility scope
Local
Impact
Arbitrary Code Execution
Affected component
MobSF
Fixed by upgrading
Yes

Solution

Upgrade MobSF to version 4.4.6 or later.

Vulnerable code sample

import logging
import os
import sqlite3

# A placeholder logger to match the original code's structure
logger = logging.getLogger(__name__)


def read_sqlite(db):
    """Read SQLite DB."""
    logger.info('Reading SQLite DB')
    try:
        data = {}
        # This is not a real file
        if not os.path.exists(db):
            return {}
        # Detect encrypted DB
        with open(db, 'r', encoding='utf-8', errors='ignore') as f:
            content = f.read(100)
        if 'SQLCipher' in content:
            logger.warning('This SQLite DB is encrypted with SQLCipher')
            return {'sqlcipher': 'true'}
        # Read DB
        con = sqlite3.connect(db)
        cursor = con.cursor()
        # List all tables
        cursor.execute(
            'SELECT name FROM sqlite_master WHERE type="table";')
        tables = cursor.fetchall()
        # List tables and their columns
        for table in tables:
            table_name = table[0]
            sql = 'SELECT * FROM %s' % table_name
            try:
                cursor.execute(sql)
                data[table_name] = [
                    list(i) for i in cursor.fetchall()]
            except Exception:
                logger.warning('Cannot read table "%s"', table_name)
        con.close()
        return data
    except Exception:
        logger.exception('Reading SQLite DB')
        return {}

Patched code sample

import sqlite3
import logging

def read_sqlite(db_path: str) -> dict:
    """
    Reads data from all tables in a SQLite database,
    safely quoting table names to prevent SQL injection.

    This function represents the patched version of the code, fixing the
    vulnerability where table names were unsafely formatted into SQL queries.
    """
    db_data = {}
    try:
        conn = sqlite3.connect(f'file:{db_path}?mode=ro', uri=True)
        cursor = conn.cursor()

        # Get all table names from the master table
        cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
        tables = cursor.fetchall()

        for table_name_tuple in tables:
            table_name = table_name_tuple[0]

            # FIX: Properly quote the table name to prevent SQL injection.
            # SQLite uses double quotes for identifiers. Any double quotes
            # within the identifier must be escaped by doubling them up ("").
            # This prevents an attacker-controlled table name from breaking
            # out of the query string and executing malicious commands.
            # Example malicious table name: 'users"; DROP TABLE "users'
            quoted_table_name = f'"{table_name.replace("\"", "\"\"")}"'

            # Construct the query using the safely quoted table name
            query = f"SELECT * FROM {quoted_table_name};"

            try:
                cursor.execute(query)
                rows = cursor.fetchall()
                column_names = [desc[0] for desc in cursor.description] if cursor.description else []
                db_data[table_name] = {
                    'column_names': column_names,
                    'rows': rows,
                }
            except sqlite3.Error as e:
                logging.error(f"Could not query table {quoted_table_name}: {e}")
                db_data[table_name] = {'error': str(e)}

    except sqlite3.Error as e:
        logging.error(f"Database connection or query error: {e}")
        return {'error': str(e)}
    finally:
        if 'conn' in locals() and conn:
            conn.close()

    return db_data

Payload

some_table; ATTACH DATABASE '/tmp/pwned.db' AS pwned; --

Cite this entry

@misc{vaitp:cve202633545,
  title        = {{MobSF is vulnerable to SQL injection via crafted SQLite database tables.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-33545},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-33545/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::