update
Browse files
app.py
CHANGED
|
@@ -361,6 +361,23 @@ def enrich_ioc(ioc, ioc_type):
|
|
| 361 |
f"Targeted countries: {', '.join(otx.get('countries', [])) or 'not specified'}")
|
| 362 |
|
| 363 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 364 |
# --- bundled retrieval -----------------------------------------------------------
|
| 365 |
IOC_RE = re.compile(r"hxxp|https?://|\b\d{1,3}\[?\.\]?\d{1,3}\[?\.\]?\d{1,3}\[?\.\]?\d{1,3}\b|\b[a-f0-9]{32,64}\b", re.I)
|
| 366 |
ACTOR_KW = re.compile(r"\b(actor|group|apt|adversary|profile|who is|what did|techniques does|ttps|campaign)\b", re.I)
|
|
@@ -481,8 +498,7 @@ SUGGESTIONS = {
|
|
| 481 |
"π οΈ Who uses Cobalt Strike?": "Which threat actors use the Cobalt Strike tool?",
|
| 482 |
"π Explain technique T1059.001": "Explain MITRE ATT&CK technique T1059.001",
|
| 483 |
"π Assess CVE-2025-0282 (live)": "Assess CVE-2025-0282 for offensive relevance",
|
| 484 |
-
"π Look up a live IOC":
|
| 485 |
-
"27.204.192.167 and assess its red team relevance."),
|
| 486 |
}
|
| 487 |
|
| 488 |
if "messages" not in st.session_state:
|
|
@@ -490,11 +506,17 @@ if "messages" not in st.session_state:
|
|
| 490 |
|
| 491 |
clicked = None
|
| 492 |
if not st.session_state.messages:
|
| 493 |
-
st.markdown("##### Try one of these π")
|
| 494 |
cols = st.columns(2)
|
| 495 |
for i, (label, text) in enumerate(SUGGESTIONS.items()):
|
| 496 |
if cols[i % 2].button(label, use_container_width=True):
|
| 497 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 498 |
|
| 499 |
for msg in st.session_state.messages:
|
| 500 |
with st.chat_message(msg["role"], avatar=ROBOT if msg["role"] == "assistant" else None):
|
|
|
|
| 361 |
f"Targeted countries: {', '.join(otx.get('countries', [])) or 'not specified'}")
|
| 362 |
|
| 363 |
|
| 364 |
+
def recent_threatfox_ioc():
|
| 365 |
+
"""A random *current* abuse.ch ThreatFox IP indicator, so the demo chip hits live data."""
|
| 366 |
+
key = _env(*ABUSE_KEYS)
|
| 367 |
+
if not key:
|
| 368 |
+
return None
|
| 369 |
+
body = json.dumps({"query": "get_iocs", "days": 1}).encode()
|
| 370 |
+
req = urllib.request.Request("https://threatfox-api.abuse.ch/api/v1/", data=body,
|
| 371 |
+
headers={"Auth-Key": key, "Content-Type": "application/json", "User-Agent": "TextScout-demo"})
|
| 372 |
+
d = json.loads(urllib.request.urlopen(req, timeout=15).read())
|
| 373 |
+
rows = d.get("data") if d.get("query_status") == "ok" else None
|
| 374 |
+
if not isinstance(rows, list) or not rows:
|
| 375 |
+
return None
|
| 376 |
+
import random
|
| 377 |
+
pool = [r for r in rows if r.get("ioc_type") == "ip:port"] or rows
|
| 378 |
+
return random.choice(pool).get("ioc", "").split(":")[0]
|
| 379 |
+
|
| 380 |
+
|
| 381 |
# --- bundled retrieval -----------------------------------------------------------
|
| 382 |
IOC_RE = re.compile(r"hxxp|https?://|\b\d{1,3}\[?\.\]?\d{1,3}\[?\.\]?\d{1,3}\[?\.\]?\d{1,3}\b|\b[a-f0-9]{32,64}\b", re.I)
|
| 383 |
ACTOR_KW = re.compile(r"\b(actor|group|apt|adversary|profile|who is|what did|techniques does|ttps|campaign)\b", re.I)
|
|
|
|
| 498 |
"π οΈ Who uses Cobalt Strike?": "Which threat actors use the Cobalt Strike tool?",
|
| 499 |
"π Explain technique T1059.001": "Explain MITRE ATT&CK technique T1059.001",
|
| 500 |
"π Assess CVE-2025-0282 (live)": "Assess CVE-2025-0282 for offensive relevance",
|
| 501 |
+
"π Look up a fresh live IOC": None, # None -> pull a current abuse.ch IOC at click time
|
|
|
|
| 502 |
}
|
| 503 |
|
| 504 |
if "messages" not in st.session_state:
|
|
|
|
| 506 |
|
| 507 |
clicked = None
|
| 508 |
if not st.session_state.messages:
|
| 509 |
+
st.markdown("##### Try one of these π Β· or type your own actor / CVE / IP / hash below")
|
| 510 |
cols = st.columns(2)
|
| 511 |
for i, (label, text) in enumerate(SUGGESTIONS.items()):
|
| 512 |
if cols[i % 2].button(label, use_container_width=True):
|
| 513 |
+
if text is None: # live IOC chip: grab a current indicator
|
| 514 |
+
ioc = _safe(recent_threatfox_ioc)
|
| 515 |
+
clicked = (f"Look up live threat intelligence for the indicator {ioc} "
|
| 516 |
+
"and assess its red team relevance." if ioc else
|
| 517 |
+
"Look up live threat intelligence for the indicator 1.1.1.1.")
|
| 518 |
+
else:
|
| 519 |
+
clicked = text
|
| 520 |
|
| 521 |
for msg in st.session_state.messages:
|
| 522 |
with st.chat_message(msg["role"], avatar=ROBOT if msg["role"] == "assistant" else None):
|