mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-05 02:18:46 +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"},
|
"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 时传入空字符串可清除"},
|
"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},
|
"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"},
|
"profile_id": map[string]interface{}{"type": "string", "description": "Malleable Profile ID"},
|
||||||
"remark": map[string]interface{}{"type": "string", "description": "备注"},
|
"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)"},
|
"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{}
|
cfg = &c2.ListenerConfig{}
|
||||||
_ = json.Unmarshal(cfgBytes, cfg)
|
_ = 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{
|
input := c2.CreateListenerInput{
|
||||||
Name: getString(params, "name"),
|
Name: getString(params, "name"),
|
||||||
Type: getString(params, "type"),
|
Type: getString(params, "type"),
|
||||||
@@ -123,7 +131,7 @@ tcp_reverse 默认仅接受 CSB1 加密 Beacon(AES-GCM + ImplantToken)才登
|
|||||||
BindPort: int(getFloat64(params, "bind_port")),
|
BindPort: int(getFloat64(params, "bind_port")),
|
||||||
ProfileID: getString(params, "profile_id"),
|
ProfileID: getString(params, "profile_id"),
|
||||||
Remark: getString(params, "remark"),
|
Remark: getString(params, "remark"),
|
||||||
ProjectID: strings.TrimSpace(mcp.MCPProjectIDFromContext(ctx)),
|
ProjectID: projectID,
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
CallbackHost: getString(params, "callback_host"),
|
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
|
return nil
|
||||||
}
|
}
|
||||||
if id == "" {
|
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 nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("missing resource identifier %s", argument)
|
return fmt.Errorf("missing resource identifier %s", argument)
|
||||||
|
|||||||
Reference in New Issue
Block a user