Загрузка данных
#!/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)