diff --git a/README.md b/README.md index 84cfca60..c8b029eb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # CyberStrikeAI -🚀 **下一代AI自主渗透测试平台** - 基于Golang构建,内置98+安全工具,支持灵活扩展自定义工具,通过MCP协议实现AI智能决策与自动化执行,让安全测试像对话一样简单。 +🚀 **下一代AI自主渗透测试平台** - 基于Golang构建,内置上百个安全工具,支持灵活扩展自定义工具,通过MCP协议实现AI智能决策与自动化执行,让安全测试像对话一样简单。 ![详情预览](./img/效果1.png) ## ✨ 功能特性 @@ -8,7 +8,7 @@ ### 核心功能 - 🤖 **AI智能代理** - 集成OpenAI兼容API(支持GPT、Claude、DeepSeek等),AI自主决策和执行安全测试 - 🧠 **智能决策引擎** - AI分析目标并自动选择最佳测试策略和工具组合 -- ⚡ **自主执行** - AI代理自动调用安全工具,无需人工干预 +- ⚡ **自主执行** - AI代理自动调用安全工具,无需人工干预,最多支持30轮迭代 - 🔄 **自适应调整** - 根据工具执行结果和发现的漏洞,AI自动调整测试策略 - 📝 **智能总结** - 达到最大迭代次数时,AI自动总结测试结果并提供下一步执行计划 - 💬 **对话式交互** - 自然语言对话界面,支持流式输出(SSE),实时查看执行过程 @@ -86,7 +86,7 @@ CyberStrikeAI/ - Go 1.21 或更高版本 - OpenAI API Key(或其他兼容OpenAI协议的API,如DeepSeek、Claude等) -- 安全工具(可选):根据您的需求安装相应的安全工具,系统支持98+个工具 +- 安全工具(可选):根据您的需求安装相应的安全工具,系统支持上百个工具 ### 安装步骤 @@ -132,7 +132,7 @@ security: 4. **安装安全工具(可选)** -根据您的需求安装相应的安全工具。系统支持98+个工具,您可以根据实际需要选择性安装: +根据您的需求安装相应的安全工具。系统支持上百个工具,您可以根据实际需要选择性安装: ```bash # macOS (使用Homebrew) @@ -303,6 +303,81 @@ parameters: 首先扫描 192.168.1.1 的开放端口,然后对发现的Web服务进行漏洞扫描 ``` +### 后渗透测试 + +在获得初始访问权限后,可以使用后渗透工具进行权限提升、横向移动和持久化: + +#### 1. Linux 权限提升枚举 +``` +使用 linpeas 对目标 Linux 系统进行权限提升检查 +``` + +#### 2. Windows 权限提升枚举 +``` +使用 winpeas 对目标 Windows 系统进行权限提升检查 +``` + +#### 3. Active Directory 攻击路径分析 +``` +使用 bloodhound 分析 Active Directory 的攻击路径 +``` + +#### 4. 凭证提取 +``` +使用 mimikatz 提取 Windows 系统的凭证信息 +``` + +#### 5. 横向移动 +``` +使用 impacket 工具集进行网络协议攻击和横向移动 +``` + +#### 6. 后门生成 +``` +使用 msfvenom 生成反向 shell 载荷 +``` + +### CTF 竞赛支持 + +系统内置了丰富的 CTF 工具,支持各种 CTF 题型的解题: + +#### 1. 隐写分析 +``` +使用 stegsolve 分析图片隐写 +使用 zsteg 检测 LSB 隐写 +``` + +#### 2. 密码破解 +``` +使用 hashcat 破解哈希值 +使用 john 破解密码文件 +使用 fcrackzip 破解 ZIP 文件密码 +使用 pdfcrack 破解 PDF 文件密码 +``` + +#### 3. 二进制分析 +``` +使用 gdb 调试二进制文件 +使用 radare2 进行逆向分析 +使用 strings 提取二进制文件中的字符串 +``` + +#### 4. 哈希识别 +``` +使用 hash-identifier 识别哈希类型 +``` + +#### 5. 数据转换和分析 +``` +使用 cyberchef 进行各种数据转换和分析 +使用 xxd 查看文件十六进制内容 +``` + +#### 6. 综合 CTF 解题 +``` +分析这个 CTF 题目:给定一个包含隐写和加密的文件,找出 flag +``` + ### 监控工具执行 在"工具监控"标签页中,您可以: @@ -571,7 +646,7 @@ curl -X POST http://localhost:8080/api/mcp \ ### 工具概览 -当前系统集成了 **98+ 个安全工具**,涵盖以下类别: +当前系统集成了 **上百个安全工具**,涵盖以下类别: - **网络扫描工具** - nmap, masscan, rustscan, arp-scan, nbtscan 等 - **Web应用扫描** - sqlmap, nikto, dirb, gobuster, feroxbuster, ffuf, httpx 等 @@ -584,6 +659,8 @@ curl -X POST http://localhost:8080/api/mcp \ - **漏洞利用** - metasploit, msfvenom, pwntools, ropper, ropgadget 等 - **密码破解** - hashcat, john, hashpump 等 - **取证分析** - volatility, volatility3, foremost, steghide, exiftool 等 +- **后渗透工具** - linpeas, winpeas, mimikatz, bloodhound, impacket, responder 等 +- **CTF工具** - stegsolve, zsteg, hash-identifier, fcrackzip, pdfcrack, cyberchef 等 - **系统工具** - exec, create-file, delete-file, list-files, modify-file 等 ### 主要工具示例 @@ -925,7 +1002,7 @@ CMD ["./cyberstrike-ai"] ### AI迭代机制 -- **最大迭代次数**:系统支持多轮AI迭代,确保复杂测试任务能够完成 +- **最大迭代次数**:系统支持最多30轮AI迭代,确保复杂测试任务能够完成 - **智能总结**:当达到最大迭代次数时,AI会自动总结所有测试结果、发现的问题和已完成的工作 - **下一步计划**:如果测试未完成,AI会提供详细的下一步执行计划,指导后续测试 diff --git a/config.yaml b/config.yaml index 9b5f9886..761cb67b 100644 --- a/config.yaml +++ b/config.yaml @@ -16,6 +16,9 @@ openai: base_url: "https://api.deepseek.com/v1" model: "deepseek-chat" +agent: + max_iterations: 30 # 最大迭代轮数 + database: path: "data/conversations.db" diff --git a/cyberstrike-ai b/cyberstrike-ai new file mode 100644 index 00000000..76f04244 Binary files /dev/null and b/cyberstrike-ai differ diff --git a/internal/agent/agent.go b/internal/agent/agent.go index 4572ac86..94b7e2db 100644 --- a/internal/agent/agent.go +++ b/internal/agent/agent.go @@ -17,19 +17,25 @@ import ( // Agent AI代理 type Agent struct { - openAIClient *http.Client - config *config.OpenAIConfig - mcpServer *mcp.Server - logger *zap.Logger + openAIClient *http.Client + config *config.OpenAIConfig + mcpServer *mcp.Server + logger *zap.Logger + maxIterations int } // NewAgent 创建新的Agent -func NewAgent(cfg *config.OpenAIConfig, mcpServer *mcp.Server, logger *zap.Logger) *Agent { +func NewAgent(cfg *config.OpenAIConfig, mcpServer *mcp.Server, logger *zap.Logger, maxIterations int) *Agent { + // 如果 maxIterations 为 0 或负数,使用默认值 30 + if maxIterations <= 0 { + maxIterations = 30 + } return &Agent{ - openAIClient: &http.Client{Timeout: 5 * time.Minute}, - config: cfg, - mcpServer: mcpServer, - logger: logger, + openAIClient: &http.Client{Timeout: 5 * time.Minute}, + config: cfg, + mcpServer: mcpServer, + logger: logger, + maxIterations: maxIterations, } } @@ -271,7 +277,7 @@ func (a *Agent) AgentLoopWithProgress(ctx context.Context, userInput string, his MCPExecutionIDs: make([]string, 0), } - maxIterations := 30 + maxIterations := a.maxIterations for i := 0; i < maxIterations; i++ { // 检查是否是最后一次迭代 isLastIteration := (i == maxIterations-1) @@ -527,7 +533,7 @@ func (a *Agent) AgentLoopWithProgress(ctx context.Context, userInput string, his sendProgress("progress", "达到最大迭代次数,正在生成总结...", nil) finalSummaryPrompt := ChatMessage{ Role: "user", - Content: "已达到最大迭代次数(30轮)。请总结到目前为止的所有测试结果、发现的问题和已完成的工作。如果需要继续测试,请提供详细的下一步执行计划。请直接回复,不要调用工具。", + Content: fmt.Sprintf("已达到最大迭代次数(%d轮)。请总结到目前为止的所有测试结果、发现的问题和已完成的工作。如果需要继续测试,请提供详细的下一步执行计划。请直接回复,不要调用工具。", a.maxIterations), } messages = append(messages, finalSummaryPrompt) @@ -542,7 +548,7 @@ func (a *Agent) AgentLoopWithProgress(ctx context.Context, userInput string, his } // 如果无法生成总结,返回友好的提示 - result.Response = "已达到最大迭代次数(30轮)。系统已执行了多轮测试,但由于达到迭代上限,无法继续自动执行。建议您查看已执行的工具结果,或提出新的测试请求以继续测试。" + result.Response = fmt.Sprintf("已达到最大迭代次数(%d轮)。系统已执行了多轮测试,但由于达到迭代上限,无法继续自动执行。建议您查看已执行的工具结果,或提出新的测试请求以继续测试。", a.maxIterations) return result, nil } diff --git a/internal/app/app.go b/internal/app/app.go index 8e1e2714..2480e3fe 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -63,7 +63,11 @@ func New(cfg *config.Config, log *logger.Logger) (*App, error) { executor.RegisterTools(mcpServer) // 创建Agent - agent := agent.NewAgent(&cfg.OpenAI, mcpServer, log.Logger) + maxIterations := cfg.Agent.MaxIterations + if maxIterations <= 0 { + maxIterations = 30 // 默认值 + } + agent := agent.NewAgent(&cfg.OpenAI, mcpServer, log.Logger, maxIterations) // 创建处理器 agentHandler := handler.NewAgentHandler(agent, db, log.Logger) diff --git a/internal/config/config.go b/internal/config/config.go index 82dd1ac0..943a27f9 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -14,6 +14,7 @@ type Config struct { Log LogConfig `yaml:"log"` MCP MCPConfig `yaml:"mcp"` OpenAI OpenAIConfig `yaml:"openai"` + Agent AgentConfig `yaml:"agent"` Security SecurityConfig `yaml:"security"` Database DatabaseConfig `yaml:"database"` } @@ -49,6 +50,10 @@ type DatabaseConfig struct { Path string `yaml:"path"` } +type AgentConfig struct { + MaxIterations int `yaml:"max_iterations"` +} + type ToolConfig struct { Name string `yaml:"name"` Command string `yaml:"command"` @@ -200,6 +205,9 @@ func Default() *Config { BaseURL: "https://api.openai.com/v1", Model: "gpt-4", }, + Agent: AgentConfig{ + MaxIterations: 30, // 默认最大迭代次数 + }, Security: SecurityConfig{ Tools: []ToolConfig{}, // 工具配置应该从 config.yaml 或 tools/ 目录加载 ToolsDir: "tools", // 默认工具目录 diff --git a/internal/security/executor.go b/internal/security/executor.go index 2ad29251..c179aa4c 100644 --- a/internal/security/executor.go +++ b/internal/security/executor.go @@ -256,7 +256,27 @@ func (e *Executor) buildCommandArgs(toolName string, toolConfig *config.ToolConf // 布尔值特殊处理:如果为 false,跳过;如果为 true,只添加标志 if param.Type == "bool" { - if boolVal, ok := value.(bool); ok { + var boolVal bool + var ok bool + + // 尝试多种类型转换 + if boolVal, ok = value.(bool); ok { + // 已经是布尔值 + } else if numVal, ok := value.(float64); ok { + // JSON 数字类型(float64) + boolVal = numVal != 0 + ok = true + } else if numVal, ok := value.(int); ok { + // int 类型 + boolVal = numVal != 0 + ok = true + } else if strVal, ok := value.(string); ok { + // 字符串类型 + boolVal = strVal == "true" || strVal == "1" || strVal == "yes" + ok = true + } + + if ok { if !boolVal { continue // false 时不添加任何参数 } diff --git a/web/static/css/style.css b/web/static/css/style.css index 9d6e1d0b..0638a539 100644 --- a/web/static/css/style.css +++ b/web/static/css/style.css @@ -618,10 +618,13 @@ header { background: var(--bg-primary); border-top: 1px solid var(--border-color); flex-shrink: 0; + width: 100%; + box-sizing: border-box; } -.chat-input-container input { +.chat-input-container textarea { flex: 1; + min-width: 0; padding: 12px 16px; border: 1px solid var(--border-color); border-radius: 8px; @@ -630,14 +633,46 @@ header { transition: all 0.2s; background: var(--bg-primary); color: var(--text-primary); + resize: none; + height: 44px; + font-family: inherit; + line-height: 1.5; + overflow-y: auto; + box-sizing: border-box; + /* 隐藏滚动条但保留滚动功能 */ + scrollbar-width: thin; /* Firefox */ + scrollbar-color: transparent transparent; /* Firefox - 隐藏滚动条 */ } -.chat-input-container input:focus { +/* WebKit 浏览器(Chrome, Safari, Edge)的滚动条样式 - 隐藏但保留功能 */ +.chat-input-container textarea::-webkit-scrollbar { + width: 4px; /* 最窄的滚动条 */ +} + +.chat-input-container textarea::-webkit-scrollbar-track { + background: transparent; /* 隐藏轨道 */ +} + +.chat-input-container textarea::-webkit-scrollbar-thumb { + background: transparent; /* 默认隐藏滑块 */ + border-radius: 2px; +} + +/* 鼠标悬停时显示滚动条 */ +.chat-input-container textarea:hover::-webkit-scrollbar-thumb { + background: var(--text-muted); /* 悬停时显示 */ +} + +.chat-input-container textarea:focus::-webkit-scrollbar-thumb { + background: var(--text-muted); /* 聚焦时显示 */ +} + +.chat-input-container textarea:focus { border-color: var(--accent-color); box-shadow: 0 0 0 3px rgba(0, 102, 255, 0.1); } -.chat-input-container input::placeholder { +.chat-input-container textarea::placeholder { color: var(--text-muted); } diff --git a/web/static/js/app.js b/web/static/js/app.js index 29b14b28..941af6fb 100644 --- a/web/static/js/app.js +++ b/web/static/js/app.js @@ -143,7 +143,7 @@ function collapseAllProgressDetails(assistantMessageId, progressId) { timeline.classList.remove('expanded'); const btn = document.querySelector(`#${assistantMessageId} .process-detail-btn`); if (btn) { - btn.innerHTML = '📋 过程详情'; + btn.innerHTML = '展开详情'; } } } @@ -271,19 +271,19 @@ function toggleProcessDetails(progressId, assistantMessageId) { if (content && timeline) { if (timeline.classList.contains('expanded')) { timeline.classList.remove('expanded'); - if (btn) btn.innerHTML = '📋 过程详情'; + if (btn) btn.innerHTML = '展开详情'; } else { timeline.classList.add('expanded'); - if (btn) btn.innerHTML = '📋 收起详情'; + if (btn) btn.innerHTML = '收起详情'; } } else if (timeline) { // 如果只有timeline,直接切换 if (timeline.classList.contains('expanded')) { timeline.classList.remove('expanded'); - if (btn) btn.innerHTML = '📋 过程详情'; + if (btn) btn.innerHTML = '展开详情'; } else { timeline.classList.add('expanded'); - if (btn) btn.innerHTML = '📋 收起详情'; + if (btn) btn.innerHTML = '收起详情'; } } @@ -613,32 +613,35 @@ function addMessage(role, content, mcpExecutionIds = null, progressId = null) { timeDiv.textContent = new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }); contentWrapper.appendChild(timeDiv); - // 如果有MCP执行ID,添加查看详情区域 - if (mcpExecutionIds && Array.isArray(mcpExecutionIds) && mcpExecutionIds.length > 0 && role === 'assistant') { + // 如果有MCP执行ID或进度ID,添加查看详情区域(统一使用"渗透测试详情"样式) + if (role === 'assistant' && ((mcpExecutionIds && Array.isArray(mcpExecutionIds) && mcpExecutionIds.length > 0) || progressId)) { const mcpSection = document.createElement('div'); mcpSection.className = 'mcp-call-section'; const mcpLabel = document.createElement('div'); mcpLabel.className = 'mcp-call-label'; - mcpLabel.textContent = `工具调用 (${mcpExecutionIds.length})`; + mcpLabel.textContent = '📋 渗透测试详情'; mcpSection.appendChild(mcpLabel); const buttonsContainer = document.createElement('div'); buttonsContainer.className = 'mcp-call-buttons'; - mcpExecutionIds.forEach((execId, index) => { - const detailBtn = document.createElement('button'); - detailBtn.className = 'mcp-detail-btn'; - detailBtn.innerHTML = `调用 #${index + 1}`; - detailBtn.onclick = () => showMCPDetail(execId); - buttonsContainer.appendChild(detailBtn); - }); + // 如果有MCP执行ID,添加MCP调用详情按钮 + if (mcpExecutionIds && Array.isArray(mcpExecutionIds) && mcpExecutionIds.length > 0) { + mcpExecutionIds.forEach((execId, index) => { + const detailBtn = document.createElement('button'); + detailBtn.className = 'mcp-detail-btn'; + detailBtn.innerHTML = `调用 #${index + 1}`; + detailBtn.onclick = () => showMCPDetail(execId); + buttonsContainer.appendChild(detailBtn); + }); + } - // 如果有进度ID,添加过程详情按钮 + // 如果有进度ID,添加展开详情按钮(统一使用"展开详情"文本) if (progressId) { const progressDetailBtn = document.createElement('button'); progressDetailBtn.className = 'mcp-detail-btn process-detail-btn'; - progressDetailBtn.innerHTML = `📋 过程详情`; + progressDetailBtn.innerHTML = '展开详情'; progressDetailBtn.onclick = () => toggleProcessDetails(progressId, messageDiv.id); buttonsContainer.appendChild(progressDetailBtn); // 存储进度ID到消息元素 @@ -688,8 +691,11 @@ function renderProcessDetails(messageId, processDetails) { if (!mcpLabel && !buttonsContainer) { mcpLabel = document.createElement('div'); mcpLabel.className = 'mcp-call-label'; - mcpLabel.textContent = '过程详情'; + mcpLabel.textContent = '📋 渗透测试详情'; mcpSection.appendChild(mcpLabel); + } else if (mcpLabel && mcpLabel.textContent !== '📋 渗透测试详情') { + // 如果标签存在但不是统一格式,更新它 + mcpLabel.textContent = '📋 渗透测试详情'; } // 如果没有按钮容器,创建一个 @@ -704,7 +710,7 @@ function renderProcessDetails(messageId, processDetails) { if (!processDetailBtn) { processDetailBtn = document.createElement('button'); processDetailBtn.className = 'mcp-detail-btn process-detail-btn'; - processDetailBtn.innerHTML = '📋 过程详情'; + processDetailBtn.innerHTML = '展开详情'; processDetailBtn.onclick = () => toggleProcessDetails(null, messageId); buttonsContainer.appendChild(processDetailBtn); } @@ -788,11 +794,14 @@ function removeMessage(id) { } } -// 回车发送消息 -document.getElementById('chat-input').addEventListener('keypress', function(e) { - if (e.key === 'Enter') { +// 回车发送消息,Shift+Enter 换行 +const chatInput = document.getElementById('chat-input'); +chatInput.addEventListener('keydown', function(e) { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); sendMessage(); } + // Shift+Enter 允许默认行为(换行) }); // 显示MCP调用详情 @@ -1122,6 +1131,12 @@ document.addEventListener('DOMContentLoaded', function() { // 加载对话列表 loadConversations(); + // 初始化 textarea 高度 + const chatInput = document.getElementById('chat-input'); + if (chatInput) { + chatInput.style.height = '44px'; + } + // 添加欢迎消息 addMessage('assistant', '系统已就绪。请输入您的测试需求,系统将自动执行相应的安全测试。'); }); diff --git a/web/templates/index.html b/web/templates/index.html index bd40fc09..116e9176 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -40,7 +40,7 @@
- +