Skip to content

Identificación de Sistema Operativo por TTL (Time To Live)

Identificación de Sistema Operativo por TTL

Section titled “Identificación de Sistema Operativo por TTL”

El Time To Live (TTL) es un campo fundamental en los protocolos de red que juega un papel crucial en la identificación de sistemas operativos durante el reconocimiento y escaneo en pentesting.

El tiempo de vida (TTL) hace referencia a la cantidad de tiempo o “saltos” que se ha establecido que un paquete debe existir dentro de una red antes de ser descartado por un enrutador. El TTL también se utiliza en otros contextos, como el almacenamiento en caché de CDN y el almacenamiento en caché de DNS.

Cuando se crea un paquete de información y se envía a través de Internet, existe el riesgo de que siga pasando de enrutador a enrutador indefinidamente. Para mitigar esta posibilidad, los paquetes se diseñan con una caducidad denominada tiempo de vida o límite de saltos.

Proceso del TTL:

  1. Cada paquete tiene un valor numérico que determina cuánto tiempo debe seguir moviéndose por la red
  2. Cada vez que un enrutador recibe un paquete, resta uno al recuento de TTL
  3. Si el recuento de TTL llega a cero después de la resta, el enrutador:
    • Descarta el paquete
    • Envía un mensaje ICMP (Time Exceeded) al host de origen
  • Prevención de bucles infinitos en redes
  • Información de trayectoria de paquetes
  • Diagnóstico de redes (traceroute)
  • Fingerprinting de sistemas operativos
  • Detección de manipulación de paquetes

Relación con la Identificación de Sistema Operativo

Section titled “Relación con la Identificación de Sistema Operativo”

Diferentes sistemas operativos tienen diferentes valores predeterminados de TTL. Esta diferencia se debe a las implementaciones específicas de la pila TCP/IP en cada sistema operativo.

Si enviamos un paquete a una máquina y recibimos una respuesta:
- TTL = 128 → Probablemente Windows
- TTL = 64 → Probablemente Linux/Unix
- TTL = 255 → Probablemente Cisco/Redes
- Otros valores → Requiere análisis adicional

¿Por qué varían los valores TTL por defecto?

Section titled “¿Por qué varían los valores TTL por defecto?”

Los valores TTL predeterminados se establecen en el kernel de cada sistema operativo:

  • Windows: TTL = 128 (desde Windows NT)
  • Linux: TTL = 64 (valor estándar)
  • macOS: TTL = 64
  • Solaris: TTL = 255
  • Cisco IOS: TTL = 255
  • HP-UX: TTL = 64

Basado en la investigación de Subin’s Blog (https://subinsb.com/default-device-ttl-values/), aquí está la tabla completa de valores TTL por defecto:

Sistema OperativoVersiónTTL PredeterminadoProtocolo
WindowsNT 4.0128TCP
Windows2000128TCP
WindowsXP128TCP
WindowsVista128TCP
Windows7128TCP
Windows8128TCP
Windows10128TCP
WindowsServer 2003128TCP
WindowsServer 2008128TCP
WindowsServer 2012128TCP
LinuxKernel 2.464TCP
LinuxKernel 2.664TCP
LinuxKernel 3.x64TCP
LinuxKernel 4.x64TCP
LinuxKernel 5.x64TCP
macOS10.x64TCP
FreeBSDTodas64TCP
OpenBSDTodas64TCP
NetBSDTodas64TCP
Dispositivo/SOVersiónTTL PredeterminadoProtocolo
Cisco IOS12.x255TCP
Cisco IOS15.x255TCP
JuniperJUNOS64TCP
HP-UX11.x64TCP
Solaris864TCP
Solaris964TCP
Solaris1064TCP
AIX5.x64TCP
AIX6.x64TCP
DispositivoSistemaTTL PredeterminadoProtocolo
iPhoneiOS64TCP
Android4.x64TCP
Android5.x64TCP
Android6.x64TCP
Android7.x64TCP
Android8.x64TCP
Android9.x64TCP
Android10.x64TCP
Sistema OperativoTTL ICMPTTL TCPObservaciones
Windows128128Consistente
Linux6464Consistente
macOS6464Consistente
Cisco255255Consistente
Algunos routersVariableVariableDepende de configuración
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
WhichSystem - Identificación de Sistema Operativo por TTL
Versión mejorada con más funcionalidades
Uso: python3 whichsystem.py <direccion-ip>
"""
import re
import sys
import subprocess
import argparse
import socket
from typing import Optional, Tuple
class OSFingerprint:
"""Clase para fingerprinting de SO basado en TTL"""
# Base de datos de valores TTL por SO
OS_DATABASE = {
'Windows': {
'range': (65, 128),
'default_ttl': 128,
'description': 'Sistema operativo Windows (NT/2000/XP/Vista/7/8/10/Server)'
},
'Linux': {
'range': (1, 64),
'default_ttl': 64,
'description': 'Sistema operativo Linux/Unix (Kernel 2.x-5.x)'
},
'macOS': {
'range': (1, 64),
'default_ttl': 64,
'description': 'macOS/iOS (Darwin kernel)'
},
'Cisco': {
'range': (129, 255),
'default_ttl': 255,
'description': 'Dispositivo Cisco (IOS/NX-OS)'
},
'Solaris': {
'range': (1, 64),
'default_ttl': 64,
'description': 'Oracle Solaris'
},
'FreeBSD': {
'range': (1, 64),
'default_ttl': 64,
'description': 'FreeBSD/OpenBSD/NetBSD'
}
}
@staticmethod
def get_ttl_ping(ip_address: str, count: int = 1) -> Optional[int]:
"""
Obtiene el TTL usando ping
Args:
ip_address: Dirección IP objetivo
count: Número de paquetes ping
Returns:
TTL del paquete recibido o None si falla
"""
try:
# Comando ping según el sistema operativo
if sys.platform.startswith('win'):
cmd = ['ping', '-n', str(count), ip_address]
else:
cmd = ['ping', '-c', str(count), ip_address]
proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True
)
stdout, stderr = proc.communicate(timeout=10)
if proc.returncode != 0:
print(f"[!] Error al hacer ping: {stderr}")
return None
# Extraer TTL de la respuesta
# Buscar patrón TTL en diferentes idiomas
ttl_patterns = [
r'TTL=(\d+)',
r'ttl=(\d+)',
r'Tiempo de vida (\d+)',
r'ttl\s+(\d+)'
]
for pattern in ttl_patterns:
match = re.search(pattern, stdout, re.IGNORECASE)
if match:
return int(match.group(1))
print("[!] No se pudo extraer TTL de la respuesta")
return None
except subprocess.TimeoutExpired:
print("[!] Timeout en ping")
return None
except Exception as e:
print(f"[!] Error ejecutando ping: {e}")
return None
@staticmethod
def get_ttl_traceroute(ip_address: str) -> Optional[int]:
"""
Obtiene el TTL usando traceroute (método alternativo)
Args:
ip_address: Dirección IP objetivo
Returns:
TTL estimado o None si falla
"""
try:
if sys.platform.startswith('win'):
cmd = ['tracert', '-d', '-h', '1', ip_address]
else:
cmd = ['traceroute', '-n', '-m', '1', ip_address]
proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True
)
stdout, stderr = proc.communicate(timeout=15)
# traceroute muestra el TTL que causó el timeout
# Buscar el último salto antes del destino
lines = stdout.split('\n')
for line in reversed(lines):
if '*' not in line and line.strip():
# Extraer el número del primer campo (salto)
parts = line.split()
if len(parts) >= 2:
try:
hop_number = int(parts[0])
return hop_number + 1 # TTL aproximado
except ValueError:
continue
return None
except Exception as e:
print(f"[!] Error en traceroute: {e}")
return None
@classmethod
def identify_os(cls, ttl: int) -> dict:
"""
Identifica el SO basado en el valor TTL
Args:
ttl: Valor TTL obtenido
Returns:
Diccionario con información del SO identificado
"""
for os_name, os_info in cls.OS_DATABASE.items():
min_ttl, max_ttl = os_info['range']
if min_ttl <= ttl <= max_ttl:
return {
'os': os_name,
'confidence': cls._calculate_confidence(ttl, os_info['default_ttl']),
'description': os_info['description'],
'ttl_range': os_info['range'],
'default_ttl': os_info['default_ttl']
}
return {
'os': 'Desconocido',
'confidence': 0,
'description': f'TTL {ttl} no coincide con valores conocidos',
'ttl_range': None,
'default_ttl': None
}
@staticmethod
def _calculate_confidence(actual_ttl: int, default_ttl: int) -> float:
"""
Calcula la confianza de la identificación
Args:
actual_ttl: TTL recibido
default_ttl: TTL por defecto del SO
Returns:
Porcentaje de confianza (0-100)
"""
if actual_ttl == default_ttl:
return 100.0
elif abs(actual_ttl - default_ttl) <= 5:
return 80.0
elif abs(actual_ttl - default_ttl) <= 10:
return 60.0
else:
return 40.0
@staticmethod
def validate_ip(ip_address: str) -> bool:
"""
Valida que la dirección IP sea correcta
Args:
ip_address: Dirección IP a validar
Returns:
True si es válida, False en caso contrario
"""
try:
socket.inet_aton(ip_address)
return True
except socket.error:
return False
def main():
parser = argparse.ArgumentParser(
description='WhichSystem - Identificación de SO por TTL',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Ejemplos de uso:
python3 whichsystem.py 192.168.1.1
python3 whichsystem.py -v 10.10.10.188
python3 whichsystem.py --traceroute 8.8.8.8
"""
)
parser.add_argument('ip', help='Dirección IP objetivo')
parser.add_argument('-v', '--verbose', action='store_true',
help='Modo verbose con más información')
parser.add_argument('-t', '--traceroute', action='store_true',
help='Usar traceroute en lugar de ping')
parser.add_argument('-c', '--count', type=int, default=1,
help='Número de paquetes ping (default: 1)')
args = parser.parse_args()
# Validar IP
if not OSFingerprint.validate_ip(args.ip):
print(f"[!] Dirección IP inválida: {args.ip}")
sys.exit(1)
print(f"[+] Analizando {args.ip}...")
print("-" * 50)
# Obtener TTL
if args.traceroute:
ttl = OSFingerprint.get_ttl_traceroute(args.ip)
method = "traceroute"
else:
ttl = OSFingerprint.get_ttl_ping(args.ip, args.count)
method = "ping"
if ttl is None:
print("[!] No se pudo obtener TTL")
sys.exit(1)
print(f"[+] Método usado: {method}")
print(f"[+] TTL recibido: {ttl}")
print("-" * 30)
# Identificar SO
result = OSFingerprint.identify_os(ttl)
print(f"[+] Sistema Operativo: {result['os']}")
print(f"[+] Confianza: {result['confidence']}%")
print(f"[+] Descripción: {result['description']}")
if args.verbose and result['ttl_range']:
print(f"[+] Rango TTL esperado: {result['ttl_range'][0]}-{result['ttl_range'][1]}")
print(f"[+] TTL por defecto: {result['default_ttl']}")
print("-" * 50)
# Advertencias
if result['confidence'] < 70:
print("[!] ADVERTENCIA: Baja confianza en la identificación")
print(" Posibles causas:")
print(" - Firewall modificando TTL")
print(" - Router intermedio")
print(" - Configuración personalizada del SO")
print(" - Red compleja (NAT, VPN, etc.)")
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print("\n[!] Interrumpido por el usuario")
sys.exit(1)
except Exception as e:
print(f"[!] Error inesperado: {e}")
sys.exit(1)
#!/usr/bin/python3
#coding: utf-8
import re, sys, subprocess
# python3 wichSystem.py 10.10.10.188
if len(sys.argv) != 2:
print("\n[!] Uso: python3 " + sys.argv[0] + " <direccion-ip>\n")
sys.exit(1)
def get_ttl(ip_address):
proc = subprocess.Popen(["/usr/bin/ping -c 1 %s" % ip_address, ""], stdout=subprocess.PIPE, shell=True)
(out,err) = proc.communicate()
out = out.split()
out = out[12].decode('utf-8')
ttl_value = re.findall(r"\d{1,3}", out)[0]
return ttl_value
def get_os(ttl):
ttl = int(ttl)
if ttl >= 0 and ttl <= 64:
return "Linux"
elif ttl >= 65 and ttl <= 128:
return "Windows"
else:
return "Not Found"
if __name__ == '__main__':
ip_address = sys.argv[1]
ttl = get_ttl(ip_address)
os_name = get_os(ttl)
print("\n%s (ttl -> %s): %s\n" % (ip_address, ttl, os_name))
Terminal window
# Identificación de Windows
$ python3 whichsystem.py 192.168.1.100
[+] Analizando 192.168.1.100...
--------------------------------------------------
[+] Método usado: ping
[+] TTL recibido: 128
------------------------------
[+] Sistema Operativo: Windows
[+] Confianza: 100%
[+] Descripción: Sistema operativo Windows (NT/2000/XP/Vista/7/8/10/Server)
--------------------------------------------------
Terminal window
# Identificación de Linux
$ python3 whichsystem.py 10.10.10.188
[+] Analizando 10.10.10.188...
--------------------------------------------------
[+] Método usado: ping
[+] TTL recibido: 63
------------------------------
[+] Sistema Operativo: Linux
[+] Confianza: 80%
[+] Descripción: Sistema operativo Linux/Unix (Kernel 2.x-5.x)
--------------------------------------------------
Terminal window
# Caso con modificaciones de red
$ python3 whichsystem.py 172.16.1.50
[+] Analizando 172.16.1.50...
--------------------------------------------------
[+] Método usado: ping
[+] TTL recibido: 45
------------------------------
[+] Sistema Operativo: Linux
[+] Confianza: 40%
[+] Descripción: Sistema operativo Linux/Unix (Kernel 2.x-5.x)
--------------------------------------------------
[!] ADVERTENCIA: Baja confianza en la identificación
Posibles causas:
- Firewall modificando TTL
- Router intermedio
- Configuración personalizada del SO
- Red compleja (NAT, VPN, etc.)
  1. Firewalls y Dispositivos de Red:

    • Algunos firewalls modifican el TTL
    • Load balancers pueden cambiar valores
    • NAT puede afectar los valores
  2. Configuraciones Personalizadas:

    • Administradores pueden cambiar TTL por defecto
    • Scripts de hardening modifican valores
    • Contenedores (Docker) pueden tener TTL diferente
  3. Redes Complejas:

    • VPNs pueden modificar TTL
    • Redes corporativas con múltiples saltos
    • Cloud providers (AWS, Azure, GCP)
  4. Dispositivos Intermedios:

    • Routers y switches pueden decrementar TTL
    • Proxies transparentes
    • Sistemas de IDS/IPS
Sistema OperativoPrecisión EstimadaFactores de Interferencia
Windows90-95%Firewall de Windows
Linux85-90%Distribuciones modificadas
macOS80-85%Configuraciones personalizadas
Cisco95%+Rara modificación
Dispositivos IoT70-80%Firmwares personalizados

Combinar con otros métodos de fingerprinting

Section titled “Combinar con otros métodos de fingerprinting”
def comprehensive_fingerprint(ip_address):
"""
Fingerprinting combinado: TTL + otros métodos
"""
results = {}
# TTL Analysis
ttl = OSFingerprint.get_ttl_ping(ip_address)
results['ttl_analysis'] = OSFingerprint.identify_os(ttl) if ttl else None
# Port scanning (simulado)
results['open_ports'] = check_common_ports(ip_address)
# Service banners
results['service_banners'] = get_service_banners(ip_address)
# HTTP headers
results['http_headers'] = get_http_headers(ip_address)
# Combinar resultados
return combine_fingerprint_results(results)
def combine_fingerprint_results(results):
"""
Combina múltiples técnicas para mayor precisión
"""
confidence_scores = {
'Windows': 0,
'Linux': 0,
'macOS': 0,
'Cisco': 0
}
# TTL aporta 40% de confianza
if results['ttl_analysis']:
os_from_ttl = results['ttl_analysis']['os']
confidence_scores[os_from_ttl] += 40
# Puertos comunes aportan 30%
if 445 in results['open_ports']: # SMB
confidence_scores['Windows'] += 30
if 22 in results['open_ports']: # SSH
confidence_scores['Linux'] += 20
# HTTP headers aportan 20%
if 'IIS' in str(results['http_headers']):
confidence_scores['Windows'] += 20
if 'Apache' in str(results['http_headers']):
confidence_scores['Linux'] += 15
# Determinar SO más probable
best_os = max(confidence_scores, key=confidence_scores.get)
best_score = confidence_scores[best_os]
return {
'os': best_os,
'confidence': best_score,
'method': 'combined_fingerprint'
}
Terminal window
# Nmap tiene opciones específicas para TTL
nmap -O --osscan-guess 192.168.1.100
# Fingerprinting agresivo
nmap -O -v --version-intensity 9 192.168.1.100
# Combinar con TTL manual
nmap -sP --packet-trace 192.168.1.100
  1. Usar múltiples técnicas:

    • Combinar TTL con fingerprinting de servicios
    • Verificar con herramientas como Nmap
    • Analizar banners de servicios
  2. Considerar el contexto de red:

    • Redes corporativas pueden tener reglas específicas
    • Cloud providers modifican TTL
    • VPNs afectan los valores
  3. Documentar hallazgos:

    • Registrar método usado
    • Nivel de confianza obtenido
    • Factores que pueden afectar precisión
  1. Configurar TTL apropiado:

    Terminal window
    # Linux - Cambiar TTL por defecto
    sysctl -w net.ipv4.ip_default_ttl=128
    # Windows - Registry
    reg add HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters /v DefaultTTL /t REG_DWORD /d 128
  2. Monitorear cambios:

    • Usar herramientas de monitoreo de red
    • Logs de firewall
    • Alertas de cambios inusuales
  1. No es 100% confiable:

    • Puede dar falsos positivos
    • Configuraciones modifican resultados
    • No debe usarse como única fuente
  2. Consideraciones éticas:

    • Usar solo en sistemas autorizados
    • Parte de reconocimiento pasivo
    • No genera alertas en sistemas objetivo
  • Usar como complemento: Combinar con otras técnicas
  • Verificar resultados: No confiar únicamente en TTL
  • Documentar metodología: Para auditorías y reportes
  • Mantener actualizado: Los valores pueden cambiar
  • Nmap: nmap -O para OS fingerprinting completo
  • P0f: Passive OS fingerprinting
  • SinFP: Advanced OS fingerprinting
  • Xprobe2: Remote OS detection
  • “The Art of Deception” - Kevin Mitnick
  • “Hacking: The Art of Exploitation” - Jon Erickson
  • “Network Security Assessment” - Chris McNab

La identificación de sistemas operativos por TTL es una técnica simple pero efectiva que forma parte del arsenal básico de cualquier profesional de seguridad. Aunque no es infalible, proporciona información valiosa cuando se combina con otras técnicas de fingerprinting.

  1. TTL varía por SO: Windows=128, Linux=64, Cisco=255
  2. Método pasivo: No genera logs en el objetivo
  3. Limitaciones conocidas: Firewalls y configuraciones afectan precisión
  4. Complementario: Mejor usado con otras técnicas (Nmap, banners, etc.)
  5. Útil en reconocimiento: Primera aproximación rápida al SO

Usa el TTL como primera aproximación en el reconocimiento, pero siempre verifica con múltiples técnicas antes de llegar a conclusiones definitivas sobre el sistema operativo objetivo.


Última actualización: 2025-01-23 Versión: 2.0