mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-01 16:38:48 +02:00
Add files via upload
This commit is contained in:
@@ -75,6 +75,7 @@ tcp_reverse 默认仅接受 CSB1 加密 Beacon(AES-GCM + ImplantToken)才登
|
||||
"bind_host": map[string]interface{}{"type": "string", "description": "绑定地址,默认 127.0.0.1;外网监听常用 0.0.0.0"},
|
||||
"callback_host": map[string]interface{}{"type": "string", "description": "可选:植入端/Payload 回连主机名(公网 IP 或域名)。写入 config_json;生成 oneliner/beacon 时优先于 bind_host。update 时传入空字符串可清除"},
|
||||
"bind_port": map[string]interface{}{"type": "integer", "description": fmt.Sprintf("绑定端口(create 必填)。须 ≠ %d(当前本服务 Web/API 端口,配置 server.port)", webListenPort), "minimum": 1, "maximum": 65535},
|
||||
"project_id": map[string]interface{}{"type": "string", "description": "所属项目 ID。create 省略时默认使用当前对话绑定项目;未绑定项目的对话则创建未绑定监听器"},
|
||||
"profile_id": map[string]interface{}{"type": "string", "description": "Malleable Profile ID"},
|
||||
"remark": map[string]interface{}{"type": "string", "description": "备注"},
|
||||
"config": map[string]interface{}{"type": "object", "description": "高级配置(beacon 路径/TLS/OPSEC 等),create/update 可用。tcp_reverse 可选 allow_legacy_shell:true 允许未加密经典 shell(默认 false)"},
|
||||
@@ -116,6 +117,13 @@ tcp_reverse 默认仅接受 CSB1 加密 Beacon(AES-GCM + ImplantToken)才登
|
||||
cfg = &c2.ListenerConfig{}
|
||||
_ = json.Unmarshal(cfgBytes, cfg)
|
||||
}
|
||||
projectID := strings.TrimSpace(getString(params, "project_id"))
|
||||
if projectID == "" {
|
||||
projectID = mcpEffectiveProjectFilter(ctx, m.DB())
|
||||
if projectID == database.ProjectFilterUnbound {
|
||||
projectID = ""
|
||||
}
|
||||
}
|
||||
input := c2.CreateListenerInput{
|
||||
Name: getString(params, "name"),
|
||||
Type: getString(params, "type"),
|
||||
@@ -123,7 +131,7 @@ tcp_reverse 默认仅接受 CSB1 加密 Beacon(AES-GCM + ImplantToken)才登
|
||||
BindPort: int(getFloat64(params, "bind_port")),
|
||||
ProfileID: getString(params, "profile_id"),
|
||||
Remark: getString(params, "remark"),
|
||||
ProjectID: strings.TrimSpace(mcp.MCPProjectIDFromContext(ctx)),
|
||||
ProjectID: projectID,
|
||||
Config: cfg,
|
||||
CallbackHost: getString(params, "callback_host"),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"cyberstrike-ai/internal/authctx"
|
||||
"cyberstrike-ai/internal/c2"
|
||||
"cyberstrike-ai/internal/database"
|
||||
"cyberstrike-ai/internal/mcp"
|
||||
"cyberstrike-ai/internal/mcp/builtin"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func TestC2ListenerCreateInheritsConversationProject(t *testing.T) {
|
||||
db, err := database.NewDB(filepath.Join(t.TempDir(), "c2-tools.db"), zap.NewNop())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
user, err := db.CreateRBACUser("c2-agent", "C2 Agent", "hash", true, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
project, err := db.CreateProject(&database.Project{Name: "engagement"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.AssignResourceToUser(user.ID, "project", project.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
conversation, err := db.CreateConversation("project chat", database.ConversationCreateMeta{ProjectID: project.ID})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
principal := authctx.NewPrincipal(user.ID, user.Username, database.RBACScopeAssigned, map[string]bool{
|
||||
"c2:read": true, "c2:write": true,
|
||||
})
|
||||
ctx := authctx.WithPrincipal(mcp.WithMCPConversationID(context.Background(), conversation.ID), principal)
|
||||
server := mcp.NewServer(zap.NewNop())
|
||||
server.SetToolAuthorizer(mcpToolAuthorizer(db))
|
||||
registerC2Tools(server, c2.NewManager(db, zap.NewNop(), t.TempDir()), zap.NewNop(), 8080)
|
||||
|
||||
result, _, err := server.CallTool(ctx, builtin.ToolC2Listener, map[string]interface{}{
|
||||
"action": "create",
|
||||
"name": "tcp-reverse-2222",
|
||||
"type": "tcp_reverse",
|
||||
"bind_host": "0.0.0.0",
|
||||
"bind_port": 2222,
|
||||
})
|
||||
if err != nil || result == nil || result.IsError {
|
||||
t.Fatalf("create listener result=%#v err=%v text=%q", result, err, toolResultText(result))
|
||||
}
|
||||
|
||||
listeners, err := db.ListC2Listeners()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(listeners) != 1 {
|
||||
t.Fatalf("listener count=%d, want 1", len(listeners))
|
||||
}
|
||||
if listeners[0].ProjectID != project.ID {
|
||||
t.Fatalf("listener project_id=%q, want %q", listeners[0].ProjectID, project.ID)
|
||||
}
|
||||
}
|
||||
@@ -244,7 +244,20 @@ func authorizeC2Action(ctx context.Context, principal authctx.Principal, db *dat
|
||||
return nil
|
||||
}
|
||||
if id == "" {
|
||||
if action == "create" || action == "list" {
|
||||
if action == "create" {
|
||||
projectID := mcpAuthorizationString(args, "project_id")
|
||||
if projectID == "" {
|
||||
projectID = mcpEffectiveProjectFilter(ctx, db)
|
||||
if projectID == database.ProjectFilterUnbound {
|
||||
projectID = ""
|
||||
}
|
||||
}
|
||||
if projectID != "" && (db == nil || !db.UserCanAccessResource(principal.UserID, principal.ScopeFor(permission), "project", projectID)) {
|
||||
return fmt.Errorf("no access to project %s", projectID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if action == "list" {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("missing resource identifier %s", argument)
|
||||
|
||||
Reference in New Issue
Block a user