mirror of
https://github.com/Vyntral/god-eye.git
synced 2026-03-19 17:43:41 +00:00
God's Eye is an ultra-fast subdomain enumeration and reconnaissance tool with AI-powered security analysis. ## ✨ Key Features ### 🔍 Comprehensive Enumeration - 20+ passive sources (crt.sh, Censys, URLScan, etc.) - DNS brute-force with smart wordlists - Wildcard detection and filtering - 1000 concurrent workers for maximum speed ### 🌐 Deep Reconnaissance - HTTP probing with 13+ security checks - Port scanning (configurable) - TLS/SSL fingerprinting - Technology detection (Wappalyzer-style) - WAF detection (Cloudflare, Akamai, etc.) - Security header analysis - JavaScript secrets extraction - Admin panel & API discovery - Backup file detection - robots.txt & sitemap.xml checks ### 🎯 Subdomain Takeover Detection - 110+ fingerprints (AWS, Azure, GitHub Pages, Heroku, etc.) - CNAME validation - Dead DNS detection ### 🤖 AI-Powered Analysis (NEW!) - Local AI using Ollama - No API costs, complete privacy - Real-time CVE detection via function calling (queries NVD database) - Cascade architecture: phi3.5 (fast triage) + qwen2.5-coder (deep analysis) - JavaScript security analysis - HTTP response anomaly detection - Executive summary reports ### 📊 Output Formats - Pretty terminal output with colors - JSON export - CSV export - TXT (simple subdomain list) - Silent mode for piping ## 🚀 Installation bash go install github.com/Vyntral/god-eye@latest ## 📖 Quick Start bash # Basic scan god-eye -d example.com # With AI analysis god-eye -d example.com --enable-ai # Only active hosts god-eye -d example.com --active # Export to JSON god-eye -d example.com -o results.json -f json ## 🎯 Use Cases - Bug bounty reconnaissance - Penetration testing - Security audits - Attack surface mapping - Red team operations ## ⚠️ Legal Notice This tool is for authorized security testing only. Users must obtain explicit permission before scanning any targets. Unauthorized access is illegal. ## 📄 License MIT License with additional security tool terms - see LICENSE file ## 🙏 Credits Built with ❤️ by Vyntral for Orizon Powered by Go, Ollama, and the security community --- 🤖 Generated with Claude Code https://claude.com/claude-code Co-Authored-By: Claude <noreply@anthropic.com>
258 lines
8.9 KiB
Go
258 lines
8.9 KiB
Go
package ai
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
// Tool represents a function that can be called by the AI
|
|
type Tool struct {
|
|
Type string `json:"type"`
|
|
Function ToolFunction `json:"function"`
|
|
}
|
|
|
|
// ToolFunction describes a callable function
|
|
type ToolFunction struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Parameters map[string]interface{} `json:"parameters"`
|
|
}
|
|
|
|
// ToolCall represents an AI request to call a function
|
|
type ToolCall struct {
|
|
ID string `json:"id"`
|
|
Type string `json:"type"`
|
|
Function ToolCallFunction `json:"function"`
|
|
}
|
|
|
|
// ToolCallFunction contains the function name and arguments
|
|
type ToolCallFunction struct {
|
|
Name string `json:"name"`
|
|
Arguments json.RawMessage `json:"arguments"`
|
|
}
|
|
|
|
// GetAvailableTools returns the list of tools available for AI function calling
|
|
func GetAvailableTools() []Tool {
|
|
return []Tool{
|
|
{
|
|
Type: "function",
|
|
Function: ToolFunction{
|
|
Name: "search_cve",
|
|
Description: "Search for CVE vulnerabilities for a specific software/technology and version. Returns a list of known CVEs with descriptions and severity.",
|
|
Parameters: map[string]interface{}{
|
|
"type": "object",
|
|
"properties": map[string]interface{}{
|
|
"technology": map[string]interface{}{
|
|
"type": "string",
|
|
"description": "The software or technology name (e.g., 'nginx', 'Apache', 'WordPress', 'IIS')",
|
|
},
|
|
"version": map[string]interface{}{
|
|
"type": "string",
|
|
"description": "The version number if known (e.g., '2.4.49', '10.0'). Use 'unknown' if version is not specified.",
|
|
},
|
|
},
|
|
"required": []string{"technology"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Type: "function",
|
|
Function: ToolFunction{
|
|
Name: "check_security_headers",
|
|
Description: "Analyzes HTTP security headers and returns recommendations for missing or misconfigured headers.",
|
|
Parameters: map[string]interface{}{
|
|
"type": "object",
|
|
"properties": map[string]interface{}{
|
|
"headers": map[string]interface{}{
|
|
"type": "object",
|
|
"description": "HTTP response headers as key-value pairs",
|
|
},
|
|
},
|
|
"required": []string{"headers"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Type: "function",
|
|
Function: ToolFunction{
|
|
Name: "analyze_javascript",
|
|
Description: "Analyzes JavaScript code for potential security issues like hardcoded secrets, eval usage, or suspicious patterns.",
|
|
Parameters: map[string]interface{}{
|
|
"type": "object",
|
|
"properties": map[string]interface{}{
|
|
"code": map[string]interface{}{
|
|
"type": "string",
|
|
"description": "JavaScript code snippet to analyze",
|
|
},
|
|
"url": map[string]interface{}{
|
|
"type": "string",
|
|
"description": "The URL where the JavaScript was found",
|
|
},
|
|
},
|
|
"required": []string{"code"},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// ExecuteTool executes a tool call and returns the result
|
|
func ExecuteTool(toolCall ToolCall) (string, error) {
|
|
switch toolCall.Function.Name {
|
|
case "search_cve":
|
|
var args struct {
|
|
Technology string `json:"technology"`
|
|
Version string `json:"version"`
|
|
}
|
|
if err := json.Unmarshal(toolCall.Function.Arguments, &args); err != nil {
|
|
return "", fmt.Errorf("failed to parse arguments: %w", err)
|
|
}
|
|
return SearchCVE(args.Technology, args.Version)
|
|
|
|
case "check_security_headers":
|
|
var args struct {
|
|
Headers map[string]string `json:"headers"`
|
|
}
|
|
if err := json.Unmarshal(toolCall.Function.Arguments, &args); err != nil {
|
|
return "", fmt.Errorf("failed to parse arguments: %w", err)
|
|
}
|
|
return CheckSecurityHeaders(args.Headers)
|
|
|
|
case "analyze_javascript":
|
|
var args struct {
|
|
Code string `json:"code"`
|
|
URL string `json:"url"`
|
|
}
|
|
if err := json.Unmarshal(toolCall.Function.Arguments, &args); err != nil {
|
|
return "", fmt.Errorf("failed to parse arguments: %w", err)
|
|
}
|
|
return AnalyzeJavaScript(args.Code, args.URL)
|
|
|
|
default:
|
|
return "", fmt.Errorf("unknown tool: %s", toolCall.Function.Name)
|
|
}
|
|
}
|
|
|
|
// CheckSecurityHeaders analyzes HTTP headers for security issues
|
|
func CheckSecurityHeaders(headers map[string]string) (string, error) {
|
|
var issues []string
|
|
var recommendations []string
|
|
|
|
// Check for important security headers
|
|
if _, ok := headers["Strict-Transport-Security"]; !ok {
|
|
issues = append(issues, "Missing HSTS header")
|
|
recommendations = append(recommendations, "Add 'Strict-Transport-Security: max-age=31536000; includeSubDomains'")
|
|
}
|
|
|
|
if _, ok := headers["X-Content-Type-Options"]; !ok {
|
|
issues = append(issues, "Missing X-Content-Type-Options header")
|
|
recommendations = append(recommendations, "Add 'X-Content-Type-Options: nosniff'")
|
|
}
|
|
|
|
if _, ok := headers["X-Frame-Options"]; !ok {
|
|
issues = append(issues, "Missing X-Frame-Options header")
|
|
recommendations = append(recommendations, "Add 'X-Frame-Options: DENY' or 'SAMEORIGIN'")
|
|
}
|
|
|
|
if csp, ok := headers["Content-Security-Policy"]; !ok {
|
|
issues = append(issues, "Missing Content-Security-Policy header")
|
|
recommendations = append(recommendations, "Add CSP header to prevent XSS attacks")
|
|
} else if csp == "" {
|
|
issues = append(issues, "Empty Content-Security-Policy header")
|
|
}
|
|
|
|
if xss, ok := headers["X-XSS-Protection"]; ok && xss == "0" {
|
|
issues = append(issues, "X-XSS-Protection is disabled")
|
|
recommendations = append(recommendations, "Enable XSS protection: '1; mode=block'")
|
|
}
|
|
|
|
// Check for information disclosure
|
|
if server, ok := headers["Server"]; ok {
|
|
issues = append(issues, fmt.Sprintf("Server header exposes technology: %s", server))
|
|
recommendations = append(recommendations, "Remove or obfuscate Server header")
|
|
}
|
|
|
|
if xPowered, ok := headers["X-Powered-By"]; ok {
|
|
issues = append(issues, fmt.Sprintf("X-Powered-By header exposes technology: %s", xPowered))
|
|
recommendations = append(recommendations, "Remove X-Powered-By header")
|
|
}
|
|
|
|
result := fmt.Sprintf("Security Headers Analysis:\n\nIssues Found (%d):\n", len(issues))
|
|
for i, issue := range issues {
|
|
result += fmt.Sprintf("%d. %s\n", i+1, issue)
|
|
}
|
|
|
|
if len(recommendations) > 0 {
|
|
result += fmt.Sprintf("\nRecommendations (%d):\n", len(recommendations))
|
|
for i, rec := range recommendations {
|
|
result += fmt.Sprintf("%d. %s\n", i+1, rec)
|
|
}
|
|
}
|
|
|
|
if len(issues) == 0 {
|
|
result = "Security headers look good! No major issues found."
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// AnalyzeJavaScript performs basic security analysis on JavaScript code
|
|
func AnalyzeJavaScript(code string, url string) (string, error) {
|
|
var findings []string
|
|
|
|
// Simple pattern matching for security issues
|
|
patterns := map[string]string{
|
|
"eval(": "Usage of eval() - can lead to code injection",
|
|
"innerHTML": "Usage of innerHTML - potential XSS vulnerability",
|
|
"document.write": "Usage of document.write - can be dangerous",
|
|
"api_key": "Potential hardcoded API key",
|
|
"apikey": "Potential hardcoded API key",
|
|
"password": "Potential hardcoded password",
|
|
"secret": "Potential hardcoded secret",
|
|
"token": "Potential hardcoded token",
|
|
"access_token": "Potential hardcoded access token",
|
|
"AKIA": "Potential AWS access key",
|
|
"Bearer ": "Potential hardcoded bearer token",
|
|
"crypto.createCipheriv": "Cryptographic operations - review implementation",
|
|
"Math.random()": "Math.random() is not cryptographically secure",
|
|
"localStorage.setItem": "Data stored in localStorage - ensure no sensitive data",
|
|
"sessionStorage.setItem": "Data stored in sessionStorage - ensure no sensitive data",
|
|
"XMLHttpRequest": "Legacy XMLHttpRequest - consider using fetch API",
|
|
"dangerouslySetInnerHTML": "React dangerouslySetInnerHTML - XSS risk",
|
|
}
|
|
|
|
for pattern, description := range patterns {
|
|
if contains(code, pattern) {
|
|
findings = append(findings, fmt.Sprintf("⚠️ %s", description))
|
|
}
|
|
}
|
|
|
|
result := fmt.Sprintf("JavaScript Security Analysis for %s:\n\n", url)
|
|
|
|
if len(findings) == 0 {
|
|
result += "No obvious security issues detected in this code snippet."
|
|
} else {
|
|
result += fmt.Sprintf("Found %d potential security issues:\n", len(findings))
|
|
for i, finding := range findings {
|
|
result += fmt.Sprintf("%d. %s\n", i+1, finding)
|
|
}
|
|
result += "\nNote: These are automated findings. Manual review is recommended."
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// contains checks if a string contains a substring (case-insensitive for simplicity)
|
|
func contains(s, substr string) bool {
|
|
return len(s) >= len(substr) && (s == substr || len(s) > len(substr) && containsAt(s, substr, 0))
|
|
}
|
|
|
|
func containsAt(s, substr string, start int) bool {
|
|
for i := start; i <= len(s)-len(substr); i++ {
|
|
if s[i:i+len(substr)] == substr {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|