Spaces:
Sleeping
Sleeping
File size: 5,461 Bytes
9bc63e5 df4bbaa 803b069 9bc63e5 df4bbaa 803b069 df4bbaa 803b069 df4bbaa 803b069 df4bbaa 803b069 df4bbaa 803b069 df4bbaa 803b069 df4bbaa 803b069 df4bbaa 803b069 df4bbaa 803b069 df4bbaa 803b069 df4bbaa 803b069 |
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 139 140 141 142 143 |
import streamlit as st
import time
import itertools
import string
import requests
# ----------------------------
# Configuración de la página
# ----------------------------
st.set_page_config(
page_title="🔐 Ataques a Contraseñas - Demo Educativa",
page_icon="🔐",
layout="centered"
)
st.title("🔐 Ataques a Contraseñas")
st.markdown("""
**Demo educativa** usando contraseñas reales del top 10,000 más comunes (SecLists).
Ingresa una contraseña **simple** (máx. 6 caracteres, solo minúsculas y números).
⚠️ **Solo para fines didácticos. No uses contraseñas reales.**
""")
# ----------------------------
# Cargar diccionario real desde SecLists (solo una vez)
# ----------------------------
@st.cache_resource
def load_common_passwords():
url = "https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/Common-Credentials/10k-most-common.txt"
try:
with st.spinner("📥 Cargando diccionario real (top 10k contraseñas)..."):
response = requests.get(url, timeout=10)
response.raise_for_status()
# Filtrar: solo contraseñas de 1 a 6 caracteres, alfanuméricas
passwords = []
for line in response.text.splitlines():
p = line.strip().lower()
if 1 <= len(p) <= 6 and p.isalnum():
passwords.append(p)
if len(passwords) >= 5000: # Límite para velocidad
break
return passwords
except Exception as e:
st.warning("⚠️ No se pudo cargar el diccionario. Usando lista de respaldo.")
return [
"123456", "12345", "password", "qwerty", "abc123",
"admin", "letmein", "welcome", "monkey", "dragon",
"123123", "sunshine", "iloveyou", "princess", "football"
]
COMMON_PASSWORDS = load_common_passwords()
# ----------------------------
# Funciones de ataque
# ----------------------------
def brute_force_attack(target, max_length=6):
chars = string.ascii_lowercase + string.digits
start_time = time.time()
attempts = 0
for length in range(1, max_length + 1):
for guess_tuple in itertools.product(chars, repeat=length):
guess = ''.join(guess_tuple)
attempts += 1
if guess == target:
return guess, attempts, time.time() - start_time
return None, attempts, time.time() - start_time
def dictionary_attack(target):
start_time = time.time()
attempts = 0
for guess in COMMON_PASSWORDS:
attempts += 1
if guess == target:
return guess, attempts, time.time() - start_time
return None, attempts, time.time() - start_time
def hybrid_attack(target):
start_time = time.time()
attempts = 0
base_words = ["password", "admin", "user", "test", "hello", "welcome", "qwerty", "love", "sunshine", "dragon"]
suffixes = ["", "1", "123", "2023", "2024", "!", "01", "12", "789"]
transformations = set()
for word in base_words:
for suf in suffixes:
# Original y capitalizada
transformations.add(word + suf)
transformations.add(word.capitalize() + suf)
# Reemplazos comunes
w = word.replace('a', '@').replace('e', '3').replace('o', '0').replace('i', '1')
transformations.add(w + suf)
transformations.add(w.capitalize() + suf)
for guess in transformations:
attempts += 1
if guess == target:
return guess, attempts, time.time() - start_time
return None, attempts, time.time() - start_time
# ----------------------------
# Interfaz de usuario
# ----------------------------
password = st.text_input(
"🔒 Ingresa una contraseña de prueba (máx. 6 caracteres, minúsculas y números):",
type="password",
max_chars=6
)
# Validación básica
if password and not all(c in (string.ascii_lowercase + string.digits) for c in password):
st.warning("⚠️ Usa solo letras minúsculas y números (ej: 'abc123').")
password = ""
attack_type = st.selectbox("🎯 Elige un tipo de ataque:", ["Fuerza Bruta", "Diccionario", "Híbrido"])
if st.button("🚀 Iniciar ataque", disabled=not password):
if len(password) > 6:
st.error("La contraseña debe tener máximo 6 caracteres.")
else:
with st.spinner("Buscando..."):
if attack_type == "Fuerza Bruta":
result, attempts, duration = brute_force_attack(password, len(password))
elif attack_type == "Diccionario":
result, attempts, duration = dictionary_attack(password)
else: # Híbrido
result, attempts, duration = hybrid_attack(password)
if result:
st.success(f"✅ ¡Contraseña encontrada! `{result}`")
st.metric("Tiempo", f"{duration:.2f} segundos")
st.metric("Intentos", f"{attempts:,}")
st.balloons()
else:
st.error("❌ Contraseña no encontrada con este método.")
st.metric("Intentos realizados", f"{attempts:,}")
st.info("💡 Prueba una contraseña más común o más corta.")
# ----------------------------
# Pie de página
# ----------------------------
st.markdown("---")
st.caption(
"🎓 Demo educativa usando el diccionario '10k-most-common.txt' de SecLists (GitHub). "
"Todo se ejecuta localmente. Código ético y sin riesgos."
) |