souleyez 2.43.29__py3-none-any.whl → 3.0.0__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.
- souleyez/__init__.py +1 -2
- souleyez/ai/__init__.py +21 -15
- souleyez/ai/action_mapper.py +249 -150
- souleyez/ai/chain_advisor.py +116 -100
- souleyez/ai/claude_provider.py +29 -28
- souleyez/ai/context_builder.py +80 -62
- souleyez/ai/executor.py +158 -117
- souleyez/ai/feedback_handler.py +136 -121
- souleyez/ai/llm_factory.py +27 -20
- souleyez/ai/llm_provider.py +4 -2
- souleyez/ai/ollama_provider.py +6 -9
- souleyez/ai/ollama_service.py +44 -37
- souleyez/ai/path_scorer.py +91 -76
- souleyez/ai/recommender.py +176 -144
- souleyez/ai/report_context.py +74 -73
- souleyez/ai/report_service.py +84 -66
- souleyez/ai/result_parser.py +222 -229
- souleyez/ai/safety.py +67 -44
- souleyez/auth/__init__.py +23 -22
- souleyez/auth/audit.py +36 -26
- souleyez/auth/engagement_access.py +65 -48
- souleyez/auth/permissions.py +14 -3
- souleyez/auth/session_manager.py +54 -37
- souleyez/auth/user_manager.py +109 -64
- souleyez/commands/audit.py +40 -43
- souleyez/commands/auth.py +35 -15
- souleyez/commands/deliverables.py +55 -50
- souleyez/commands/engagement.py +47 -28
- souleyez/commands/license.py +32 -23
- souleyez/commands/screenshots.py +36 -32
- souleyez/commands/user.py +82 -36
- souleyez/config.py +52 -44
- souleyez/core/credential_tester.py +87 -81
- souleyez/core/cve_mappings.py +179 -192
- souleyez/core/cve_matcher.py +162 -148
- souleyez/core/msf_auto_mapper.py +100 -83
- souleyez/core/msf_chain_engine.py +294 -256
- souleyez/core/msf_database.py +153 -70
- souleyez/core/msf_integration.py +679 -673
- souleyez/core/msf_rpc_client.py +40 -42
- souleyez/core/msf_rpc_manager.py +77 -79
- souleyez/core/msf_sync_manager.py +241 -181
- souleyez/core/network_utils.py +22 -15
- souleyez/core/parser_handler.py +34 -25
- souleyez/core/pending_chains.py +114 -63
- souleyez/core/templates.py +158 -107
- souleyez/core/tool_chaining.py +9564 -2881
- souleyez/core/version_utils.py +79 -94
- souleyez/core/vuln_correlation.py +136 -89
- souleyez/core/web_utils.py +33 -32
- souleyez/data/wordlists/ad_users.txt +378 -0
- souleyez/data/wordlists/api_endpoints_large.txt +769 -0
- souleyez/data/wordlists/home_dir_sensitive.txt +39 -0
- souleyez/data/wordlists/lfi_payloads.txt +82 -0
- souleyez/data/wordlists/passwords_brute.txt +1548 -0
- souleyez/data/wordlists/passwords_crack.txt +2479 -0
- souleyez/data/wordlists/passwords_spray.txt +386 -0
- souleyez/data/wordlists/subdomains_large.txt +5057 -0
- souleyez/data/wordlists/usernames_common.txt +694 -0
- souleyez/data/wordlists/web_dirs_large.txt +4769 -0
- souleyez/detection/__init__.py +1 -1
- souleyez/detection/attack_signatures.py +12 -17
- souleyez/detection/mitre_mappings.py +61 -55
- souleyez/detection/validator.py +97 -86
- souleyez/devtools.py +23 -10
- souleyez/docs/README.md +4 -4
- souleyez/docs/api-reference/cli-commands.md +2 -2
- souleyez/docs/developer-guide/adding-new-tools.md +562 -0
- souleyez/docs/user-guide/auto-chaining.md +30 -8
- souleyez/docs/user-guide/getting-started.md +1 -1
- souleyez/docs/user-guide/installation.md +26 -3
- souleyez/docs/user-guide/metasploit-integration.md +2 -2
- souleyez/docs/user-guide/rbac.md +1 -1
- souleyez/docs/user-guide/scope-management.md +1 -1
- souleyez/docs/user-guide/siem-integration.md +1 -1
- souleyez/docs/user-guide/tools-reference.md +1 -8
- souleyez/docs/user-guide/worker-management.md +1 -1
- souleyez/engine/background.py +1239 -535
- souleyez/engine/base.py +4 -1
- souleyez/engine/job_status.py +17 -49
- souleyez/engine/log_sanitizer.py +103 -77
- souleyez/engine/manager.py +38 -7
- souleyez/engine/result_handler.py +2200 -1550
- souleyez/engine/worker_manager.py +50 -41
- souleyez/export/evidence_bundle.py +72 -62
- souleyez/feature_flags/features.py +16 -20
- souleyez/feature_flags.py +5 -9
- souleyez/handlers/__init__.py +11 -0
- souleyez/handlers/base.py +188 -0
- souleyez/handlers/bash_handler.py +277 -0
- souleyez/handlers/bloodhound_handler.py +243 -0
- souleyez/handlers/certipy_handler.py +311 -0
- souleyez/handlers/crackmapexec_handler.py +486 -0
- souleyez/handlers/dnsrecon_handler.py +344 -0
- souleyez/handlers/enum4linux_handler.py +400 -0
- souleyez/handlers/evil_winrm_handler.py +493 -0
- souleyez/handlers/ffuf_handler.py +815 -0
- souleyez/handlers/gobuster_handler.py +1114 -0
- souleyez/handlers/gpp_extract_handler.py +334 -0
- souleyez/handlers/hashcat_handler.py +444 -0
- souleyez/handlers/hydra_handler.py +564 -0
- souleyez/handlers/impacket_getuserspns_handler.py +343 -0
- souleyez/handlers/impacket_psexec_handler.py +222 -0
- souleyez/handlers/impacket_secretsdump_handler.py +426 -0
- souleyez/handlers/john_handler.py +286 -0
- souleyez/handlers/katana_handler.py +425 -0
- souleyez/handlers/kerbrute_handler.py +298 -0
- souleyez/handlers/ldapsearch_handler.py +636 -0
- souleyez/handlers/lfi_extract_handler.py +464 -0
- souleyez/handlers/msf_auxiliary_handler.py +409 -0
- souleyez/handlers/msf_exploit_handler.py +380 -0
- souleyez/handlers/nikto_handler.py +413 -0
- souleyez/handlers/nmap_handler.py +821 -0
- souleyez/handlers/nuclei_handler.py +359 -0
- souleyez/handlers/nxc_handler.py +417 -0
- souleyez/handlers/rdp_sec_check_handler.py +353 -0
- souleyez/handlers/registry.py +292 -0
- souleyez/handlers/responder_handler.py +232 -0
- souleyez/handlers/service_explorer_handler.py +434 -0
- souleyez/handlers/smbclient_handler.py +344 -0
- souleyez/handlers/smbmap_handler.py +510 -0
- souleyez/handlers/smbpasswd_handler.py +296 -0
- souleyez/handlers/sqlmap_handler.py +1116 -0
- souleyez/handlers/theharvester_handler.py +601 -0
- souleyez/handlers/web_login_test_handler.py +327 -0
- souleyez/handlers/whois_handler.py +277 -0
- souleyez/handlers/wpscan_handler.py +554 -0
- souleyez/history.py +32 -16
- souleyez/importers/msf_importer.py +106 -75
- souleyez/importers/smart_importer.py +208 -147
- souleyez/integrations/siem/__init__.py +10 -10
- souleyez/integrations/siem/base.py +17 -18
- souleyez/integrations/siem/elastic.py +108 -122
- souleyez/integrations/siem/factory.py +207 -80
- souleyez/integrations/siem/googlesecops.py +146 -154
- souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
- souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
- souleyez/integrations/siem/sentinel.py +107 -109
- souleyez/integrations/siem/splunk.py +246 -212
- souleyez/integrations/siem/wazuh.py +65 -71
- souleyez/integrations/wazuh/__init__.py +5 -5
- souleyez/integrations/wazuh/client.py +70 -93
- souleyez/integrations/wazuh/config.py +85 -57
- souleyez/integrations/wazuh/host_mapper.py +28 -36
- souleyez/integrations/wazuh/sync.py +78 -68
- souleyez/intelligence/__init__.py +4 -5
- souleyez/intelligence/correlation_analyzer.py +309 -295
- souleyez/intelligence/exploit_knowledge.py +661 -623
- souleyez/intelligence/exploit_suggestions.py +159 -139
- souleyez/intelligence/gap_analyzer.py +132 -97
- souleyez/intelligence/gap_detector.py +251 -214
- souleyez/intelligence/sensitive_tables.py +266 -129
- souleyez/intelligence/service_parser.py +137 -123
- souleyez/intelligence/surface_analyzer.py +407 -268
- souleyez/intelligence/target_parser.py +159 -162
- souleyez/licensing/__init__.py +6 -6
- souleyez/licensing/validator.py +17 -19
- souleyez/log_config.py +79 -54
- souleyez/main.py +1505 -687
- souleyez/migrations/fix_job_counter.py +16 -14
- souleyez/parsers/bloodhound_parser.py +41 -39
- souleyez/parsers/crackmapexec_parser.py +178 -111
- souleyez/parsers/dalfox_parser.py +72 -77
- souleyez/parsers/dnsrecon_parser.py +103 -91
- souleyez/parsers/enum4linux_parser.py +183 -153
- souleyez/parsers/ffuf_parser.py +29 -25
- souleyez/parsers/gobuster_parser.py +301 -41
- souleyez/parsers/hashcat_parser.py +324 -79
- souleyez/parsers/http_fingerprint_parser.py +350 -103
- souleyez/parsers/hydra_parser.py +131 -111
- souleyez/parsers/impacket_parser.py +231 -178
- souleyez/parsers/john_parser.py +98 -86
- souleyez/parsers/katana_parser.py +316 -0
- souleyez/parsers/msf_parser.py +943 -498
- souleyez/parsers/nikto_parser.py +346 -65
- souleyez/parsers/nmap_parser.py +262 -174
- souleyez/parsers/nuclei_parser.py +40 -44
- souleyez/parsers/responder_parser.py +26 -26
- souleyez/parsers/searchsploit_parser.py +74 -74
- souleyez/parsers/service_explorer_parser.py +279 -0
- souleyez/parsers/smbmap_parser.py +180 -124
- souleyez/parsers/sqlmap_parser.py +434 -308
- souleyez/parsers/theharvester_parser.py +75 -57
- souleyez/parsers/whois_parser.py +135 -94
- souleyez/parsers/wpscan_parser.py +278 -190
- souleyez/plugins/afp.py +44 -36
- souleyez/plugins/afp_brute.py +114 -46
- souleyez/plugins/ard.py +48 -37
- souleyez/plugins/bloodhound.py +95 -61
- souleyez/plugins/certipy.py +303 -0
- souleyez/plugins/crackmapexec.py +186 -85
- souleyez/plugins/dalfox.py +120 -59
- souleyez/plugins/dns_hijack.py +146 -41
- souleyez/plugins/dnsrecon.py +97 -61
- souleyez/plugins/enum4linux.py +91 -66
- souleyez/plugins/evil_winrm.py +291 -0
- souleyez/plugins/ffuf.py +166 -90
- souleyez/plugins/firmware_extract.py +133 -29
- souleyez/plugins/gobuster.py +387 -190
- souleyez/plugins/gpp_extract.py +393 -0
- souleyez/plugins/hashcat.py +100 -73
- souleyez/plugins/http_fingerprint.py +913 -267
- souleyez/plugins/hydra.py +566 -200
- souleyez/plugins/impacket_getnpusers.py +117 -69
- souleyez/plugins/impacket_psexec.py +84 -64
- souleyez/plugins/impacket_secretsdump.py +103 -69
- souleyez/plugins/impacket_smbclient.py +89 -75
- souleyez/plugins/john.py +86 -69
- souleyez/plugins/katana.py +313 -0
- souleyez/plugins/kerbrute.py +237 -0
- souleyez/plugins/lfi_extract.py +541 -0
- souleyez/plugins/macos_ssh.py +117 -48
- souleyez/plugins/mdns.py +35 -30
- souleyez/plugins/msf_auxiliary.py +253 -130
- souleyez/plugins/msf_exploit.py +239 -161
- souleyez/plugins/nikto.py +134 -78
- souleyez/plugins/nmap.py +275 -91
- souleyez/plugins/nuclei.py +180 -89
- souleyez/plugins/nxc.py +285 -0
- souleyez/plugins/plugin_base.py +35 -36
- souleyez/plugins/plugin_template.py +13 -5
- souleyez/plugins/rdp_sec_check.py +130 -0
- souleyez/plugins/responder.py +112 -71
- souleyez/plugins/router_http_brute.py +76 -65
- souleyez/plugins/router_ssh_brute.py +118 -41
- souleyez/plugins/router_telnet_brute.py +124 -42
- souleyez/plugins/routersploit.py +91 -59
- souleyez/plugins/routersploit_exploit.py +77 -55
- souleyez/plugins/searchsploit.py +91 -77
- souleyez/plugins/service_explorer.py +1160 -0
- souleyez/plugins/smbmap.py +122 -72
- souleyez/plugins/smbpasswd.py +215 -0
- souleyez/plugins/sqlmap.py +301 -113
- souleyez/plugins/theharvester.py +127 -75
- souleyez/plugins/tr069.py +79 -57
- souleyez/plugins/upnp.py +65 -47
- souleyez/plugins/upnp_abuse.py +73 -55
- souleyez/plugins/vnc_access.py +129 -42
- souleyez/plugins/vnc_brute.py +109 -38
- souleyez/plugins/web_login_test.py +417 -0
- souleyez/plugins/whois.py +77 -58
- souleyez/plugins/wpscan.py +219 -69
- souleyez/reporting/__init__.py +2 -1
- souleyez/reporting/attack_chain.py +411 -346
- souleyez/reporting/charts.py +436 -501
- souleyez/reporting/compliance_mappings.py +334 -201
- souleyez/reporting/detection_report.py +126 -125
- souleyez/reporting/formatters.py +828 -591
- souleyez/reporting/generator.py +386 -302
- souleyez/reporting/metrics.py +72 -75
- souleyez/scanner.py +35 -29
- souleyez/security/__init__.py +37 -11
- souleyez/security/scope_validator.py +175 -106
- souleyez/security/validation.py +237 -149
- souleyez/security.py +22 -6
- souleyez/storage/credentials.py +247 -186
- souleyez/storage/crypto.py +296 -129
- souleyez/storage/database.py +73 -50
- souleyez/storage/db.py +58 -36
- souleyez/storage/deliverable_evidence.py +177 -128
- souleyez/storage/deliverable_exporter.py +282 -246
- souleyez/storage/deliverable_templates.py +134 -116
- souleyez/storage/deliverables.py +135 -130
- souleyez/storage/engagements.py +109 -56
- souleyez/storage/evidence.py +181 -152
- souleyez/storage/execution_log.py +31 -17
- souleyez/storage/exploit_attempts.py +93 -57
- souleyez/storage/exploits.py +67 -36
- souleyez/storage/findings.py +48 -61
- souleyez/storage/hosts.py +176 -144
- souleyez/storage/migrate_to_engagements.py +43 -19
- souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
- souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
- souleyez/storage/migrations/_003_add_execution_log.py +14 -8
- souleyez/storage/migrations/_005_screenshots.py +13 -5
- souleyez/storage/migrations/_006_deliverables.py +13 -5
- souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
- souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
- souleyez/storage/migrations/_010_evidence_linking.py +17 -10
- souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
- souleyez/storage/migrations/_012_team_collaboration.py +34 -21
- souleyez/storage/migrations/_013_add_host_tags.py +12 -6
- souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
- souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
- souleyez/storage/migrations/_016_add_domain_field.py +10 -4
- souleyez/storage/migrations/_017_msf_sessions.py +16 -8
- souleyez/storage/migrations/_018_add_osint_target.py +10 -6
- souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
- souleyez/storage/migrations/_020_add_rbac.py +36 -15
- souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
- souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
- souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
- souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
- souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
- souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
- souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
- souleyez/storage/migrations/__init__.py +26 -26
- souleyez/storage/migrations/migration_manager.py +19 -19
- souleyez/storage/msf_sessions.py +100 -65
- souleyez/storage/osint.py +17 -24
- souleyez/storage/recommendation_engine.py +269 -235
- souleyez/storage/screenshots.py +33 -32
- souleyez/storage/smb_shares.py +136 -92
- souleyez/storage/sqlmap_data.py +183 -128
- souleyez/storage/team_collaboration.py +135 -141
- souleyez/storage/timeline_tracker.py +122 -94
- souleyez/storage/wazuh_vulns.py +64 -66
- souleyez/storage/web_paths.py +33 -37
- souleyez/testing/credential_tester.py +221 -205
- souleyez/ui/__init__.py +1 -1
- souleyez/ui/ai_quotes.py +12 -12
- souleyez/ui/attack_surface.py +2439 -1516
- souleyez/ui/chain_rules_view.py +914 -382
- souleyez/ui/correlation_view.py +312 -230
- souleyez/ui/dashboard.py +2382 -1130
- souleyez/ui/deliverables_view.py +148 -62
- souleyez/ui/design_system.py +13 -13
- souleyez/ui/errors.py +49 -49
- souleyez/ui/evidence_linking_view.py +284 -179
- souleyez/ui/evidence_vault.py +393 -285
- souleyez/ui/exploit_suggestions_view.py +555 -349
- souleyez/ui/export_view.py +100 -66
- souleyez/ui/gap_analysis_view.py +315 -171
- souleyez/ui/help_system.py +105 -97
- souleyez/ui/intelligence_view.py +436 -293
- souleyez/ui/interactive.py +23034 -10679
- souleyez/ui/interactive_selector.py +75 -68
- souleyez/ui/log_formatter.py +47 -39
- souleyez/ui/menu_components.py +22 -13
- souleyez/ui/msf_auxiliary_menu.py +184 -133
- souleyez/ui/pending_chains_view.py +336 -172
- souleyez/ui/progress_indicators.py +5 -3
- souleyez/ui/recommendations_view.py +195 -137
- souleyez/ui/rule_builder.py +343 -225
- souleyez/ui/setup_wizard.py +678 -284
- souleyez/ui/shortcuts.py +217 -165
- souleyez/ui/splunk_gap_analysis_view.py +452 -270
- souleyez/ui/splunk_vulns_view.py +139 -86
- souleyez/ui/team_dashboard.py +498 -335
- souleyez/ui/template_selector.py +196 -105
- souleyez/ui/terminal.py +6 -6
- souleyez/ui/timeline_view.py +198 -127
- souleyez/ui/tool_setup.py +264 -164
- souleyez/ui/tutorial.py +202 -72
- souleyez/ui/tutorial_state.py +40 -40
- souleyez/ui/wazuh_vulns_view.py +235 -141
- souleyez/ui/wordlist_browser.py +260 -107
- souleyez/ui.py +464 -312
- souleyez/utils/tool_checker.py +427 -367
- souleyez/utils.py +33 -29
- souleyez/wordlists.py +134 -167
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/METADATA +2 -2
- souleyez-3.0.0.dist-info/RECORD +443 -0
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/WHEEL +1 -1
- souleyez-2.43.29.dist-info/RECORD +0 -379
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/entry_points.txt +0 -0
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/top_level.txt +0 -0
souleyez/plugins/wpscan.py
CHANGED
|
@@ -4,6 +4,7 @@ souleyez.plugins.wpscan
|
|
|
4
4
|
|
|
5
5
|
WPScan WordPress vulnerability scanner plugin.
|
|
6
6
|
"""
|
|
7
|
+
import os
|
|
7
8
|
import subprocess
|
|
8
9
|
import time
|
|
9
10
|
from typing import List
|
|
@@ -29,12 +30,15 @@ HELP = {
|
|
|
29
30
|
"usage": "souleyez jobs enqueue wpscan <url>",
|
|
30
31
|
"examples": [
|
|
31
32
|
"souleyez jobs enqueue wpscan http://example.com",
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
'souleyez jobs enqueue wpscan http://example.com --args "--enumerate vp"',
|
|
34
|
+
'souleyez jobs enqueue wpscan http://example.com --args "--enumerate u,ap,at"',
|
|
35
|
+
'souleyez jobs enqueue wpscan http://example.com --args "--passwords data/wordlists/top100.txt"',
|
|
35
36
|
],
|
|
36
37
|
"flags": [
|
|
37
|
-
[
|
|
38
|
+
[
|
|
39
|
+
"--enumerate <opts>",
|
|
40
|
+
"Enumerate: u (users), p (plugins), t (themes), vp (vulnerable plugins), vt (vulnerable themes)",
|
|
41
|
+
],
|
|
38
42
|
["--plugins-detection <mode>", "Detection mode: mixed, passive, aggressive"],
|
|
39
43
|
["--passwords <file>", "Password list for brute-force attacks"],
|
|
40
44
|
["--usernames <list>", "Usernames to use for brute-force (comma-separated)"],
|
|
@@ -43,58 +47,100 @@ HELP = {
|
|
|
43
47
|
["--api-token <token>", "WPVulnDB API token for vulnerability data"],
|
|
44
48
|
],
|
|
45
49
|
"presets": [
|
|
46
|
-
{
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
{
|
|
51
|
+
"name": "Quick Scan",
|
|
52
|
+
"args": ["--random-user-agent"],
|
|
53
|
+
"desc": "Basic WordPress detection and version check",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "Full Enumeration",
|
|
57
|
+
"args": ["--enumerate", "ap,at,u", "--random-user-agent"],
|
|
58
|
+
"desc": "Enumerate all plugins, themes, and users",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "Vulnerable Plugins",
|
|
62
|
+
"args": [
|
|
63
|
+
"--enumerate",
|
|
64
|
+
"vp",
|
|
65
|
+
"--plugins-detection",
|
|
66
|
+
"aggressive",
|
|
67
|
+
"--random-user-agent",
|
|
68
|
+
],
|
|
69
|
+
"desc": "Find vulnerable plugins only",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "User Enumeration",
|
|
73
|
+
"args": ["--enumerate", "u", "--random-user-agent"],
|
|
74
|
+
"desc": "Enumerate WordPress users",
|
|
75
|
+
},
|
|
50
76
|
],
|
|
51
77
|
"help_sections": [
|
|
52
78
|
{
|
|
53
79
|
"title": "What is WPScan?",
|
|
54
80
|
"color": "cyan",
|
|
55
81
|
"content": [
|
|
56
|
-
{
|
|
57
|
-
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
82
|
+
{
|
|
83
|
+
"title": "Overview",
|
|
84
|
+
"desc": "WPScan is the de-facto WordPress vulnerability scanner, identifying WordPress version, plugins, themes, misconfigurations, and known vulnerabilities.",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"title": "Use Cases",
|
|
88
|
+
"desc": "Essential for WordPress security assessments",
|
|
89
|
+
"tips": [
|
|
90
|
+
"Detect WordPress version and vulnerabilities",
|
|
91
|
+
"Enumerate installed plugins and themes",
|
|
92
|
+
"Find security misconfigurations",
|
|
93
|
+
"Test for weak passwords via brute-force",
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
],
|
|
64
97
|
},
|
|
65
98
|
{
|
|
66
99
|
"title": "How to Use",
|
|
67
100
|
"color": "green",
|
|
68
101
|
"content": [
|
|
69
|
-
{
|
|
70
|
-
|
|
71
|
-
"
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
"
|
|
75
|
-
|
|
76
|
-
|
|
102
|
+
{
|
|
103
|
+
"title": "Basic Workflow",
|
|
104
|
+
"desc": "1. Run quick scan to detect WordPress version\n 2. Enumerate vulnerable plugins/themes (vp,vt)\n 3. Check for users and misconfigurations\n 4. Test weak passwords if authorized",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"title": "Enumeration Options",
|
|
108
|
+
"desc": "Key flags for different scans",
|
|
109
|
+
"tips": [
|
|
110
|
+
"vp: Vulnerable plugins only",
|
|
111
|
+
"ap: All plugins (slow but thorough)",
|
|
112
|
+
"u: User enumeration",
|
|
113
|
+
"--passwords: Brute-force password file",
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
],
|
|
77
117
|
},
|
|
78
118
|
{
|
|
79
119
|
"title": "Tips & Best Practices",
|
|
80
120
|
"color": "yellow",
|
|
81
121
|
"content": [
|
|
82
|
-
(
|
|
83
|
-
"
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
122
|
+
(
|
|
123
|
+
"Best Practices:",
|
|
124
|
+
[
|
|
125
|
+
"Always use --random-user-agent to avoid detection",
|
|
126
|
+
"Start with vulnerable plugins/themes only (vp,vt)",
|
|
127
|
+
"Use WPVulnDB API token for full vulnerability data",
|
|
128
|
+
"Document outdated plugins as security findings",
|
|
129
|
+
"Test password lists only with explicit authorization",
|
|
130
|
+
],
|
|
131
|
+
),
|
|
132
|
+
(
|
|
133
|
+
"Common Issues:",
|
|
134
|
+
[
|
|
135
|
+
"Not WordPress site: Verify URL is a WordPress installation",
|
|
136
|
+
"Rate limiting: Add delays or reduce enumeration scope",
|
|
137
|
+
"No vulnerabilities found: Update WPScan or use API token",
|
|
138
|
+
"Enumeration blocked: Some hosts block automated scanners",
|
|
139
|
+
],
|
|
140
|
+
),
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
],
|
|
98
144
|
}
|
|
99
145
|
|
|
100
146
|
|
|
@@ -104,37 +150,102 @@ class WpscanPlugin(PluginBase):
|
|
|
104
150
|
category = "vulnerability_analysis"
|
|
105
151
|
HELP = HELP
|
|
106
152
|
|
|
107
|
-
|
|
108
153
|
def _get_base_url(self, url: str) -> str:
|
|
109
154
|
"""
|
|
110
|
-
Extract
|
|
155
|
+
Extract WordPress root URL from a full URL.
|
|
111
156
|
|
|
112
157
|
WPScan needs the WordPress root URL, not subpaths like /wp-content.
|
|
113
|
-
|
|
158
|
+
For WordPress in subdirectories, we preserve the parent path.
|
|
159
|
+
|
|
160
|
+
Examples:
|
|
161
|
+
http://10.0.0.48/wp-content → http://10.0.0.48/
|
|
162
|
+
http://10.0.0.48/blogblog/wp-admin/ → http://10.0.0.48/blogblog/
|
|
163
|
+
http://10.0.0.48/site/wordpress/wp-includes/ → http://10.0.0.48/site/wordpress/
|
|
114
164
|
"""
|
|
115
165
|
parsed = urlparse(url)
|
|
116
|
-
|
|
117
|
-
|
|
166
|
+
path = parsed.path
|
|
167
|
+
|
|
168
|
+
# WordPress subdirectory patterns to strip
|
|
169
|
+
# These indicate we're inside the WordPress installation
|
|
170
|
+
wp_subpaths = ["/wp-admin", "/wp-content", "/wp-includes", "/wp-login.php"]
|
|
171
|
+
|
|
172
|
+
# Find and strip WordPress-specific subpaths
|
|
173
|
+
for wp_sub in wp_subpaths:
|
|
174
|
+
idx = path.lower().find(wp_sub.lower())
|
|
175
|
+
if idx != -1:
|
|
176
|
+
# Keep everything before the WordPress subpath
|
|
177
|
+
path = path[:idx]
|
|
178
|
+
break
|
|
179
|
+
|
|
180
|
+
# Ensure path ends with /
|
|
181
|
+
if not path.endswith("/"):
|
|
182
|
+
path = path + "/"
|
|
183
|
+
|
|
184
|
+
# If path is empty, use root
|
|
185
|
+
if not path:
|
|
186
|
+
path = "/"
|
|
187
|
+
|
|
188
|
+
base = urlunparse((parsed.scheme, parsed.netloc, path, "", "", ""))
|
|
118
189
|
return base
|
|
119
190
|
|
|
120
|
-
def
|
|
191
|
+
def _fix_enumerate_args(self, args: List[str]) -> List[str]:
|
|
192
|
+
"""
|
|
193
|
+
Fix incompatible WPScan enumerate options.
|
|
194
|
+
|
|
195
|
+
WPScan has mutually exclusive options:
|
|
196
|
+
- vp (vulnerable plugins) and ap (all plugins) cannot be used together
|
|
197
|
+
- vt (vulnerable themes) and at (all themes) cannot be used together
|
|
198
|
+
|
|
199
|
+
If both are present, prefer the vulnerable-only option (vp/vt) as it's
|
|
200
|
+
faster and more focused.
|
|
201
|
+
"""
|
|
202
|
+
new_args = []
|
|
203
|
+
i = 0
|
|
204
|
+
while i < len(args):
|
|
205
|
+
arg = args[i]
|
|
206
|
+
if arg == "--enumerate" and i + 1 < len(args):
|
|
207
|
+
enum_value = args[i + 1]
|
|
208
|
+
# Parse the enumerate options
|
|
209
|
+
options = [opt.strip() for opt in enum_value.split(",")]
|
|
210
|
+
|
|
211
|
+
# Fix incompatible options
|
|
212
|
+
# If both vp and ap, remove ap (prefer vulnerable-only)
|
|
213
|
+
if "vp" in options and "ap" in options:
|
|
214
|
+
options.remove("ap")
|
|
215
|
+
# If both vt and at, remove at (prefer vulnerable-only)
|
|
216
|
+
if "vt" in options and "at" in options:
|
|
217
|
+
options.remove("at")
|
|
218
|
+
|
|
219
|
+
# Rebuild enumerate value
|
|
220
|
+
new_args.append("--enumerate")
|
|
221
|
+
new_args.append(",".join(options))
|
|
222
|
+
i += 2
|
|
223
|
+
else:
|
|
224
|
+
new_args.append(arg)
|
|
225
|
+
i += 1
|
|
226
|
+
|
|
227
|
+
return new_args
|
|
228
|
+
|
|
229
|
+
def build_command(
|
|
230
|
+
self, target: str, args: List[str] = None, label: str = "", log_path: str = None
|
|
231
|
+
):
|
|
121
232
|
"""Build command for background execution with PID tracking."""
|
|
122
233
|
if not target:
|
|
123
234
|
if log_path:
|
|
124
|
-
with open(log_path,
|
|
235
|
+
with open(log_path, "w") as f:
|
|
125
236
|
f.write("ERROR: Target URL is required\n")
|
|
126
237
|
return None
|
|
127
238
|
|
|
128
239
|
# Ensure URL format
|
|
129
|
-
if not target.startswith(
|
|
130
|
-
target = f
|
|
240
|
+
if not target.startswith("http://") and not target.startswith("https://"):
|
|
241
|
+
target = f"http://{target}"
|
|
131
242
|
|
|
132
243
|
# Validate URL
|
|
133
244
|
try:
|
|
134
245
|
target = validate_url(target)
|
|
135
246
|
except ValidationError as e:
|
|
136
247
|
if log_path:
|
|
137
|
-
with open(log_path,
|
|
248
|
+
with open(log_path, "w") as f:
|
|
138
249
|
f.write(f"ERROR: Invalid URL: {e}\n")
|
|
139
250
|
return None
|
|
140
251
|
|
|
@@ -144,20 +255,36 @@ class WpscanPlugin(PluginBase):
|
|
|
144
255
|
|
|
145
256
|
args = args or []
|
|
146
257
|
|
|
258
|
+
# Fix incompatible enumerate options (vp/ap, vt/at are mutually exclusive)
|
|
259
|
+
# vp = vulnerable plugins, ap = all plugins (can't use both)
|
|
260
|
+
# vt = vulnerable themes, at = all themes (can't use both)
|
|
261
|
+
args = self._fix_enumerate_args(args)
|
|
262
|
+
|
|
263
|
+
# Add --disable-tls-checks for HTTPS targets (handles self-signed certs)
|
|
264
|
+
if target.startswith("https://") and "--disable-tls-checks" not in args:
|
|
265
|
+
args = ["--disable-tls-checks"] + args
|
|
266
|
+
|
|
267
|
+
# Auto-add API token from environment if not already specified
|
|
268
|
+
if "--api-token" not in " ".join(args):
|
|
269
|
+
api_token = os.environ.get("WPSCAN_API_TOKEN")
|
|
270
|
+
if api_token:
|
|
271
|
+
args = ["--api-token", api_token] + args
|
|
272
|
+
|
|
147
273
|
# wpscan uses --url flag
|
|
148
274
|
cmd = ["wpscan", "--url", target] + args
|
|
149
275
|
|
|
150
276
|
# Log if we modified the URL
|
|
151
277
|
if log_path and original_target != target:
|
|
152
|
-
with open(log_path,
|
|
153
|
-
f.write(
|
|
278
|
+
with open(log_path, "w") as f:
|
|
279
|
+
f.write(
|
|
280
|
+
f"INFO: Using base URL {target} (original: {original_target})\n\n"
|
|
281
|
+
)
|
|
154
282
|
|
|
155
|
-
return {
|
|
156
|
-
'cmd': cmd,
|
|
157
|
-
'timeout': 1800
|
|
158
|
-
}
|
|
283
|
+
return {"cmd": cmd, "timeout": 1800}
|
|
159
284
|
|
|
160
|
-
def run(
|
|
285
|
+
def run(
|
|
286
|
+
self, target: str, args: List[str] = None, label: str = "", log_path: str = None
|
|
287
|
+
) -> int:
|
|
161
288
|
"""
|
|
162
289
|
Execute WPScan and write output to log_path.
|
|
163
290
|
"""
|
|
@@ -165,15 +292,15 @@ class WpscanPlugin(PluginBase):
|
|
|
165
292
|
raise ValueError("Target URL is required")
|
|
166
293
|
|
|
167
294
|
# Ensure URL format
|
|
168
|
-
if not target.startswith(
|
|
169
|
-
target = f
|
|
295
|
+
if not target.startswith("http://") and not target.startswith("https://"):
|
|
296
|
+
target = f"http://{target}"
|
|
170
297
|
|
|
171
298
|
# Validate URL
|
|
172
299
|
try:
|
|
173
300
|
target = validate_url(target)
|
|
174
301
|
except ValidationError as e:
|
|
175
302
|
if log_path:
|
|
176
|
-
with open(log_path,
|
|
303
|
+
with open(log_path, "w") as f:
|
|
177
304
|
f.write(f"ERROR: Invalid URL: {e}\n")
|
|
178
305
|
return 1
|
|
179
306
|
raise ValueError(f"Invalid URL: {e}")
|
|
@@ -184,24 +311,47 @@ class WpscanPlugin(PluginBase):
|
|
|
184
311
|
if args is None:
|
|
185
312
|
args = []
|
|
186
313
|
|
|
314
|
+
# Fix incompatible enumerate options (vp/ap, vt/at are mutually exclusive)
|
|
315
|
+
args = self._fix_enumerate_args(args)
|
|
316
|
+
|
|
317
|
+
# Add --disable-tls-checks for HTTPS targets (handles self-signed certs)
|
|
318
|
+
if target.startswith("https://") and "--disable-tls-checks" not in args:
|
|
319
|
+
args = ["--disable-tls-checks"] + args
|
|
320
|
+
|
|
321
|
+
# Auto-add API token from environment if not already specified
|
|
322
|
+
if "--api-token" not in " ".join(args):
|
|
323
|
+
api_token = os.environ.get("WPSCAN_API_TOKEN")
|
|
324
|
+
if api_token:
|
|
325
|
+
args = ["--api-token", api_token] + args
|
|
326
|
+
|
|
187
327
|
cmd = ["wpscan", "--url", target] + args
|
|
188
328
|
|
|
189
329
|
if log_path:
|
|
190
|
-
|
|
330
|
+
# Redact API token from logged command
|
|
331
|
+
logged_cmd = []
|
|
332
|
+
skip_next = False
|
|
333
|
+
for arg in cmd:
|
|
334
|
+
if skip_next:
|
|
335
|
+
logged_cmd.append("[REDACTED]")
|
|
336
|
+
skip_next = False
|
|
337
|
+
elif arg == "--api-token":
|
|
338
|
+
logged_cmd.append(arg)
|
|
339
|
+
skip_next = True
|
|
340
|
+
else:
|
|
341
|
+
logged_cmd.append(arg)
|
|
342
|
+
|
|
343
|
+
with open(log_path, "w") as f:
|
|
191
344
|
f.write(f"# WPScan for {target}\n")
|
|
192
|
-
f.write(f"# Command: {' '.join(
|
|
345
|
+
f.write(f"# Command: {' '.join(logged_cmd)}\n")
|
|
193
346
|
f.write(f"# Started: {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n")
|
|
194
347
|
|
|
195
348
|
try:
|
|
196
349
|
result = subprocess.run(
|
|
197
|
-
cmd,
|
|
198
|
-
capture_output=True,
|
|
199
|
-
text=True,
|
|
200
|
-
timeout=600 # 10 minutes
|
|
350
|
+
cmd, capture_output=True, text=True, timeout=600 # 10 minutes
|
|
201
351
|
)
|
|
202
352
|
|
|
203
353
|
if log_path:
|
|
204
|
-
with open(log_path,
|
|
354
|
+
with open(log_path, "a") as f:
|
|
205
355
|
f.write(result.stdout)
|
|
206
356
|
if result.stderr:
|
|
207
357
|
f.write(f"\n\n# Errors:\n{result.stderr}\n")
|
|
@@ -210,12 +360,12 @@ class WpscanPlugin(PluginBase):
|
|
|
210
360
|
|
|
211
361
|
except subprocess.TimeoutExpired:
|
|
212
362
|
if log_path:
|
|
213
|
-
with open(log_path,
|
|
363
|
+
with open(log_path, "a") as f:
|
|
214
364
|
f.write("\n\n# ERROR: Command timed out after 10 minutes\n")
|
|
215
365
|
return 124
|
|
216
366
|
except Exception as e:
|
|
217
367
|
if log_path:
|
|
218
|
-
with open(log_path,
|
|
368
|
+
with open(log_path, "a") as f:
|
|
219
369
|
f.write(f"\n\n# ERROR: {str(e)}\n")
|
|
220
370
|
return 1
|
|
221
371
|
|
souleyez/reporting/__init__.py
CHANGED