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


#!/usr/bin/env python3
"""
Targeted Security Assessment Script for Attendance System
Target: 172.140.140.79 (Davamiyyət sistemi)
WARNING: For authorized penetration testing only!
"""

import requests
import socket
import sys
import json
import time
from urllib.parse import urljoin, urlparse
from concurrent.futures import ThreadPoolExecutor
import warnings
warnings.filterwarnings('ignore')

# Configuration
TARGET_IP = "172.140.140.79"
TARGET_URL = f"http://{TARGET_IP}"
TIMEOUT = 10
THREADS = 20

# Colors for output
class Colors:
    RED = '\033[91m'
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    BLUE = '\033[94m'
    END = '\033[0m'

def print_status(message, color=Colors.BLUE):
    print(f"{color}[*] {message}{Colors.END}")

def print_vuln(message):
    print(f"{Colors.RED}[!] VULNERABILITY: {message}{Colors.END}")

def print_success(message):
    print(f"{Colors.GREEN}[+] {message}{Colors.END}")

class AttendanceSystemPentest:
    def __init__(self, target):
        self.target = target
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Accept-Language': 'ru,en-US;q=0.9,en;q=0.8',
            'Accept-Encoding': 'gzip, deflate',
            'Connection': 'keep-alive',
        })
        self.findings = []
        
    def check_network_reachability(self):
        """Check if target is reachable and identify open ports"""
        print_status("Checking network reachability...")
        
        common_ports = [21, 22, 23, 25, 53, 80, 110, 143, 443, 3306, 3389, 5432, 8080, 8443]
        open_ports = []
        
        for port in common_ports:
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(2)
                result = sock.connect_ex((TARGET_IP, port))
                if result == 0:
                    open_ports.append(port)
                    print_success(f"Port {port} is OPEN")
                sock.close()
            except Exception as e:
                pass
        
        if 80 in open_ports and 443 not in open_ports:
            self.findings.append({
                "severity": "HIGH",
                "issue": "HTTP without HTTPS",
                "description": "Application runs on unencrypted HTTP (port 80) without HTTPS redirect"
            })
            print_vuln("Application uses unencrypted HTTP without TLS/SSL encryption")
            
        return open_ports
    
    def analyze_security_headers(self):
        """Check for missing security headers"""
        print_status("Analyzing HTTP security headers...")
        
        try:
            response = self.session.get(TARGET_URL, timeout=TIMEOUT, verify=False)
            headers = response.headers
            
            security_headers = {
                'Strict-Transport-Security': 'HSTS missing - vulnerable to SSL stripping',
                'X-Frame-Options': 'Clickjacking protection missing',
                'X-Content-Type-Options': 'MIME-sniffing protection missing',
                'X-XSS-Protection': 'XSS filter not enabled',
                'Content-Security-Policy': 'CSP missing - vulnerable to XSS/injection',
                'Referrer-Policy': 'Referrer policy not set',
                'Permissions-Policy': 'Permissions policy missing'
            }
            
            missing = []
            for header, description in security_headers.items():
                if header not in headers:
                    missing.append(header)
                    print_vuln(f"Missing header: {header} - {description}")
            
            if 'Server' in headers:
                print_vuln(f"Server banner exposed: {headers['Server']}")
                self.findings.append({
                    "severity": "LOW",
                    "issue": "Information Disclosure",
                    "description": f"Server version exposed: {headers['Server']}"
                })
            
            # Check for CORS misconfiguration
            if 'Access-Control-Allow-Origin' in headers:
                if headers['Access-Control-Allow-Origin'] == '*':
                    print_vuln("Dangerous CORS policy: Access-Control-Allow-Origin: *")
                    self.findings.append({
                        "severity": "HIGH",
                        "issue": "CORS Misconfiguration",
                        "description": "Overly permissive CORS allows any origin"
                    })
            
            return missing
            
        except Exception as e:
            print_status(f"Error checking headers: {e}", Colors.RED)
            return []
    
    def enumerate_directories(self):
        """Enumerate common directories and files"""
        print_status("Enumerating directories and files...")
        
        # Based on HAR analysis - React SPA structure
        paths = [
            '/assets/', '/fonts/', '/static/', '/api/', '/graphql',
            '/login', '/admin', '/dashboard', '/api/auth', '/api/users',
            '/.env', '/.git/', '/config.json', '/robots.txt', '/sitemap.xml',
            '/swagger', '/api-docs', '/health', '/metrics',
            '/assets/index.js', '/assets/react.js', '/assets/vendor.js',
            '/site.webmanifest', '/favicon.ico', '/apple-touch-icon.png'
        ]
        
        found = []
        
        def check_path(path):
            try:
                url = urljoin(TARGET_URL, path)
                response = self.session.get(url, timeout=TIMEOUT, verify=False)
                if response.status_code == 200:
                    print_success(f"Found: {path} (200 OK)")
                    found.append(path)
                    
                    # Check for sensitive files
                    if path in ['/.env', '/config.json', '/.git/']:
                        print_vuln(f"Potentially sensitive file exposed: {path}")
                        self.findings.append({
                            "severity": "CRITICAL",
                            "issue": "Sensitive File Exposure",
                            "description": f"{path} is accessible without authentication"
                        })
                        
                elif response.status_code == 403:
                    print_status(f"Forbidden: {path} (403)")
            except:
                pass
        
        with ThreadPoolExecutor(max_workers=THREADS) as executor:
            executor.map(check_path, paths)
        
        return found
    
    def analyze_react_app(self):
        """Analyze React application for exposed source maps and API endpoints"""
        print_status("Analyzing React application structure...")
        
        try:
            # Get main page
            response = self.session.get(TARGET_URL, timeout=TIMEOUT, verify=False)
            content = response.text
            
            # Extract JS files from modulepreload
            import re
            js_files = re.findall(r'href="(/assets/[^"]+\.js)"', content)
            
            print_success(f"Found {len(js_files)} JavaScript files")
            
            # Check for source maps
            for js_file in js_files[:5]:  # Check first 5
                map_url = urljoin(TARGET_URL, js_file + '.map')
                try:
                    map_resp = self.session.get(map_url, timeout=5, verify=False)
                    if map_resp.status_code == 200:
                        print_vuln(f"Source map exposed: {js_file}.map")
                        self.findings.append({
                            "severity": "HIGH",
                            "issue": "Source Map Exposure",
                            "description": f"Source map available at {map_url} - reveals source code"
                        })
                except:
                    pass
            
            # Extract API endpoints from JS
            api_patterns = re.findall(r'["\'](/api/[^"\']+)["\']', content)
            if api_patterns:
                print_success(f"Found {len(api_patterns)} potential API endpoints")
                for api in set(api_patterns):
                    print_status(f"  API Endpoint: {api}")
                    
        except Exception as e:
            print_status(f"Error analyzing React app: {e}", Colors.RED)
    
    def test_authentication_bypass(self):
        """Test for common authentication vulnerabilities"""
        print_status("Testing authentication mechanisms...")
        
        # Check if login page has CSRF protection
        try:
            login_url = urljoin(TARGET_URL, '/login')
            response = self.session.get(login_url, timeout=TIMEOUT, verify=False)
            
            # Check for CSRF token
            if 'csrf' not in response.text.lower() and 'token' not in response.text.lower():
                print_vuln("Login form may lack CSRF protection")
                self.findings.append({
                    "severity": "MEDIUM",
                    "issue": "Missing CSRF Protection",
                    "description": "Login form does not appear to have CSRF tokens"
                })
            
            # Test for default credentials
            common_creds = [
                ('admin', 'admin'),
                ('admin', 'password'),
                ('user', 'user'),
                ('test', 'test')
            ]
            
            print_status("Testing common default credentials...")
            # Note: This is for demonstration - actual brute force should be rate-limited
            
        except Exception as e:
            print_status(f"Error testing auth: {e}", Colors.RED)
    
    def test_cors_misconfiguration(self):
        """Test CORS misconfiguration in detail"""
        print_status("Testing CORS configuration...")
        
        test_origins = [
            'https://evil.com',
            'http://localhost',
            'http://127.0.0.1',
            'https://attacker.com',
            'null'
        ]
        
        vulnerable = False
        for origin in test_origins:
            headers = {
                'Origin': origin,
                'Access-Control-Request-Method': 'POST',
                'Access-Control-Request-Headers': 'Content-Type'
            }
            try:
                response = self.session.options(
                    TARGET_URL, 
                    headers=headers, 
                    timeout=TIMEOUT,
                    verify=False
                )
                
                acao = response.headers.get('Access-Control-Allow-Origin')
                if acao == origin or acao == '*':
                    print_vuln(f"CORS allows origin: {origin}")
                    vulnerable = True
                    
            except:
                pass
        
        if vulnerable:
            self.findings.append({
                "severity": "HIGH",
                "issue": "CORS Misconfiguration",
                "description": "CORS policy allows arbitrary origins to make authenticated requests"
            })
    
    def generate_report(self):
        """Generate final report"""
        print("\n" + "="*60)
        print(f"{Colors.YELLOW}SECURITY ASSESSMENT REPORT{Colors.END}")
        print("="*60)
        print(f"Target: {TARGET_URL}")
        print(f"System: Attendance Management System (Davamiyyət sistemi)")
        print(f"Assessment Date: {time.strftime('%Y-%m-%d %H:%M:%S')}")
        print("="*60)
        
        severity_counts = {"CRITICAL": 0, "HIGH": 0, "MEDIUM": 0, "LOW": 0}
        
        for finding in self.findings:
            sev = finding['severity']
            severity_counts[sev] = severity_counts.get(sev, 0) + 1
            color = Colors.RED if sev in ['CRITICAL', 'HIGH'] else Colors.YELLOW
            print(f"\n{color}[{sev}] {finding['issue']}{Colors.END}")
            print(f"   {finding['description']}")
        
        print("\n" + "="*60)
        print("SUMMARY:")
        for sev, count in severity_counts.items():
            if count > 0:
                color = Colors.RED if sev in ['CRITICAL', 'HIGH'] else Colors.YELLOW
                print(f"{color}{sev}: {count}{Colors.END}")
        
        # Save to file
        report_file = f"pentest_report_{TARGET_IP.replace('.', '_')}.json"
        with open(report_file, 'w') as f:
            json.dump({
                'target': TARGET_URL,
                'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
                'findings': self.findings
            }, f, indent=2)
        print(f"\nDetailed report saved to: {report_file}")

def main():
    print(f"""
    {Colors.BLUE}
    =========================================
    Attendance System Security Assessment
    Target: {TARGET_IP}
    =========================================
    {Colors.END}
    WARNING: This script is for authorized security testing only!
    Unauthorized access to computer systems is illegal.
    """)
    
    pentest = AttendanceSystemPentest(TARGET_URL)
    
    # Run all tests
    pentest.check_network_reachability()
    pentest.analyze_security_headers()
    pentest.enumerate_directories()
    pentest.analyze_react_app()
    pentest.test_authentication_bypass()
    pentest.test_cors_misconfiguration()
    
    # Generate report
    pentest.generate_report()

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print(f"\n{Colors.YELLOW}[!] Assessment interrupted by user{Colors.END}")
        sys.exit(0)