suite des maj

This commit is contained in:
SOC Analyst
2026-03-18 09:00:47 +01:00
parent 446d3623ec
commit 32a96966dd
17 changed files with 2398 additions and 755 deletions

View File

@ -104,40 +104,40 @@ async def get_ip_ja4_history(ip: str):
@router.get("/sophistication")
async def get_sophistication(limit: int = Query(50, ge=1, le=500)):
"""Score de sophistication adversaire par IP (rotation JA4 + récurrence + bruteforce)."""
"""Score de sophistication adversaire par IP (rotation JA4 + récurrence + bruteforce).
Single SQL JOIN query — aucun traitement Python sur 34K entrées.
"""
try:
# Separate queries merged in Python to avoid view JOIN issues
rot_result = db.query("""
SELECT
replaceRegexpAll(toString(src_ip), '^::ffff:', '') AS ip,
distinct_ja4_count
FROM mabase_prod.view_host_ip_ja4_rotation
""")
rotation_map = {str(row[0]): int(row[1]) for row in rot_result.result_rows}
rec_result = db.query("""
SELECT
replaceRegexpAll(toString(src_ip), '^::ffff:', '') AS ip,
recurrence
FROM mabase_prod.view_ip_recurrence
""")
recurrence_map = {str(row[0]): int(row[1]) for row in rec_result.result_rows}
bf_result = db.query("""
SELECT
replaceRegexpAll(toString(src_ip), '^::ffff:', '') AS ip,
sum(hits) AS total_hits
sql = """
SELECT
replaceRegexpAll(toString(r.src_ip), '^::ffff:', '') AS ip,
r.distinct_ja4_count,
coalesce(rec.recurrence, 0) AS recurrence,
coalesce(bf.bruteforce_hits, 0) AS bruteforce_hits,
round(least(100.0,
r.distinct_ja4_count * 10
+ coalesce(rec.recurrence, 0) * 20
+ least(30.0, log(coalesce(bf.bruteforce_hits, 0) + 1) * 5)
), 1) AS sophistication_score
FROM mabase_prod.view_host_ip_ja4_rotation r
LEFT JOIN (
SELECT src_ip, count() AS recurrence
FROM mabase_prod.ml_detected_anomalies FINAL
GROUP BY src_ip
) rec USING(src_ip)
LEFT JOIN (
SELECT replaceRegexpAll(toString(src_ip),'^::ffff:','') AS src_ip,
sum(hits) AS bruteforce_hits
FROM mabase_prod.view_form_bruteforce_detected
GROUP BY ip
""")
bruteforce_map = {str(row[0]): int(row[1]) for row in bf_result.result_rows}
# Start from IPs that appear in rotation view (most evasive)
GROUP BY src_ip
) bf USING(src_ip)
ORDER BY sophistication_score DESC
LIMIT %(limit)s
"""
result = db.query(sql, {"limit": limit})
items = []
for ip, ja4_count in rotation_map.items():
recurrence = recurrence_map.get(ip, 0)
bf_hits = bruteforce_map.get(ip, 0)
score = min(100.0, ja4_count * 10 + recurrence * 20 + min(30.0, math.log(bf_hits + 1) * 5))
for row in result.result_rows:
score = float(row[4] or 0)
if score > 80:
tier = "APT-like"
elif score > 50:
@ -147,16 +147,13 @@ async def get_sophistication(limit: int = Query(50, ge=1, le=500)):
else:
tier = "Basic"
items.append({
"ip": ip,
"ja4_rotation_count": ja4_count,
"recurrence": recurrence,
"bruteforce_hits": bf_hits,
"sophistication_score": round(score, 1),
"tier": tier,
"ip": str(row[0]),
"ja4_rotation_count": int(row[1] or 0),
"recurrence": int(row[2] or 0),
"bruteforce_hits": int(row[3] or 0),
"sophistication_score":score,
"tier": tier,
})
items.sort(key=lambda x: x["sophistication_score"], reverse=True)
items = items[:limit]
return {"items": items, "total": len(items)}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))