Download tools/sql_syntax_reviewer.py from lablab-ai-amd-developer-hackathon/Threat_Hunter: direct link, hf CLI and curl.
- Browser
- Download file 4.62 kB
-
https://huggingface.co/spaces/lablab-ai-amd-developer-hackathon/Threat_Hunter/resolve/main/tools/sql_syntax_reviewer.py
- Command line
-
hf download hf://spaces/lablab-ai-amd-developer-hackathon/Threat_Hunter/tools/sql_syntax_reviewer.py
-
curl -L -o sql_syntax_reviewer.py https://huggingface.co/spaces/lablab-ai-amd-developer-hackathon/Threat_Hunter/resolve/main/tools/sql_syntax_reviewer.py
4.62 kB
| """SQL 語法風險審查器。 | |
| 此工具只審查孤立 SQL corpus 裡的危險語法與測試 payload。 | |
| 它不宣稱已驗證應用程式漏洞,因為缺少 application source/sink context。 | |
| """ | |
| from __future__ import annotations | |
| import re | |
| from dataclasses import dataclass | |
| from typing import Any | |
| class SqlPatternSpec: | |
| """SQL review pattern 的固定規格。""" | |
| syntax_pattern: str | |
| category: str | |
| regex: re.Pattern[str] | |
| risk_note: str | |
| SQL_REVIEW_PATTERNS: tuple[SqlPatternSpec, ...] = ( | |
| SqlPatternSpec( | |
| syntax_pattern="boolean_blind", | |
| category="sql_injection_payload", | |
| regex=re.compile(r"(?i)(?:\bOR\b|\bAND\b)\s+(?:1\s*=\s*1|'1'\s*=\s*'1')"), | |
| risk_note="Boolean-based SQL injection payload. Requires application input-flow context.", | |
| ), | |
| SqlPatternSpec( | |
| syntax_pattern="union_select", | |
| category="sql_injection_payload", | |
| regex=re.compile(r"(?i)\bUNION\s+(?:ALL\s+)?SELECT\b"), | |
| risk_note="UNION-based SQL injection payload. Requires application input-flow context.", | |
| ), | |
| SqlPatternSpec( | |
| syntax_pattern="time_based", | |
| category="sql_injection_payload", | |
| regex=re.compile(r"(?i)\b(?:SLEEP\s*\(|BENCHMARK\s*\(|WAITFOR\s+DELAY|pg_sleep\s*\()"), | |
| risk_note="Time-based SQL injection payload. Requires runtime and database context.", | |
| ), | |
| SqlPatternSpec( | |
| syntax_pattern="error_based", | |
| category="sql_injection_payload", | |
| regex=re.compile(r"(?i)\b(?:EXTRACTVALUE\s*\(|UPDATEXML\s*\(|CONVERT\s*\(|CAST\s*\()"), | |
| risk_note="Error-based SQL injection payload. Requires database error exposure context.", | |
| ), | |
| SqlPatternSpec( | |
| syntax_pattern="stacked_query", | |
| category="dangerous_sql_syntax", | |
| regex=re.compile(r"(?i);\s*(?:DROP|EXEC|CREATE\s+USER|GRANT\s+ALL|ALTER|TRUNCATE|DELETE)\b"), | |
| risk_note="Stacked query or destructive statement pattern. Requires execution context.", | |
| ), | |
| SqlPatternSpec( | |
| syntax_pattern="dynamic_sql", | |
| category="dangerous_sql_syntax", | |
| regex=re.compile(r"(?i)(?:\bEXEC\s*\(@?\w+\)|\bsp_executesql\b|\bEXECUTE\s+IMMEDIATE\b|\bPREPARE\s+\w+\s+FROM\b)"), | |
| risk_note="Dynamic SQL execution pattern. Requires parameterization and source context.", | |
| ), | |
| SqlPatternSpec( | |
| syntax_pattern="nosql_payload", | |
| category="nosql_injection_payload", | |
| regex=re.compile(r"(?i)(?:['\"]?\$(?:gt|gte|lt|lte|ne|in|nin|regex|where)['\"]?\s*:|\$where\b)"), | |
| risk_note="NoSQL-style injection payload. Requires datastore and request parsing context.", | |
| ), | |
| ) | |
| def _line_no(text: str, offset: int) -> int: | |
| """依字元 offset 計算 1-based 行號。""" | |
| return text[:offset].count("\n") + 1 | |
| def _snippet(value: str, limit: int = 160) -> str: | |
| """回傳短 snippet,避免 review output 過長。""" | |
| compact = " ".join(value.strip().split()) | |
| return compact[:limit] | |
| def review_sql_syntax(sql_text: str) -> dict[str, Any]: | |
| """ | |
| 審查 SQL corpus 中的危險語法與 injection payload。 | |
| Returns: | |
| `sql_syntax_review` 契約;所有 finding 都標示 | |
| `requires_application_context=true`,避免被下游包裝成 verified CWE。 | |
| """ | |
| if not isinstance(sql_text, str): | |
| sql_text = str(sql_text) | |
| findings: list[dict[str, Any]] = [] | |
| seen: set[tuple[str, int, str]] = set() | |
| for spec in SQL_REVIEW_PATTERNS: | |
| for match in spec.regex.finditer(sql_text): | |
| line_no = _line_no(sql_text, match.start()) | |
| snippet = _snippet(match.group(0)) | |
| key = (spec.syntax_pattern, line_no, snippet) | |
| if key in seen: | |
| continue | |
| seen.add(key) | |
| findings.append({ | |
| "syntax_pattern": spec.syntax_pattern, | |
| "line_no": line_no, | |
| "category": spec.category, | |
| "snippet": snippet, | |
| "risk_note": spec.risk_note, | |
| "requires_application_context": True, | |
| }) | |
| categories = sorted({item["syntax_pattern"] for item in findings}) | |
| return { | |
| "review_status": "completed", | |
| "review_type": "sql_syntax_review", | |
| "requires_application_context": True, | |
| "verified_application_vulnerability": False, | |
| "code_scan_excluded": True, | |
| "package_scan_allowed": False, | |
| "patterns": findings, | |
| "summary": { | |
| "total": len(findings), | |
| "patterns_detected": len(categories), | |
| "syntax_patterns": categories, | |
| }, | |
| } | |