mirror of
https://github.com/Vyntral/god-eye.git
synced 2026-10-11 06:28:43 +02:00
feat: Add Multi-Agent AI Orchestration with 8 specialized agents
- Implement 8 specialized AI agents (XSS, SQLi, Auth, API, Crypto, Secrets, Headers, General) - Add fast type-based routing for finding classification - Include OWASP-aligned knowledge bases per agent - Add agent handoff logic for cross-vulnerability detection - Optimize timeouts and parallelism for local LLM - Add new modules: cache, network, fingerprint, secrets, cloud, API, discovery - Update documentation with multi-agent feature
This commit is contained in:
1 parent
45295bb262
commit
812b3530b5
35 files changed
+9490
-341
No files matched your search
+3
-151
@@ -19,44 +19,7 @@ func CheckOpenRedirect(subdomain string, timeout int) bool {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
|
||||
// Common open redirect parameters
|
||||
testPayloads := []string{
|
||||
"?url=https://evil.com",
|
||||
"?redirect=https://evil.com",
|
||||
"?next=https://evil.com",
|
||||
"?return=https://evil.com",
|
||||
"?dest=https://evil.com",
|
||||
"?destination=https://evil.com",
|
||||
"?rurl=https://evil.com",
|
||||
"?target=https://evil.com",
|
||||
}
|
||||
|
||||
baseURLs := []string{
|
||||
fmt.Sprintf("https://%s", subdomain),
|
||||
fmt.Sprintf("http://%s", subdomain),
|
||||
}
|
||||
|
||||
for _, baseURL := range baseURLs {
|
||||
for _, payload := range testPayloads {
|
||||
testURL := baseURL + payload
|
||||
resp, err := client.Get(testURL)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
// Check if redirects to evil.com
|
||||
if resp.StatusCode >= 300 && resp.StatusCode < 400 {
|
||||
location := resp.Header.Get("Location")
|
||||
if strings.Contains(location, "evil.com") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return CheckOpenRedirectWithClient(subdomain, client)
|
||||
}
|
||||
|
||||
// CheckCORS tests for CORS misconfiguration
|
||||
@@ -67,51 +30,7 @@ func CheckCORS(subdomain string, timeout int) string {
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
|
||||
urls := []string{
|
||||
fmt.Sprintf("https://%s", subdomain),
|
||||
fmt.Sprintf("http://%s", subdomain),
|
||||
}
|
||||
|
||||
for _, url := range urls {
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Test with evil origin
|
||||
req.Header.Set("Origin", "https://evil.com")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
acao := resp.Header.Get("Access-Control-Allow-Origin")
|
||||
acac := resp.Header.Get("Access-Control-Allow-Credentials")
|
||||
|
||||
// Check for dangerous CORS configs
|
||||
if acao == "*" {
|
||||
if acac == "true" {
|
||||
return "Wildcard + Credentials"
|
||||
}
|
||||
return "Wildcard Origin"
|
||||
}
|
||||
|
||||
if acao == "https://evil.com" {
|
||||
if acac == "true" {
|
||||
return "Origin Reflection + Credentials"
|
||||
}
|
||||
return "Origin Reflection"
|
||||
}
|
||||
|
||||
if strings.Contains(acao, "null") {
|
||||
return "Null Origin Allowed"
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
return CheckCORSWithClient(subdomain, client)
|
||||
}
|
||||
|
||||
// CheckHTTPMethods tests which HTTP methods are allowed
|
||||
@@ -122,74 +41,7 @@ func CheckHTTPMethods(subdomain string, timeout int) (allowed []string, dangerou
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
|
||||
urls := []string{
|
||||
fmt.Sprintf("https://%s", subdomain),
|
||||
fmt.Sprintf("http://%s", subdomain),
|
||||
}
|
||||
|
||||
methods := []string{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "TRACE"}
|
||||
dangerousMethods := map[string]bool{
|
||||
"PUT": true,
|
||||
"DELETE": true,
|
||||
"TRACE": true,
|
||||
"PATCH": true,
|
||||
}
|
||||
|
||||
for _, url := range urls {
|
||||
// First try OPTIONS to get Allow header
|
||||
req, err := http.NewRequest("OPTIONS", url, nil)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
// Check Allow header
|
||||
allowHeader := resp.Header.Get("Allow")
|
||||
if allowHeader != "" {
|
||||
for _, method := range strings.Split(allowHeader, ",") {
|
||||
method = strings.TrimSpace(method)
|
||||
allowed = append(allowed, method)
|
||||
if dangerousMethods[method] {
|
||||
dangerous = append(dangerous, method)
|
||||
}
|
||||
}
|
||||
return allowed, dangerous
|
||||
}
|
||||
|
||||
// If no Allow header, test each method
|
||||
for _, method := range methods {
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
// Method is allowed if not 405 Method Not Allowed
|
||||
if resp.StatusCode != 405 {
|
||||
allowed = append(allowed, method)
|
||||
if dangerousMethods[method] {
|
||||
dangerous = append(dangerous, method)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(allowed) > 0 {
|
||||
return allowed, dangerous
|
||||
}
|
||||
}
|
||||
|
||||
return allowed, dangerous
|
||||
return CheckHTTPMethodsWithClient(subdomain, client)
|
||||
}
|
||||
|
||||
// WithClient versions for parallel execution with shared client
|
||||
|
||||
@@ -19,43 +19,7 @@ func CheckAdminPanels(subdomain string, timeout int) []string {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
|
||||
// Generic admin paths (common across all platforms)
|
||||
// Note: Removed platform-specific paths like /wp-admin, /admin.php, /phpmyadmin
|
||||
// These generate false positives on non-PHP/WordPress sites
|
||||
paths := []string{
|
||||
"/admin", "/administrator",
|
||||
"/login", "/signin", "/auth",
|
||||
"/manager", "/console", "/dashboard",
|
||||
"/admin/login", "/user/login",
|
||||
}
|
||||
|
||||
var found []string
|
||||
baseURLs := []string{
|
||||
fmt.Sprintf("https://%s", subdomain),
|
||||
fmt.Sprintf("http://%s", subdomain),
|
||||
}
|
||||
|
||||
for _, baseURL := range baseURLs {
|
||||
for _, path := range paths {
|
||||
testURL := baseURL + path
|
||||
resp, err := client.Get(testURL)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
// Found if 200, 301, 302, 401, 403 (not 404)
|
||||
if resp.StatusCode != 404 && resp.StatusCode != 0 {
|
||||
found = append(found, path)
|
||||
}
|
||||
}
|
||||
if len(found) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return found
|
||||
return CheckAdminPanelsWithClient(subdomain, client)
|
||||
}
|
||||
|
||||
// CheckGitSvnExposure checks for exposed .git or .svn directories
|
||||
@@ -66,38 +30,7 @@ func CheckGitSvnExposure(subdomain string, timeout int) (gitExposed bool, svnExp
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
|
||||
baseURLs := []string{
|
||||
fmt.Sprintf("https://%s", subdomain),
|
||||
fmt.Sprintf("http://%s", subdomain),
|
||||
}
|
||||
|
||||
for _, baseURL := range baseURLs {
|
||||
// Check .git
|
||||
resp, err := client.Get(baseURL + "/.git/config")
|
||||
if err == nil {
|
||||
body, _ := io.ReadAll(io.LimitReader(resp.Body, 1000))
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode == 200 && strings.Contains(string(body), "[core]") {
|
||||
gitExposed = true
|
||||
}
|
||||
}
|
||||
|
||||
// Check .svn
|
||||
resp, err = client.Get(baseURL + "/.svn/entries")
|
||||
if err == nil {
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode == 200 {
|
||||
svnExposed = true
|
||||
}
|
||||
}
|
||||
|
||||
if gitExposed || svnExposed {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return gitExposed, svnExposed
|
||||
return CheckGitSvnExposureWithClient(subdomain, client)
|
||||
}
|
||||
|
||||
// CheckBackupFiles checks for common backup files
|
||||
@@ -108,41 +41,7 @@ func CheckBackupFiles(subdomain string, timeout int) []string {
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
|
||||
// Common backup file patterns
|
||||
paths := []string{
|
||||
"/backup.zip", "/backup.tar.gz", "/backup.sql",
|
||||
"/db.sql", "/database.sql", "/dump.sql",
|
||||
"/site.zip", "/www.zip", "/public.zip",
|
||||
"/config.bak", "/config.old", "/.env.bak",
|
||||
"/index.php.bak", "/index.php.old", "/index.html.bak",
|
||||
"/web.config.bak", "/.htaccess.bak",
|
||||
}
|
||||
|
||||
var found []string
|
||||
baseURLs := []string{
|
||||
fmt.Sprintf("https://%s", subdomain),
|
||||
fmt.Sprintf("http://%s", subdomain),
|
||||
}
|
||||
|
||||
for _, baseURL := range baseURLs {
|
||||
for _, path := range paths {
|
||||
resp, err := client.Head(baseURL + path)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == 200 {
|
||||
found = append(found, path)
|
||||
}
|
||||
}
|
||||
if len(found) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return found
|
||||
return CheckBackupFilesWithClient(subdomain, client)
|
||||
}
|
||||
|
||||
// CheckAPIEndpoints checks for common API endpoints
|
||||
@@ -156,44 +55,7 @@ func CheckAPIEndpoints(subdomain string, timeout int) []string {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
|
||||
// Common API endpoint patterns
|
||||
paths := []string{
|
||||
"/api", "/api/v1", "/api/v2", "/api/v3",
|
||||
"/graphql", "/graphiql",
|
||||
"/swagger", "/swagger-ui", "/swagger.json", "/swagger.yaml",
|
||||
"/openapi.json", "/openapi.yaml",
|
||||
"/docs", "/api-docs", "/redoc",
|
||||
"/health", "/healthz", "/status",
|
||||
"/metrics", "/actuator", "/actuator/health",
|
||||
"/v1", "/v2", "/rest",
|
||||
}
|
||||
|
||||
var found []string
|
||||
baseURLs := []string{
|
||||
fmt.Sprintf("https://%s", subdomain),
|
||||
fmt.Sprintf("http://%s", subdomain),
|
||||
}
|
||||
|
||||
for _, baseURL := range baseURLs {
|
||||
for _, path := range paths {
|
||||
resp, err := client.Get(baseURL + path)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
// Found if not 404
|
||||
if resp.StatusCode != 404 && resp.StatusCode != 0 {
|
||||
found = append(found, path)
|
||||
}
|
||||
}
|
||||
if len(found) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return found
|
||||
return CheckAPIEndpointsWithClient(subdomain, client)
|
||||
}
|
||||
|
||||
// WithClient versions for parallel execution
|
||||
|
||||
Reference in new issue
Block a user