EAV123 commited on
Commit
4af55c1
·
verified ·
1 Parent(s): f94f145

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -230
app.py CHANGED
@@ -16,19 +16,16 @@ def load_components():
16
  # Load deep learning models
17
  cnn_model = load_model('cnn_model.h5')
18
  lstm_model = load_model('lstm_model.h5')
19
-
20
  # Load traditional ML models
21
  with open('rf_model.pkl', 'rb') as f:
22
  rf_model = pickle.load(f)
23
  with open('svm_model.pkl', 'rb') as f:
24
  svm_model = pickle.load(f)
25
-
26
  # Load tokenizer and vectorizer
27
  with open('sql_tokenizer.pkl', 'rb') as f:
28
  tokenizer_data = pickle.load(f)
29
  with open('tfidf_vectorizer.pkl', 'rb') as f:
30
  tfidf_vectorizer = pickle.load(f)
31
-
32
  return {
33
  'cnn_model': cnn_model,
34
  'lstm_model': lstm_model,
@@ -49,17 +46,11 @@ except Exception as e:
49
 
50
  # Preprocess functions
51
  def preprocess_query_for_deep_learning(query, tokenizer, max_sequence_length):
52
- """
53
- Tokenizes and pads the input query to prepare it for deep learning models.
54
- """
55
  sequences = tokenizer.texts_to_sequences([query])
56
  padded = pad_sequences(sequences, maxlen=max_sequence_length, padding='post')
57
  return padded
58
 
59
  def preprocess_query_for_traditional_ml(query, tfidf_vectorizer):
60
- """
61
- Transforms the input query using TF-IDF for traditional ML models.
62
- """
63
  return tfidf_vectorizer.transform([query])
64
 
65
  # Define improved regex patterns for SQL injection attempts
@@ -113,71 +104,48 @@ SAFE_SQL_PATTERNS = [
113
  r"(?i)^UPDATE\s+[\w\d]+\s+SET\s+[\w\d\s=',]+(\s+WHERE\s+[\w\d\s=<>']+)?$",
114
  ]
115
 
 
116
  # Rule-based detection function
117
  def detect_sql_injection_with_regex(query):
118
- """
119
- Detects potential SQL injection patterns using improved regex.
120
- Returns True if any malicious pattern matches and no safe pattern matches.
121
- """
122
- # First check if the query matches any safe pattern
123
  for pattern in SAFE_SQL_PATTERNS:
124
  if re.search(pattern, query.strip()):
125
- # Query matches a safe pattern
126
  return False, None
127
-
128
- # Then check for malicious patterns
129
  for pattern in SQL_INJECTION_PATTERNS:
130
  match = re.search(pattern, query)
131
  if match:
132
  return True, match.group(0)
133
-
134
- # If no malicious pattern found
135
  return False, None
136
 
137
  # Ensemble prediction function
138
  def predict_with_ensemble(query, components):
139
- """
140
- Uses an ensemble of models to predict if the query is malicious.
141
- Returns predictions from individual models and ensemble vote.
142
- """
143
- # Get individual model predictions
144
-
145
  # Random Forest prediction
146
  query_tfidf = preprocess_query_for_traditional_ml(query, components['tfidf_vectorizer'])
147
  rf_pred = int(components['rf_model'].predict(query_tfidf)[0])
148
-
149
  # SVM prediction
150
  svm_pred = int(components['svm_model'].predict(query_tfidf)[0])
151
-
152
  # CNN prediction
153
  query_padded = preprocess_query_for_deep_learning(query, components['tokenizer'], components['max_sequence_length'])
154
  cnn_probability = components['cnn_model'].predict(query_padded)[0][0]
155
  cnn_pred = int(cnn_probability > 0.5)
156
-
157
  # LSTM prediction
158
  lstm_probability = components['lstm_model'].predict(query_padded)[0][0]
159
  lstm_pred = int(lstm_probability > 0.5)
160
-
161
- # Majority voting
162
  votes = [rf_pred, svm_pred, cnn_pred, lstm_pred]
163
- ensemble_pred = np.bincount(votes).argmax()
164
-
165
  return {
166
  'rf': rf_pred,
167
  'svm': svm_pred,
168
  'cnn': {'prediction': cnn_pred, 'probability': float(cnn_probability)},
169
  'lstm': {'prediction': lstm_pred, 'probability': float(lstm_probability)},
170
- 'ensemble': int(ensemble_pred),
171
- 'vote_count': {0: list(votes).count(0), 1: list(votes).count(1)}
172
  }
173
 
174
- # Initialize session state for UI flow control
175
  if 'analysis_stage' not in st.session_state:
176
- st.session_state.analysis_stage = 0 # 0: not started, 1: regex done, 2: ensemble done
177
-
178
  if 'regex_result' not in st.session_state:
179
  st.session_state.regex_result = None
180
-
181
  if 'ensemble_result' not in st.session_state:
182
  st.session_state.ensemble_result = None
183
 
@@ -185,14 +153,12 @@ if 'ensemble_result' not in st.session_state:
185
  st.title("🛡️ SQL Injection Detection")
186
  st.markdown("""
187
  This application uses a multi-layered approach to detect potentially malicious SQL queries:
188
- 1. **Rule-based detection** using improved regex patterns
189
  2. **Ensemble learning** with majority voting from 4 models:
190
  - Random Forest
191
  - Support Vector Machine
192
  - Convolutional Neural Network
193
- - Long Short-Term Memory Network
194
-
195
- Enter a query below or select from the examples to begin analysis.
196
  """)
197
 
198
  # Display warning if models couldn't be loaded
@@ -200,142 +166,41 @@ if model_loading_error:
200
  st.warning(f"⚠️ Some models could not be loaded. The application will only use rule-based detection. Error: {model_loading_error}")
201
 
202
  # Example queries in a dropdown
203
- st.subheader("Select an Example or Enter Your Own Query")
204
-
205
  example_categories = {
206
  "Benign SQL Queries": [
207
- "SELECT * FROM users WHERE username='admin'",
208
- "SELECT id, name, price FROM products WHERE category_id=5",
209
- "SELECT COUNT(*) FROM orders WHERE date > '2023-01-01'",
210
- "INSERT INTO logs (user_id, action) VALUES (42, 'login')",
211
- "UPDATE customers SET last_login='2023-06-15' WHERE id=101",
212
- "DELETE FROM sessions WHERE last_activity < '2023-01-01'",
213
- "SELECT email FROM subscribers WHERE active=1",
214
- "INSERT INTO feedback (user_id, message) VALUES (87, 'Great service!')",
215
- "UPDATE inventory SET stock = stock - 1 WHERE product_id = 300",
216
- "SELECT name FROM employees WHERE department = 'Sales'",
217
- "SELECT AVG(rating) FROM reviews WHERE product_id = 55",
218
- "INSERT INTO audit_log (timestamp, event) VALUES (CURRENT_TIMESTAMP, 'update')",
219
- "SELECT * FROM appointments WHERE doctor_id = 10 AND status = 'confirmed'",
220
- "UPDATE settings SET value='dark' WHERE key='theme'",
221
- "SELECT DISTINCT city FROM customers WHERE country='USA'",
222
- "DELETE FROM cart_items WHERE user_id=12 AND product_id=78",
223
- "SELECT MAX(salary) FROM employees WHERE role='manager'",
224
- "INSERT INTO payments (user_id, amount, method) VALUES (33, 99.99, 'credit')",
225
- "UPDATE products SET price = price * 1.1 WHERE category_id = 7",
226
- "SELECT * FROM messages WHERE sender_id = 5 AND is_read = 0"
227
  ],
228
  "Malicious SQL Queries": [
229
- "' OR 1=1 --",
230
- "admin'; DROP TABLE users; --",
231
- "SELECT * FROM users WHERE username='' UNION SELECT username,password FROM admin_users --",
232
- "'; WAITFOR DELAY '0:0:10' --",
233
- "admin' OR '1'='1",
234
- "' OR 'a'='a",
235
- "' OR 1=1#",
236
- "' OR 1=1/*",
237
- "admin'--",
238
- "'; EXEC xp_cmdshell('dir'); --",
239
- "' OR EXISTS(SELECT * FROM users WHERE username = 'admin') --",
240
- "1; DROP TABLE sessions --",
241
- "'; SHUTDOWN --",
242
- "' OR SLEEP(5) --",
243
- "' AND 1=(SELECT COUNT(*) FROM users) --",
244
- "admin' AND SUBSTRING(password, 1, 1) = 'a' --",
245
- "' UNION ALL SELECT NULL,NULL,NULL --",
246
- "0' OR 1=1 ORDER BY 1 --",
247
- "1' AND (SELECT COUNT(*) FROM users) > 0 --",
248
- "' OR (SELECT ASCII(SUBSTRING(password,1,1)) FROM users WHERE username='admin') > 64 --"
249
  ]
250
  }
251
 
252
- # First create category selection
253
- category = st.selectbox(
254
- "Choose query category:",
255
- options=list(example_categories.keys()),
256
- key="category"
257
- )
258
-
259
- # Then show examples from selected category
260
- example = st.selectbox(
261
- "Select an example:",
262
- options=example_categories[category],
263
- key="example"
264
- )
265
-
266
- # Allow user to use the selected example or enter their own
267
- query_source = st.radio(
268
- "Query source:",
269
- ["Use selected example", "Enter my own query"],
270
- key="query_source"
271
- )
272
-
273
- if query_source == "Enter my own query":
274
- query = st.text_area(
275
- "Enter SQL Query:",
276
- height=100,
277
- placeholder="Type your SQL query here..."
278
- )
279
- else:
280
- query = example
281
- st.code(query, language="sql")
282
 
283
  # Analysis process
284
  if st.button("Start Analysis") and query:
285
- # Reset analysis state
286
  st.session_state.analysis_stage = 1
287
-
288
- # Step 1: Rule-based detection
289
  with st.spinner("Running rule-based detection..."):
290
  time.sleep(0.5) # Simulate processing time
291
  is_malicious, matched_pattern = detect_sql_injection_with_regex(query)
292
  st.session_state.regex_result = (is_malicious, matched_pattern)
293
 
294
- # If we have completed the regex analysis
295
  if st.session_state.analysis_stage >= 1 and st.session_state.regex_result is not None:
296
  is_malicious, matched_pattern = st.session_state.regex_result
297
  st.subheader("Step 1: Rule-Based Detection")
298
-
299
  if is_malicious:
300
  st.error("🚨 SQL Injection Detected (Rule-Based)!")
301
  st.warning(f"Matched pattern: `{matched_pattern}`")
302
-
303
- # Show details in expander
304
- with st.expander("Rule-Based Detection Details"):
305
- st.markdown("""
306
- **What was detected:**
307
- - The query matched one or more known SQL injection patterns
308
- - This type of pattern is commonly used in SQL injection attacks
309
- - Review the query for security implications
310
- """)
311
-
312
- st.markdown("**Common SQL injection techniques detected:**")
313
- st.markdown("""
314
- - Comment sequences (`--`) after quotes
315
- - Always true conditions (`OR 1=1`)
316
- - Union-based injections
317
- - SQL command injections
318
- """)
319
  else:
320
  st.success("✅ No SQL injection patterns detected using rules")
321
-
322
- with st.expander("Rule-Based Detection Details"):
323
- st.markdown("""
324
- **Analysis Details:**
325
- - The query did not match any known SQL injection patterns
326
- - The structure appears to be standard SQL syntax
327
- - No suspicious patterns were identified
328
- """)
329
-
330
- # Ask if user wants to proceed with ensemble detection
331
- proceed = st.radio(
332
- "Would you like to proceed with ensemble model detection?",
333
- ["Yes", "No"],
334
- index=0, # Default to Yes
335
- key="proceed"
336
- )
337
-
338
- # Check if models are loaded before allowing ensemble analysis
339
  if proceed == "Yes" and not model_loading_error:
340
  if st.button("Run Ensemble Analysis"):
341
  st.session_state.analysis_stage = 2
@@ -343,114 +208,63 @@ if st.session_state.analysis_stage >= 1 and st.session_state.regex_result is not
343
  time.sleep(1) # Simulate processing time
344
  ensemble_results = predict_with_ensemble(query, components)
345
  st.session_state.ensemble_result = ensemble_results
346
- elif proceed == "Yes" and model_loading_error:
347
- st.error("Cannot run ensemble analysis because models failed to load.")
348
 
349
- # If we have completed the ensemble analysis
350
  if st.session_state.analysis_stage >= 2 and st.session_state.ensemble_result is not None:
351
  results = st.session_state.ensemble_result
352
-
353
  st.subheader("Step 2: Ensemble Model Detection")
354
-
355
- # Create a visual representation of voting
356
- vote_benign = results['vote_count'][0]
357
  vote_malicious = results['vote_count'][1]
358
-
359
- st.markdown(f"### Model Votes")
360
-
361
- # Create columns for the voting visualization
362
  col1, col2 = st.columns(2)
363
-
364
  with col1:
365
  st.metric("Safe Votes", vote_benign)
366
-
367
  with col2:
368
  st.metric("Malicious Votes", vote_malicious)
369
-
370
- # Create a progress bar to visualize the voting ratio
371
  vote_ratio = vote_malicious / (vote_benign + vote_malicious)
372
  st.progress(vote_ratio, text=f"Malicious vote ratio: {vote_ratio*100:.0f}%")
373
-
374
- # Display individual model results
375
  st.markdown("### Individual Model Results")
376
-
377
  model_cols = st.columns(4)
378
-
379
  with model_cols[0]:
380
  st.markdown("**Random Forest**")
381
- if results['rf'] == 1:
382
- st.error("⚠️ Malicious")
383
- else:
384
- st.success("✅ Safe")
385
-
386
  with model_cols[1]:
387
  st.markdown("**SVM**")
388
- if results['svm'] == 1:
389
- st.error("⚠️ Malicious")
390
- else:
391
- st.success("✅ Safe")
392
-
393
  with model_cols[2]:
394
  st.markdown("**CNN**")
395
  cnn_prob = results['cnn']['probability'] * 100
396
- if results['cnn']['prediction'] == 1:
397
- st.error(f"⚠️ Malicious ({cnn_prob:.1f}%)")
398
- else:
399
- st.success(f"✅ Safe ({100-cnn_prob:.1f}%)")
400
-
401
  with model_cols[3]:
402
  st.markdown("**LSTM**")
403
  lstm_prob = results['lstm']['probability'] * 100
404
- if results['lstm']['prediction'] == 1:
405
- st.error(f"⚠️ Malicious ({lstm_prob:.1f}%)")
406
- else:
407
- st.success(f"✅ Safe ({100-lstm_prob:.1f}%)")
408
-
409
  # Final ensemble verdict
410
  st.markdown("### Ensemble Verdict")
411
- if results['ensemble'] == 1:
412
- st.error("🚨 SQL Injection Detected by Majority Vote!")
 
 
413
  else:
414
- st.success(" Query deemed safe by majority vote")
415
-
416
- # Explanation in expander
417
- with st.expander("Ensemble Detection Details"):
418
- st.markdown("""
419
- **How ensemble voting works:**
420
- - Each model casts a vote (0 for safe, 1 for malicious)
421
- - The final decision is based on majority vote
422
- - This approach combines the strengths of different model architectures
423
- - More robust than any single model alone
424
- """)
425
-
426
- if results['ensemble'] == 1:
427
- st.markdown(f"""
428
- **Why was this flagged:**
429
- - {vote_malicious} out of 4 models identified this query as potentially malicious
430
- - The majority vote indicates suspicious patterns
431
- - This query should be carefully reviewed before execution
432
- """)
433
- else:
434
- st.markdown(f"""
435
- **Why was this considered safe:**
436
- - {vote_benign} out of 4 models identified this query as likely safe
437
- - The majority vote indicates standard SQL patterns
438
- - No significant red flags were detected in the ensemble
439
- """)
440
-
441
  # Final verdict combining both approaches
442
  st.subheader("Final Analysis")
443
-
444
  is_malicious_regex, _ = st.session_state.regex_result
445
- is_malicious_ensemble = results['ensemble'] == 1
446
-
447
  if is_malicious_regex or is_malicious_ensemble:
448
- st.error("⚠️ This query appears to contain SQL injection patterns. Review carefully before executing.")
 
 
449
  else:
450
- st.success(" This query appears safe based on both rule-based and ensemble detection.")
451
-
452
- st.info("ℹ️ Remember: Always use parameterized queries and proper input validation in production systems.")
453
-
454
  # Reset button
455
  if st.button("Analyze Another Query"):
456
  st.session_state.analysis_stage = 0
 
16
  # Load deep learning models
17
  cnn_model = load_model('cnn_model.h5')
18
  lstm_model = load_model('lstm_model.h5')
 
19
  # Load traditional ML models
20
  with open('rf_model.pkl', 'rb') as f:
21
  rf_model = pickle.load(f)
22
  with open('svm_model.pkl', 'rb') as f:
23
  svm_model = pickle.load(f)
 
24
  # Load tokenizer and vectorizer
25
  with open('sql_tokenizer.pkl', 'rb') as f:
26
  tokenizer_data = pickle.load(f)
27
  with open('tfidf_vectorizer.pkl', 'rb') as f:
28
  tfidf_vectorizer = pickle.load(f)
 
29
  return {
30
  'cnn_model': cnn_model,
31
  'lstm_model': lstm_model,
 
46
 
47
  # Preprocess functions
48
  def preprocess_query_for_deep_learning(query, tokenizer, max_sequence_length):
 
 
 
49
  sequences = tokenizer.texts_to_sequences([query])
50
  padded = pad_sequences(sequences, maxlen=max_sequence_length, padding='post')
51
  return padded
52
 
53
  def preprocess_query_for_traditional_ml(query, tfidf_vectorizer):
 
 
 
54
  return tfidf_vectorizer.transform([query])
55
 
56
  # Define improved regex patterns for SQL injection attempts
 
104
  r"(?i)^UPDATE\s+[\w\d]+\s+SET\s+[\w\d\s=',]+(\s+WHERE\s+[\w\d\s=<>']+)?$",
105
  ]
106
 
107
+
108
  # Rule-based detection function
109
  def detect_sql_injection_with_regex(query):
 
 
 
 
 
110
  for pattern in SAFE_SQL_PATTERNS:
111
  if re.search(pattern, query.strip()):
 
112
  return False, None
 
 
113
  for pattern in SQL_INJECTION_PATTERNS:
114
  match = re.search(pattern, query)
115
  if match:
116
  return True, match.group(0)
 
 
117
  return False, None
118
 
119
  # Ensemble prediction function
120
  def predict_with_ensemble(query, components):
 
 
 
 
 
 
121
  # Random Forest prediction
122
  query_tfidf = preprocess_query_for_traditional_ml(query, components['tfidf_vectorizer'])
123
  rf_pred = int(components['rf_model'].predict(query_tfidf)[0])
 
124
  # SVM prediction
125
  svm_pred = int(components['svm_model'].predict(query_tfidf)[0])
 
126
  # CNN prediction
127
  query_padded = preprocess_query_for_deep_learning(query, components['tokenizer'], components['max_sequence_length'])
128
  cnn_probability = components['cnn_model'].predict(query_padded)[0][0]
129
  cnn_pred = int(cnn_probability > 0.5)
 
130
  # LSTM prediction
131
  lstm_probability = components['lstm_model'].predict(query_padded)[0][0]
132
  lstm_pred = int(lstm_probability > 0.5)
133
+ # Count votes
 
134
  votes = [rf_pred, svm_pred, cnn_pred, lstm_pred]
135
+ vote_count = {0: votes.count(0), 1: votes.count(1)}
 
136
  return {
137
  'rf': rf_pred,
138
  'svm': svm_pred,
139
  'cnn': {'prediction': cnn_pred, 'probability': float(cnn_probability)},
140
  'lstm': {'prediction': lstm_pred, 'probability': float(lstm_probability)},
141
+ 'vote_count': vote_count
 
142
  }
143
 
144
+ # Initialize session state
145
  if 'analysis_stage' not in st.session_state:
146
+ st.session_state.analysis_stage = 0
 
147
  if 'regex_result' not in st.session_state:
148
  st.session_state.regex_result = None
 
149
  if 'ensemble_result' not in st.session_state:
150
  st.session_state.ensemble_result = None
151
 
 
153
  st.title("🛡️ SQL Injection Detection")
154
  st.markdown("""
155
  This application uses a multi-layered approach to detect potentially malicious SQL queries:
156
+ 1. **Rule-based detection** using improved regex patterns.
157
  2. **Ensemble learning** with majority voting from 4 models:
158
  - Random Forest
159
  - Support Vector Machine
160
  - Convolutional Neural Network
161
+ - Long Short-Term Memory Network.
 
 
162
  """)
163
 
164
  # Display warning if models couldn't be loaded
 
166
  st.warning(f"⚠️ Some models could not be loaded. The application will only use rule-based detection. Error: {model_loading_error}")
167
 
168
  # Example queries in a dropdown
 
 
169
  example_categories = {
170
  "Benign SQL Queries": [
171
+ "SELECT * FROM users WHERE username='admin'",
172
+ "SELECT id, name, price FROM products WHERE category_id=5"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  ],
174
  "Malicious SQL Queries": [
175
+ "' OR 1=1 --",
176
+ "admin'; DROP TABLE users; --"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  ]
178
  }
179
 
180
+ category = st.selectbox("Choose query category:", options=list(example_categories.keys()))
181
+ example = st.selectbox("Select an example:", options=example_categories[category])
182
+ query_source = st.radio("Query source:", ["Use selected example", "Enter my own query"])
183
+ query = example if query_source == "Use selected example" else st.text_area("Enter SQL Query:", placeholder="Type your SQL query here...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
 
185
  # Analysis process
186
  if st.button("Start Analysis") and query:
 
187
  st.session_state.analysis_stage = 1
 
 
188
  with st.spinner("Running rule-based detection..."):
189
  time.sleep(0.5) # Simulate processing time
190
  is_malicious, matched_pattern = detect_sql_injection_with_regex(query)
191
  st.session_state.regex_result = (is_malicious, matched_pattern)
192
 
193
+ # Rule-based analysis results
194
  if st.session_state.analysis_stage >= 1 and st.session_state.regex_result is not None:
195
  is_malicious, matched_pattern = st.session_state.regex_result
196
  st.subheader("Step 1: Rule-Based Detection")
 
197
  if is_malicious:
198
  st.error("🚨 SQL Injection Detected (Rule-Based)!")
199
  st.warning(f"Matched pattern: `{matched_pattern}`")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  else:
201
  st.success("✅ No SQL injection patterns detected using rules")
202
+
203
+ proceed = st.radio("Proceed with ensemble detection?", ["Yes", "No"], index=0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  if proceed == "Yes" and not model_loading_error:
205
  if st.button("Run Ensemble Analysis"):
206
  st.session_state.analysis_stage = 2
 
208
  time.sleep(1) # Simulate processing time
209
  ensemble_results = predict_with_ensemble(query, components)
210
  st.session_state.ensemble_result = ensemble_results
 
 
211
 
212
+ # Ensemble analysis results
213
  if st.session_state.analysis_stage >= 2 and st.session_state.ensemble_result is not None:
214
  results = st.session_state.ensemble_result
 
215
  st.subheader("Step 2: Ensemble Model Detection")
216
+ vote_benign = results['vote_count'][0]
 
 
217
  vote_malicious = results['vote_count'][1]
218
+
219
+ # Create columns for voting visualization
 
 
220
  col1, col2 = st.columns(2)
 
221
  with col1:
222
  st.metric("Safe Votes", vote_benign)
 
223
  with col2:
224
  st.metric("Malicious Votes", vote_malicious)
225
+
226
+ # Progress bar for malicious ratio
227
  vote_ratio = vote_malicious / (vote_benign + vote_malicious)
228
  st.progress(vote_ratio, text=f"Malicious vote ratio: {vote_ratio*100:.0f}%")
229
+
230
+ # Individual model results
231
  st.markdown("### Individual Model Results")
 
232
  model_cols = st.columns(4)
 
233
  with model_cols[0]:
234
  st.markdown("**Random Forest**")
235
+ st.error("⚠️ Malicious") if results['rf'] == 1 else st.success("✅ Safe")
 
 
 
 
236
  with model_cols[1]:
237
  st.markdown("**SVM**")
238
+ st.error("⚠️ Malicious") if results['svm'] == 1 else st.success("✅ Safe")
 
 
 
 
239
  with model_cols[2]:
240
  st.markdown("**CNN**")
241
  cnn_prob = results['cnn']['probability'] * 100
242
+ st.error(f"⚠️ Malicious ({cnn_prob:.1f}%)") if results['cnn']['prediction'] == 1 else st.success(f"✅ Safe ({100-cnn_prob:.1f}%)")
 
 
 
 
243
  with model_cols[3]:
244
  st.markdown("**LSTM**")
245
  lstm_prob = results['lstm']['probability'] * 100
246
+ st.error(f"⚠️ Malicious ({lstm_prob:.1f}%)") if results['lstm']['prediction'] == 1 else st.success(f"✅ Safe ({100-lstm_prob:.1f}%)")
247
+
 
 
 
248
  # Final ensemble verdict
249
  st.markdown("### Ensemble Verdict")
250
+ if vote_benign > 3:
251
+ st.success(" Query deemed safe by majority vote (>3 safe votes)")
252
+ elif vote_malicious > 3:
253
+ st.error("🚨 SQL Injection Detected by Majority Vote (>3 malicious votes)")
254
  else:
255
+ st.warning("⚠️ Ambiguous result: Votes split (≤3 each). Please cross-check manually.")
256
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  # Final verdict combining both approaches
258
  st.subheader("Final Analysis")
 
259
  is_malicious_regex, _ = st.session_state.regex_result
260
+ is_malicious_ensemble = vote_malicious > 3
 
261
  if is_malicious_regex or is_malicious_ensemble:
262
+ st.error("⚠️ This query appears malicious. Review immediately!")
263
+ elif vote_benign > 3:
264
+ st.success("✅ Query appears safe based on multi-layer analysis")
265
  else:
266
+ st.warning("⚠️ Ambiguous result - manual verification required")
267
+
 
 
268
  # Reset button
269
  if st.button("Analyze Another Query"):
270
  st.session_state.analysis_stage = 0