forked from JoasASantos/NeuroSploit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatabase.py
More file actions
executable file
·243 lines (207 loc) · 10.8 KB
/
Copy pathdatabase.py
File metadata and controls
executable file
·243 lines (207 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
"""
NeuroSploit v3 - Database Configuration
"""
import logging
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy import text
from backend.config import settings
logger = logging.getLogger(__name__)
class Base(DeclarativeBase):
"""Base class for all models"""
pass
# Create async engine
engine = create_async_engine(
settings.DATABASE_URL,
echo=settings.DEBUG,
future=True
)
# Create async session factory
async_session_maker = async_sessionmaker(
engine,
class_=AsyncSession,
expire_on_commit=False
)
# Alias for background tasks
async_session_factory = async_session_maker
async def get_db() -> AsyncSession:
"""Dependency to get database session"""
async with async_session_maker() as session:
try:
yield session
await session.commit()
except Exception:
await session.rollback()
raise
finally:
await session.close()
async def _run_migrations(conn):
"""Run schema migrations to add missing columns"""
try:
# Check and add duration column to scans table
result = await conn.execute(text("PRAGMA table_info(scans)"))
columns = [row[1] for row in result.fetchall()]
if "duration" not in columns:
logger.info("Adding 'duration' column to scans table...")
await conn.execute(text("ALTER TABLE scans ADD COLUMN duration INTEGER"))
# Check and add columns to reports table
result = await conn.execute(text("PRAGMA table_info(reports)"))
columns = [row[1] for row in result.fetchall()]
if columns: # Table exists
if "auto_generated" not in columns:
logger.info("Adding 'auto_generated' column to reports table...")
await conn.execute(text("ALTER TABLE reports ADD COLUMN auto_generated BOOLEAN DEFAULT 0"))
if "is_partial" not in columns:
logger.info("Adding 'is_partial' column to reports table...")
await conn.execute(text("ALTER TABLE reports ADD COLUMN is_partial BOOLEAN DEFAULT 0"))
# Check and add columns to vulnerabilities table
result = await conn.execute(text("PRAGMA table_info(vulnerabilities)"))
columns = [row[1] for row in result.fetchall()]
if columns: # Table exists
if "test_id" not in columns:
logger.info("Adding 'test_id' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN test_id VARCHAR(36)"))
if "poc_parameter" not in columns:
logger.info("Adding 'poc_parameter' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN poc_parameter VARCHAR(500)"))
if "poc_evidence" not in columns:
logger.info("Adding 'poc_evidence' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN poc_evidence TEXT"))
if "screenshots" not in columns:
logger.info("Adding 'screenshots' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN screenshots JSON DEFAULT '[]'"))
if "url" not in columns:
logger.info("Adding 'url' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN url TEXT"))
if "parameter" not in columns:
logger.info("Adding 'parameter' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN parameter VARCHAR(500)"))
if "validation_status" not in columns:
logger.info("Adding 'validation_status' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN validation_status VARCHAR(20) DEFAULT 'ai_confirmed'"))
if "ai_rejection_reason" not in columns:
logger.info("Adding 'ai_rejection_reason' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN ai_rejection_reason TEXT"))
if "poc_code" not in columns:
logger.info("Adding 'poc_code' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN poc_code TEXT"))
if "confidence_score" not in columns:
logger.info("Adding 'confidence_score' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN confidence_score INTEGER"))
if "confidence_breakdown" not in columns:
logger.info("Adding 'confidence_breakdown' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN confidence_breakdown JSON DEFAULT '{}'"))
if "proof_of_execution" not in columns:
logger.info("Adding 'proof_of_execution' column to vulnerabilities table...")
await conn.execute(text("ALTER TABLE vulnerabilities ADD COLUMN proof_of_execution TEXT"))
# Check if agent_tasks table exists
result = await conn.execute(
text("SELECT name FROM sqlite_master WHERE type='table' AND name='agent_tasks'")
)
if not result.fetchone():
logger.info("Creating 'agent_tasks' table...")
await conn.execute(text("""
CREATE TABLE agent_tasks (
id VARCHAR(36) PRIMARY KEY,
scan_id VARCHAR(36) NOT NULL,
task_type VARCHAR(50) NOT NULL,
task_name VARCHAR(255) NOT NULL,
description TEXT,
tool_name VARCHAR(100),
tool_category VARCHAR(100),
status VARCHAR(20) DEFAULT 'pending',
started_at DATETIME,
completed_at DATETIME,
duration_ms INTEGER,
items_processed INTEGER DEFAULT 0,
items_found INTEGER DEFAULT 0,
result_summary TEXT,
error_message TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (scan_id) REFERENCES scans(id) ON DELETE CASCADE
)
"""))
await conn.execute(text("CREATE INDEX IF NOT EXISTS idx_agent_tasks_scan_id ON agent_tasks(scan_id)"))
await conn.execute(text("CREATE INDEX IF NOT EXISTS idx_agent_tasks_status ON agent_tasks(status)"))
# Check if vulnerability_tests table exists
result = await conn.execute(
text("SELECT name FROM sqlite_master WHERE type='table' AND name='vulnerability_tests'")
)
if not result.fetchone():
logger.info("Creating 'vulnerability_tests' table...")
await conn.execute(text("""
CREATE TABLE vulnerability_tests (
id VARCHAR(36) PRIMARY KEY,
scan_id VARCHAR(36) NOT NULL,
endpoint_id VARCHAR(36),
vulnerability_type VARCHAR(100) NOT NULL,
payload TEXT,
request_data JSON DEFAULT '{}',
response_data JSON DEFAULT '{}',
is_vulnerable BOOLEAN DEFAULT 0,
confidence FLOAT,
evidence TEXT,
tested_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (scan_id) REFERENCES scans(id) ON DELETE CASCADE,
FOREIGN KEY (endpoint_id) REFERENCES endpoints(id) ON DELETE SET NULL
)
"""))
await conn.execute(text("CREATE INDEX IF NOT EXISTS idx_vulnerability_tests_scan_id ON vulnerability_tests(scan_id)"))
# Check if vuln_lab_challenges table exists
result = await conn.execute(
text("SELECT name FROM sqlite_master WHERE type='table' AND name='vuln_lab_challenges'")
)
if not result.fetchone():
logger.info("Creating 'vuln_lab_challenges' table...")
await conn.execute(text("""
CREATE TABLE vuln_lab_challenges (
id VARCHAR(36) PRIMARY KEY,
target_url TEXT NOT NULL,
challenge_name VARCHAR(255),
vuln_type VARCHAR(100) NOT NULL,
vuln_category VARCHAR(50),
auth_type VARCHAR(20),
auth_value TEXT,
status VARCHAR(20) DEFAULT 'pending',
result VARCHAR(20),
agent_id VARCHAR(36),
scan_id VARCHAR(36),
findings_count INTEGER DEFAULT 0,
critical_count INTEGER DEFAULT 0,
high_count INTEGER DEFAULT 0,
medium_count INTEGER DEFAULT 0,
low_count INTEGER DEFAULT 0,
info_count INTEGER DEFAULT 0,
findings_detail JSON DEFAULT '[]',
started_at DATETIME,
completed_at DATETIME,
duration INTEGER,
notes TEXT,
logs JSON DEFAULT '[]',
endpoints_count INTEGER DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
"""))
await conn.execute(text("CREATE INDEX IF NOT EXISTS idx_vuln_lab_status ON vuln_lab_challenges(status)"))
await conn.execute(text("CREATE INDEX IF NOT EXISTS idx_vuln_lab_vuln_type ON vuln_lab_challenges(vuln_type)"))
else:
# Migrate existing table - add new columns if missing
result = await conn.execute(text("PRAGMA table_info(vuln_lab_challenges)"))
columns = [row[1] for row in result.fetchall()]
if "logs" not in columns:
await conn.execute(text("ALTER TABLE vuln_lab_challenges ADD COLUMN logs JSON DEFAULT '[]'"))
if "endpoints_count" not in columns:
await conn.execute(text("ALTER TABLE vuln_lab_challenges ADD COLUMN endpoints_count INTEGER DEFAULT 0"))
logger.info("Database migrations completed")
except Exception as e:
logger.warning(f"Migration check failed (may be normal on first run): {e}")
async def init_db():
"""Initialize database tables and run migrations"""
async with engine.begin() as conn:
# Create all tables from models
await conn.run_sync(Base.metadata.create_all)
# Run migrations to add any missing columns
await _run_migrations(conn)
async def close_db():
"""Close database connection"""
await engine.dispose()