aiptx 2.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of aiptx might be problematic. Click here for more details.
- aipt_v2/__init__.py +110 -0
- aipt_v2/__main__.py +24 -0
- aipt_v2/agents/AIPTxAgent/__init__.py +10 -0
- aipt_v2/agents/AIPTxAgent/aiptx_agent.py +211 -0
- aipt_v2/agents/__init__.py +24 -0
- aipt_v2/agents/base.py +520 -0
- aipt_v2/agents/ptt.py +406 -0
- aipt_v2/agents/state.py +168 -0
- aipt_v2/app.py +960 -0
- aipt_v2/browser/__init__.py +31 -0
- aipt_v2/browser/automation.py +458 -0
- aipt_v2/browser/crawler.py +453 -0
- aipt_v2/cli.py +321 -0
- aipt_v2/compliance/__init__.py +71 -0
- aipt_v2/compliance/compliance_report.py +449 -0
- aipt_v2/compliance/framework_mapper.py +424 -0
- aipt_v2/compliance/nist_mapping.py +345 -0
- aipt_v2/compliance/owasp_mapping.py +330 -0
- aipt_v2/compliance/pci_mapping.py +297 -0
- aipt_v2/config.py +288 -0
- aipt_v2/core/__init__.py +43 -0
- aipt_v2/core/agent.py +630 -0
- aipt_v2/core/llm.py +395 -0
- aipt_v2/core/memory.py +305 -0
- aipt_v2/core/ptt.py +329 -0
- aipt_v2/database/__init__.py +14 -0
- aipt_v2/database/models.py +232 -0
- aipt_v2/database/repository.py +384 -0
- aipt_v2/docker/__init__.py +23 -0
- aipt_v2/docker/builder.py +260 -0
- aipt_v2/docker/manager.py +222 -0
- aipt_v2/docker/sandbox.py +371 -0
- aipt_v2/evasion/__init__.py +58 -0
- aipt_v2/evasion/request_obfuscator.py +272 -0
- aipt_v2/evasion/tls_fingerprint.py +285 -0
- aipt_v2/evasion/ua_rotator.py +301 -0
- aipt_v2/evasion/waf_bypass.py +439 -0
- aipt_v2/execution/__init__.py +23 -0
- aipt_v2/execution/executor.py +302 -0
- aipt_v2/execution/parser.py +544 -0
- aipt_v2/execution/terminal.py +337 -0
- aipt_v2/health.py +437 -0
- aipt_v2/intelligence/__init__.py +85 -0
- aipt_v2/intelligence/auth.py +520 -0
- aipt_v2/intelligence/chaining.py +775 -0
- aipt_v2/intelligence/cve_aipt.py +334 -0
- aipt_v2/intelligence/cve_info.py +1111 -0
- aipt_v2/intelligence/rag.py +239 -0
- aipt_v2/intelligence/scope.py +442 -0
- aipt_v2/intelligence/searchers/__init__.py +5 -0
- aipt_v2/intelligence/searchers/exploitdb_searcher.py +523 -0
- aipt_v2/intelligence/searchers/github_searcher.py +467 -0
- aipt_v2/intelligence/searchers/google_searcher.py +281 -0
- aipt_v2/intelligence/tools.json +443 -0
- aipt_v2/intelligence/triage.py +670 -0
- aipt_v2/interface/__init__.py +5 -0
- aipt_v2/interface/cli.py +230 -0
- aipt_v2/interface/main.py +501 -0
- aipt_v2/interface/tui.py +1276 -0
- aipt_v2/interface/utils.py +583 -0
- aipt_v2/llm/__init__.py +39 -0
- aipt_v2/llm/config.py +26 -0
- aipt_v2/llm/llm.py +514 -0
- aipt_v2/llm/memory.py +214 -0
- aipt_v2/llm/request_queue.py +89 -0
- aipt_v2/llm/utils.py +89 -0
- aipt_v2/models/__init__.py +15 -0
- aipt_v2/models/findings.py +295 -0
- aipt_v2/models/phase_result.py +224 -0
- aipt_v2/models/scan_config.py +207 -0
- aipt_v2/monitoring/grafana/dashboards/aipt-dashboard.json +355 -0
- aipt_v2/monitoring/grafana/dashboards/default.yml +17 -0
- aipt_v2/monitoring/grafana/datasources/prometheus.yml +17 -0
- aipt_v2/monitoring/prometheus.yml +60 -0
- aipt_v2/orchestration/__init__.py +52 -0
- aipt_v2/orchestration/pipeline.py +398 -0
- aipt_v2/orchestration/progress.py +300 -0
- aipt_v2/orchestration/scheduler.py +296 -0
- aipt_v2/orchestrator.py +2284 -0
- aipt_v2/payloads/__init__.py +27 -0
- aipt_v2/payloads/cmdi.py +150 -0
- aipt_v2/payloads/sqli.py +263 -0
- aipt_v2/payloads/ssrf.py +204 -0
- aipt_v2/payloads/templates.py +222 -0
- aipt_v2/payloads/traversal.py +166 -0
- aipt_v2/payloads/xss.py +204 -0
- aipt_v2/prompts/__init__.py +60 -0
- aipt_v2/proxy/__init__.py +29 -0
- aipt_v2/proxy/history.py +352 -0
- aipt_v2/proxy/interceptor.py +452 -0
- aipt_v2/recon/__init__.py +44 -0
- aipt_v2/recon/dns.py +241 -0
- aipt_v2/recon/osint.py +367 -0
- aipt_v2/recon/subdomain.py +372 -0
- aipt_v2/recon/tech_detect.py +311 -0
- aipt_v2/reports/__init__.py +17 -0
- aipt_v2/reports/generator.py +313 -0
- aipt_v2/reports/html_report.py +378 -0
- aipt_v2/runtime/__init__.py +44 -0
- aipt_v2/runtime/base.py +30 -0
- aipt_v2/runtime/docker.py +401 -0
- aipt_v2/runtime/local.py +346 -0
- aipt_v2/runtime/tool_server.py +205 -0
- aipt_v2/scanners/__init__.py +28 -0
- aipt_v2/scanners/base.py +273 -0
- aipt_v2/scanners/nikto.py +244 -0
- aipt_v2/scanners/nmap.py +402 -0
- aipt_v2/scanners/nuclei.py +273 -0
- aipt_v2/scanners/web.py +454 -0
- aipt_v2/scripts/security_audit.py +366 -0
- aipt_v2/telemetry/__init__.py +7 -0
- aipt_v2/telemetry/tracer.py +347 -0
- aipt_v2/terminal/__init__.py +28 -0
- aipt_v2/terminal/executor.py +400 -0
- aipt_v2/terminal/sandbox.py +350 -0
- aipt_v2/tools/__init__.py +44 -0
- aipt_v2/tools/active_directory/__init__.py +78 -0
- aipt_v2/tools/active_directory/ad_config.py +238 -0
- aipt_v2/tools/active_directory/bloodhound_wrapper.py +447 -0
- aipt_v2/tools/active_directory/kerberos_attacks.py +430 -0
- aipt_v2/tools/active_directory/ldap_enum.py +533 -0
- aipt_v2/tools/active_directory/smb_attacks.py +505 -0
- aipt_v2/tools/agents_graph/__init__.py +19 -0
- aipt_v2/tools/agents_graph/agents_graph_actions.py +69 -0
- aipt_v2/tools/api_security/__init__.py +76 -0
- aipt_v2/tools/api_security/api_discovery.py +608 -0
- aipt_v2/tools/api_security/graphql_scanner.py +622 -0
- aipt_v2/tools/api_security/jwt_analyzer.py +577 -0
- aipt_v2/tools/api_security/openapi_fuzzer.py +761 -0
- aipt_v2/tools/browser/__init__.py +5 -0
- aipt_v2/tools/browser/browser_actions.py +238 -0
- aipt_v2/tools/browser/browser_instance.py +535 -0
- aipt_v2/tools/browser/tab_manager.py +344 -0
- aipt_v2/tools/cloud/__init__.py +70 -0
- aipt_v2/tools/cloud/cloud_config.py +273 -0
- aipt_v2/tools/cloud/cloud_scanner.py +639 -0
- aipt_v2/tools/cloud/prowler_tool.py +571 -0
- aipt_v2/tools/cloud/scoutsuite_tool.py +359 -0
- aipt_v2/tools/executor.py +307 -0
- aipt_v2/tools/parser.py +408 -0
- aipt_v2/tools/proxy/__init__.py +5 -0
- aipt_v2/tools/proxy/proxy_actions.py +103 -0
- aipt_v2/tools/proxy/proxy_manager.py +789 -0
- aipt_v2/tools/registry.py +196 -0
- aipt_v2/tools/scanners/__init__.py +343 -0
- aipt_v2/tools/scanners/acunetix_tool.py +712 -0
- aipt_v2/tools/scanners/burp_tool.py +631 -0
- aipt_v2/tools/scanners/config.py +156 -0
- aipt_v2/tools/scanners/nessus_tool.py +588 -0
- aipt_v2/tools/scanners/zap_tool.py +612 -0
- aipt_v2/tools/terminal/__init__.py +5 -0
- aipt_v2/tools/terminal/terminal_actions.py +37 -0
- aipt_v2/tools/terminal/terminal_manager.py +153 -0
- aipt_v2/tools/terminal/terminal_session.py +449 -0
- aipt_v2/tools/tool_processing.py +108 -0
- aipt_v2/utils/__init__.py +17 -0
- aipt_v2/utils/logging.py +201 -0
- aipt_v2/utils/model_manager.py +187 -0
- aipt_v2/utils/searchers/__init__.py +269 -0
- aiptx-2.0.2.dist-info/METADATA +324 -0
- aiptx-2.0.2.dist-info/RECORD +165 -0
- aiptx-2.0.2.dist-info/WHEEL +5 -0
- aiptx-2.0.2.dist-info/entry_points.txt +7 -0
- aiptx-2.0.2.dist-info/licenses/LICENSE +21 -0
- aiptx-2.0.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from functools import wraps
|
|
6
|
+
from inspect import signature
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
tools: list[dict[str, Any]] = []
|
|
12
|
+
_tools_by_name: dict[str, Callable[..., Any]] = {}
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ImplementedInClientSideOnlyError(Exception):
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
message: str = "This tool is implemented in the client side only",
|
|
20
|
+
) -> None:
|
|
21
|
+
self.message = message
|
|
22
|
+
super().__init__(self.message)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _process_dynamic_content(content: str) -> str:
|
|
26
|
+
if "{{DYNAMIC_MODULES_DESCRIPTION}}" in content:
|
|
27
|
+
try:
|
|
28
|
+
from prompts import generate_modules_description
|
|
29
|
+
|
|
30
|
+
modules_description = generate_modules_description()
|
|
31
|
+
content = content.replace("{{DYNAMIC_MODULES_DESCRIPTION}}", modules_description)
|
|
32
|
+
except ImportError:
|
|
33
|
+
logger.warning("Could not import prompts utilities for dynamic schema generation")
|
|
34
|
+
content = content.replace(
|
|
35
|
+
"{{DYNAMIC_MODULES_DESCRIPTION}}",
|
|
36
|
+
"List of prompt modules to load for this agent (max 5). Module discovery failed.",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
return content
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _load_xml_schema(path: Path) -> Any:
|
|
43
|
+
if not path.exists():
|
|
44
|
+
return None
|
|
45
|
+
try:
|
|
46
|
+
content = path.read_text()
|
|
47
|
+
|
|
48
|
+
content = _process_dynamic_content(content)
|
|
49
|
+
|
|
50
|
+
start_tag = '<tool name="'
|
|
51
|
+
end_tag = "</tool>"
|
|
52
|
+
tools_dict = {}
|
|
53
|
+
|
|
54
|
+
pos = 0
|
|
55
|
+
while True:
|
|
56
|
+
start_pos = content.find(start_tag, pos)
|
|
57
|
+
if start_pos == -1:
|
|
58
|
+
break
|
|
59
|
+
|
|
60
|
+
name_start = start_pos + len(start_tag)
|
|
61
|
+
name_end = content.find('"', name_start)
|
|
62
|
+
if name_end == -1:
|
|
63
|
+
break
|
|
64
|
+
tool_name = content[name_start:name_end]
|
|
65
|
+
|
|
66
|
+
end_pos = content.find(end_tag, name_end)
|
|
67
|
+
if end_pos == -1:
|
|
68
|
+
break
|
|
69
|
+
end_pos += len(end_tag)
|
|
70
|
+
|
|
71
|
+
tool_element = content[start_pos:end_pos]
|
|
72
|
+
tools_dict[tool_name] = tool_element
|
|
73
|
+
|
|
74
|
+
pos = end_pos
|
|
75
|
+
|
|
76
|
+
if pos >= len(content):
|
|
77
|
+
break
|
|
78
|
+
except (IndexError, ValueError, UnicodeError) as e:
|
|
79
|
+
logger.warning(f"Error loading schema file {path}: {e}")
|
|
80
|
+
return None
|
|
81
|
+
else:
|
|
82
|
+
return tools_dict
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _get_module_name(func: Callable[..., Any]) -> str:
|
|
86
|
+
module = inspect.getmodule(func)
|
|
87
|
+
if not module:
|
|
88
|
+
return "unknown"
|
|
89
|
+
|
|
90
|
+
module_name = module.__name__
|
|
91
|
+
if ".tools." in module_name:
|
|
92
|
+
parts = module_name.split(".tools.")[-1].split(".")
|
|
93
|
+
if len(parts) >= 1:
|
|
94
|
+
return parts[0]
|
|
95
|
+
return "unknown"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def register_tool(
|
|
99
|
+
func: Callable[..., Any] | None = None, *, sandbox_execution: bool = True
|
|
100
|
+
) -> Callable[..., Any]:
|
|
101
|
+
def decorator(f: Callable[..., Any]) -> Callable[..., Any]:
|
|
102
|
+
func_dict = {
|
|
103
|
+
"name": f.__name__,
|
|
104
|
+
"function": f,
|
|
105
|
+
"module": _get_module_name(f),
|
|
106
|
+
"sandbox_execution": sandbox_execution,
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
sandbox_mode = os.getenv("AIPT_SANDBOX_MODE", "false").lower() == "true"
|
|
110
|
+
if not sandbox_mode:
|
|
111
|
+
try:
|
|
112
|
+
module_path = Path(inspect.getfile(f))
|
|
113
|
+
schema_file_name = f"{module_path.stem}_schema.xml"
|
|
114
|
+
schema_path = module_path.parent / schema_file_name
|
|
115
|
+
|
|
116
|
+
xml_tools = _load_xml_schema(schema_path)
|
|
117
|
+
|
|
118
|
+
if xml_tools is not None and f.__name__ in xml_tools:
|
|
119
|
+
func_dict["xml_schema"] = xml_tools[f.__name__]
|
|
120
|
+
else:
|
|
121
|
+
func_dict["xml_schema"] = (
|
|
122
|
+
f'<tool name="{f.__name__}">'
|
|
123
|
+
"<description>Schema not found for tool.</description>"
|
|
124
|
+
"</tool>"
|
|
125
|
+
)
|
|
126
|
+
except (TypeError, FileNotFoundError) as e:
|
|
127
|
+
logger.warning(f"Error loading schema for {f.__name__}: {e}")
|
|
128
|
+
func_dict["xml_schema"] = (
|
|
129
|
+
f'<tool name="{f.__name__}">'
|
|
130
|
+
"<description>Error loading schema.</description>"
|
|
131
|
+
"</tool>"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
tools.append(func_dict)
|
|
135
|
+
_tools_by_name[str(func_dict["name"])] = f
|
|
136
|
+
|
|
137
|
+
@wraps(f)
|
|
138
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
139
|
+
return f(*args, **kwargs)
|
|
140
|
+
|
|
141
|
+
return wrapper
|
|
142
|
+
|
|
143
|
+
if func is None:
|
|
144
|
+
return decorator
|
|
145
|
+
return decorator(func)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def get_tool_by_name(name: str) -> Callable[..., Any] | None:
|
|
149
|
+
return _tools_by_name.get(name)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def get_tool_names() -> list[str]:
|
|
153
|
+
return list(_tools_by_name.keys())
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def needs_agent_state(tool_name: str) -> bool:
|
|
157
|
+
tool_func = get_tool_by_name(tool_name)
|
|
158
|
+
if not tool_func:
|
|
159
|
+
return False
|
|
160
|
+
sig = signature(tool_func)
|
|
161
|
+
return "agent_state" in sig.parameters
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def should_execute_in_sandbox(tool_name: str) -> bool:
|
|
165
|
+
for tool in tools:
|
|
166
|
+
if tool.get("name") == tool_name:
|
|
167
|
+
return bool(tool.get("sandbox_execution", True))
|
|
168
|
+
return True
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def get_tools_prompt() -> str:
|
|
172
|
+
tools_by_module: dict[str, list[dict[str, Any]]] = {}
|
|
173
|
+
for tool in tools:
|
|
174
|
+
module = tool.get("module", "unknown")
|
|
175
|
+
if module not in tools_by_module:
|
|
176
|
+
tools_by_module[module] = []
|
|
177
|
+
tools_by_module[module].append(tool)
|
|
178
|
+
|
|
179
|
+
xml_sections = []
|
|
180
|
+
for module, module_tools in sorted(tools_by_module.items()):
|
|
181
|
+
tag_name = f"{module}_tools"
|
|
182
|
+
section_parts = [f"<{tag_name}>"]
|
|
183
|
+
for tool in module_tools:
|
|
184
|
+
tool_xml = tool.get("xml_schema", "")
|
|
185
|
+
if tool_xml:
|
|
186
|
+
indented_tool = "\n".join(f" {line}" for line in tool_xml.split("\n"))
|
|
187
|
+
section_parts.append(indented_tool)
|
|
188
|
+
section_parts.append(f"</{tag_name}>")
|
|
189
|
+
xml_sections.append("\n".join(section_parts))
|
|
190
|
+
|
|
191
|
+
return "\n\n".join(xml_sections)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def clear_registry() -> None:
|
|
195
|
+
tools.clear()
|
|
196
|
+
_tools_by_name.clear()
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AIPT Scanner Tools - External Scanner Integrations
|
|
3
|
+
|
|
4
|
+
Provides plug-and-play integrations with enterprise security scanners:
|
|
5
|
+
- Acunetix Web Vulnerability Scanner
|
|
6
|
+
- Burp Suite Pro/Enterprise
|
|
7
|
+
- Nessus Professional/Expert (Network Vulnerability Scanner)
|
|
8
|
+
- OWASP ZAP (Dynamic Application Security Testing)
|
|
9
|
+
|
|
10
|
+
Server Configuration:
|
|
11
|
+
Public IP: 13.127.28.41
|
|
12
|
+
Acunetix: https://13.127.28.41:3443
|
|
13
|
+
Burp Suite: http://13.127.28.41:1337
|
|
14
|
+
Nessus: https://your-nessus-server:8834
|
|
15
|
+
ZAP: http://localhost:8080
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
# Configuration
|
|
19
|
+
from aipt_v2.tools.scanners.config import (
|
|
20
|
+
SCANNER_SERVER_IP,
|
|
21
|
+
ACUNETIX_PORT,
|
|
22
|
+
BURP_PORT,
|
|
23
|
+
ACUNETIX_URL,
|
|
24
|
+
BURP_URL,
|
|
25
|
+
ACUNETIX,
|
|
26
|
+
BURP,
|
|
27
|
+
SCANNER,
|
|
28
|
+
AcunetixSettings,
|
|
29
|
+
BurpSettings,
|
|
30
|
+
ScannerSettings,
|
|
31
|
+
get_acunetix_config,
|
|
32
|
+
get_burp_config,
|
|
33
|
+
print_config,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Acunetix Integration
|
|
37
|
+
from aipt_v2.tools.scanners.acunetix_tool import (
|
|
38
|
+
AcunetixTool,
|
|
39
|
+
AcunetixConfig,
|
|
40
|
+
ScanProfile,
|
|
41
|
+
ScanStatus as AcunetixScanStatus,
|
|
42
|
+
ScanResult as AcunetixScanResult,
|
|
43
|
+
Vulnerability as AcunetixVulnerability,
|
|
44
|
+
Severity as AcunetixSeverity,
|
|
45
|
+
get_acunetix,
|
|
46
|
+
acunetix_scan,
|
|
47
|
+
acunetix_status,
|
|
48
|
+
acunetix_vulns,
|
|
49
|
+
acunetix_summary,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Burp Suite Integration
|
|
53
|
+
from aipt_v2.tools.scanners.burp_tool import (
|
|
54
|
+
BurpTool,
|
|
55
|
+
BurpConfig,
|
|
56
|
+
ScanStatus as BurpScanStatus,
|
|
57
|
+
ScanResult as BurpScanResult,
|
|
58
|
+
Issue as BurpIssue,
|
|
59
|
+
IssueSeverity,
|
|
60
|
+
IssueConfidence,
|
|
61
|
+
get_burp,
|
|
62
|
+
burp_scan,
|
|
63
|
+
burp_status,
|
|
64
|
+
burp_issues,
|
|
65
|
+
burp_summary,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Nessus Integration
|
|
69
|
+
from aipt_v2.tools.scanners.nessus_tool import (
|
|
70
|
+
NessusTool,
|
|
71
|
+
NessusConfig,
|
|
72
|
+
ScanResult as NessusScanResult,
|
|
73
|
+
Vulnerability as NessusVulnerability,
|
|
74
|
+
get_nessus,
|
|
75
|
+
nessus_scan,
|
|
76
|
+
nessus_vulns,
|
|
77
|
+
nessus_summary,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# OWASP ZAP Integration
|
|
81
|
+
from aipt_v2.tools.scanners.zap_tool import (
|
|
82
|
+
ZAPTool,
|
|
83
|
+
ZAPConfig,
|
|
84
|
+
ScanResult as ZAPScanResult,
|
|
85
|
+
Alert as ZAPAlert,
|
|
86
|
+
get_zap,
|
|
87
|
+
zap_scan,
|
|
88
|
+
zap_alerts,
|
|
89
|
+
zap_summary,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
__all__ = [
|
|
93
|
+
# Configuration
|
|
94
|
+
"SCANNER_SERVER_IP",
|
|
95
|
+
"ACUNETIX_PORT",
|
|
96
|
+
"BURP_PORT",
|
|
97
|
+
"ACUNETIX_URL",
|
|
98
|
+
"BURP_URL",
|
|
99
|
+
"ACUNETIX",
|
|
100
|
+
"BURP",
|
|
101
|
+
"SCANNER",
|
|
102
|
+
"AcunetixSettings",
|
|
103
|
+
"BurpSettings",
|
|
104
|
+
"ScannerSettings",
|
|
105
|
+
"get_acunetix_config",
|
|
106
|
+
"get_burp_config",
|
|
107
|
+
"print_config",
|
|
108
|
+
# Acunetix
|
|
109
|
+
"AcunetixTool",
|
|
110
|
+
"AcunetixConfig",
|
|
111
|
+
"ScanProfile",
|
|
112
|
+
"AcunetixScanStatus",
|
|
113
|
+
"AcunetixScanResult",
|
|
114
|
+
"AcunetixVulnerability",
|
|
115
|
+
"AcunetixSeverity",
|
|
116
|
+
"get_acunetix",
|
|
117
|
+
"acunetix_scan",
|
|
118
|
+
"acunetix_status",
|
|
119
|
+
"acunetix_vulns",
|
|
120
|
+
"acunetix_summary",
|
|
121
|
+
# Burp Suite
|
|
122
|
+
"BurpTool",
|
|
123
|
+
"BurpConfig",
|
|
124
|
+
"BurpScanStatus",
|
|
125
|
+
"BurpScanResult",
|
|
126
|
+
"BurpIssue",
|
|
127
|
+
"IssueSeverity",
|
|
128
|
+
"IssueConfidence",
|
|
129
|
+
"get_burp",
|
|
130
|
+
"burp_scan",
|
|
131
|
+
"burp_status",
|
|
132
|
+
"burp_issues",
|
|
133
|
+
"burp_summary",
|
|
134
|
+
# Nessus
|
|
135
|
+
"NessusTool",
|
|
136
|
+
"NessusConfig",
|
|
137
|
+
"NessusScanResult",
|
|
138
|
+
"NessusVulnerability",
|
|
139
|
+
"get_nessus",
|
|
140
|
+
"nessus_scan",
|
|
141
|
+
"nessus_vulns",
|
|
142
|
+
"nessus_summary",
|
|
143
|
+
# OWASP ZAP
|
|
144
|
+
"ZAPTool",
|
|
145
|
+
"ZAPConfig",
|
|
146
|
+
"ZAPScanResult",
|
|
147
|
+
"ZAPAlert",
|
|
148
|
+
"get_zap",
|
|
149
|
+
"zap_scan",
|
|
150
|
+
"zap_alerts",
|
|
151
|
+
"zap_summary",
|
|
152
|
+
# Unified Interface
|
|
153
|
+
"ScannerType",
|
|
154
|
+
"get_scanner",
|
|
155
|
+
"scan_target",
|
|
156
|
+
"get_findings",
|
|
157
|
+
"get_all_findings",
|
|
158
|
+
"test_all_connections",
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
# ==================== Unified Scanner Interface ====================
|
|
163
|
+
|
|
164
|
+
class ScannerType:
|
|
165
|
+
"""Scanner type constants."""
|
|
166
|
+
ACUNETIX = "acunetix"
|
|
167
|
+
BURP = "burp"
|
|
168
|
+
NESSUS = "nessus"
|
|
169
|
+
ZAP = "zap"
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def get_scanner(scanner_type: str, config: dict = None):
|
|
173
|
+
"""
|
|
174
|
+
Get a scanner instance by type.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
scanner_type: 'acunetix', 'burp', 'nessus', or 'zap'
|
|
178
|
+
config: Optional configuration dict
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Scanner tool instance
|
|
182
|
+
"""
|
|
183
|
+
if scanner_type == ScannerType.ACUNETIX:
|
|
184
|
+
cfg = AcunetixConfig(**config) if config else None
|
|
185
|
+
return get_acunetix(cfg)
|
|
186
|
+
elif scanner_type == ScannerType.BURP:
|
|
187
|
+
cfg = BurpConfig(**config) if config else None
|
|
188
|
+
return get_burp(cfg)
|
|
189
|
+
elif scanner_type == ScannerType.NESSUS:
|
|
190
|
+
cfg = NessusConfig(**config) if config else None
|
|
191
|
+
return get_nessus(cfg)
|
|
192
|
+
elif scanner_type == ScannerType.ZAP:
|
|
193
|
+
cfg = ZAPConfig(**config) if config else None
|
|
194
|
+
return get_zap(cfg)
|
|
195
|
+
else:
|
|
196
|
+
raise ValueError(f"Unknown scanner type: {scanner_type}")
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def scan_target(url: str, scanner_type: str = "acunetix", **kwargs):
|
|
200
|
+
"""
|
|
201
|
+
Unified scan function - works with any scanner.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
url: Target URL to scan
|
|
205
|
+
scanner_type: 'acunetix', 'burp', 'nessus', or 'zap'
|
|
206
|
+
**kwargs: Scanner-specific options
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
ScanResult from the chosen scanner
|
|
210
|
+
"""
|
|
211
|
+
if scanner_type == ScannerType.ACUNETIX:
|
|
212
|
+
profile = kwargs.get("profile", "full")
|
|
213
|
+
return acunetix_scan(url, profile)
|
|
214
|
+
elif scanner_type == ScannerType.BURP:
|
|
215
|
+
config_id = kwargs.get("config_id")
|
|
216
|
+
return burp_scan(url, config_id)
|
|
217
|
+
elif scanner_type == ScannerType.NESSUS:
|
|
218
|
+
policy = kwargs.get("policy", "basic")
|
|
219
|
+
return nessus_scan(url, policy)
|
|
220
|
+
elif scanner_type == ScannerType.ZAP:
|
|
221
|
+
return zap_scan(url)
|
|
222
|
+
else:
|
|
223
|
+
raise ValueError(f"Unknown scanner type: {scanner_type}")
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def get_findings(scanner_type: str, scan_id: str = None, severity: str = None):
|
|
227
|
+
"""
|
|
228
|
+
Get findings from any scanner in unified AIPT format.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
scanner_type: 'acunetix', 'burp', 'nessus', or 'zap'
|
|
232
|
+
scan_id: Optional scan ID filter
|
|
233
|
+
severity: Optional severity filter
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
List of findings in AIPT format
|
|
237
|
+
"""
|
|
238
|
+
if scanner_type == ScannerType.ACUNETIX:
|
|
239
|
+
return acunetix_vulns(scan_id, severity)
|
|
240
|
+
elif scanner_type == ScannerType.BURP:
|
|
241
|
+
return burp_issues(scan_id, severity)
|
|
242
|
+
elif scanner_type == ScannerType.NESSUS:
|
|
243
|
+
return nessus_vulns(scan_id, severity)
|
|
244
|
+
elif scanner_type == ScannerType.ZAP:
|
|
245
|
+
return zap_alerts(scan_id, severity)
|
|
246
|
+
else:
|
|
247
|
+
raise ValueError(f"Unknown scanner type: {scanner_type}")
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def get_all_findings(scan_ids: dict = None) -> list:
|
|
251
|
+
"""
|
|
252
|
+
Aggregate findings from all scanners.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
scan_ids: Dict mapping scanner_type to scan_id
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
Combined list of findings from all scanners
|
|
259
|
+
"""
|
|
260
|
+
findings = []
|
|
261
|
+
scan_ids = scan_ids or {}
|
|
262
|
+
|
|
263
|
+
try:
|
|
264
|
+
acunetix_findings = acunetix_vulns(scan_ids.get("acunetix"))
|
|
265
|
+
findings.extend(acunetix_findings)
|
|
266
|
+
except Exception:
|
|
267
|
+
pass # Scanner not available
|
|
268
|
+
|
|
269
|
+
try:
|
|
270
|
+
burp_findings = burp_issues(scan_ids.get("burp"))
|
|
271
|
+
findings.extend(burp_findings)
|
|
272
|
+
except Exception:
|
|
273
|
+
pass # Scanner not available
|
|
274
|
+
|
|
275
|
+
try:
|
|
276
|
+
nessus_findings = nessus_vulns(scan_ids.get("nessus"))
|
|
277
|
+
findings.extend(nessus_findings)
|
|
278
|
+
except Exception:
|
|
279
|
+
pass # Scanner not available
|
|
280
|
+
|
|
281
|
+
try:
|
|
282
|
+
zap_findings = zap_alerts(scan_ids.get("zap"))
|
|
283
|
+
findings.extend(zap_findings)
|
|
284
|
+
except Exception:
|
|
285
|
+
pass # Scanner not available
|
|
286
|
+
|
|
287
|
+
return findings
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def test_all_connections() -> dict:
|
|
291
|
+
"""
|
|
292
|
+
Test connections to all configured scanners.
|
|
293
|
+
|
|
294
|
+
Returns:
|
|
295
|
+
Dict with connection status for each scanner
|
|
296
|
+
"""
|
|
297
|
+
results = {}
|
|
298
|
+
|
|
299
|
+
# Test Acunetix
|
|
300
|
+
try:
|
|
301
|
+
acunetix = AcunetixTool()
|
|
302
|
+
results["acunetix"] = {
|
|
303
|
+
"connected": acunetix.connect(),
|
|
304
|
+
"url": acunetix.config.base_url,
|
|
305
|
+
"info": acunetix.get_info() if acunetix.is_connected() else None
|
|
306
|
+
}
|
|
307
|
+
except Exception as e:
|
|
308
|
+
results["acunetix"] = {"connected": False, "error": str(e)}
|
|
309
|
+
|
|
310
|
+
# Test Burp
|
|
311
|
+
try:
|
|
312
|
+
burp = BurpTool()
|
|
313
|
+
results["burp"] = {
|
|
314
|
+
"connected": burp.connect(),
|
|
315
|
+
"url": burp.config.base_url,
|
|
316
|
+
"info": burp.get_info() if burp.is_connected() else None
|
|
317
|
+
}
|
|
318
|
+
except Exception as e:
|
|
319
|
+
results["burp"] = {"connected": False, "error": str(e)}
|
|
320
|
+
|
|
321
|
+
# Test Nessus
|
|
322
|
+
try:
|
|
323
|
+
nessus = NessusTool()
|
|
324
|
+
results["nessus"] = {
|
|
325
|
+
"connected": nessus.connect(),
|
|
326
|
+
"url": nessus.config.base_url,
|
|
327
|
+
"info": nessus.get_info() if nessus.is_connected() else None
|
|
328
|
+
}
|
|
329
|
+
except Exception as e:
|
|
330
|
+
results["nessus"] = {"connected": False, "error": str(e)}
|
|
331
|
+
|
|
332
|
+
# Test OWASP ZAP
|
|
333
|
+
try:
|
|
334
|
+
zap = ZAPTool()
|
|
335
|
+
results["zap"] = {
|
|
336
|
+
"connected": zap.connect(),
|
|
337
|
+
"url": zap.config.base_url,
|
|
338
|
+
"info": zap.get_info() if zap.is_connected() else None
|
|
339
|
+
}
|
|
340
|
+
except Exception as e:
|
|
341
|
+
results["zap"] = {"connected": False, "error": str(e)}
|
|
342
|
+
|
|
343
|
+
return results
|