Skip to content

Commit

Permalink
Added rekey() VQL function (Velocidex#1604)
Browse files Browse the repository at this point in the history
This forces the client to regenerate it's own client id and reconnect
using the new client id.

Sometimes client writeback files are accidentally copied across
deployments (e.g. in VM images). This PR adds a
Server.Monitor.ClientConflict server event artifact to watch for the
409 conflict events and force clients to rekey when detected. It
should be used in situations where it is possible to client writeback
files to be duplicated.

This PR also fixes the client comms mechanism so it can be gracefully
cancelled and recreated without restarting the process.
  • Loading branch information
scudette authored Mar 2, 2022
1 parent 7dfb251 commit 6b70865
Show file tree
Hide file tree
Showing 44 changed files with 887 additions and 484 deletions.
10 changes: 5 additions & 5 deletions actions/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,12 @@ func update_writeback(
config_obj *config_proto.Config,
event_table *actions_proto.VQLEventTable) error {

// Store the event table in the Writeback file.
config_copy := proto.Clone(config_obj).(*config_proto.Config)
event_copy := proto.Clone(event_table).(*actions_proto.VQLEventTable)
config_copy.Writeback.EventQueries = event_copy
// Read the existing writeback file - it is ok if it does not
// exist yet.
writeback, _ := config.GetWriteback(config_obj.Client)
writeback.EventQueries = event_table

return config.UpdateWriteback(config_copy)
return config.UpdateWriteback(config_obj.Client, writeback)
}

func InitializeEventTable(ctx context.Context, service_wg *sync.WaitGroup) {
Expand Down
46 changes: 0 additions & 46 deletions actions/foreman.go

This file was deleted.

9 changes: 1 addition & 8 deletions api/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,15 +423,8 @@ func StartFrontendPlainHttp(
server_obj.Info("<red>Shutting down</> frontend")
atomic.StoreInt32(&server_obj.Healthy, 0)

time_ctx, cancel := context.WithTimeout(
context.Background(), 10*time.Second)
defer cancel()

server.SetKeepAlivesEnabled(false)
err := server.Shutdown(time_ctx)
if err != nil {
server_obj.Error("Frontend server error %v", err)
}
_ = server.Shutdown(ctx)
}()

return nil
Expand Down
28 changes: 14 additions & 14 deletions api/proto/api.pb.gw.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions artifacts/definitions/Generic/Client/Rekey.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Generic.Client.Rekey
description: |
This artifact forces the client to reinitialize it's client id.
It is normally not needed! You will want to use this artifact in
very specific situation, such as the Velociraptor service was
accidentally incorporated into a VM image with an existing write
back file. This will cause multiple systems to connect with the same
client id, and the server will reject clients with a HTTP 409
Rejected message.
If this happens, you can use the Server.Monitor.ClientConflict
artifact to schedule this artifact automatically.
The Wait parameter controls how long we wait before restarting the
client. Reduce this number if you need to rekey a lot of clients
quickly.
required_permissions:
- EXECVE

parameters:
- name: Wait
description: Wait this long before restarting the client.
type: int
default: '10'

sources:
- query:
SELECT rekey(wait=Wait) FROM scope()
11 changes: 11 additions & 0 deletions artifacts/definitions/Server/Internal/ClientConflict.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: Server.Internal.ClientConflict
description: |
This event artifact is an internal event stream receiving events
about client conflict.
When two clients attempt to connect to the server with the same
client id, the server rejects one of these with a 409 Conflict HTTP
message. The client id will be forwarded on this artifact as well so
the server may take action.
type: INTERNAL
21 changes: 21 additions & 0 deletions artifacts/definitions/Server/Monitor/ClientConflict.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Server.Monitor.ClientConflict
type: SERVER_EVENT
description: |
Sometimes the Velociraptor client is installed into a VM template
image with an existing write back file. In this case each VM
instance will start the client with the same client id.
When clients connect to the server multiple times, the server will
reject one with the HTTP 409 Conflict response.
This artifact will also force conflicting clients to rekey
themselves. Clients will generate a new client id and reconnect with
the server, saving their new keys into their write back files.
sources:
- query: |
SELECT
collect_client(client_id=ClientId,
artifacts="Generic.Client.Rekey", env=dict())
AS NewCollection
FROM watch_monitoring(artifact="Server.Internal.ClientConflict")
2 changes: 1 addition & 1 deletion artifacts/testdata/server/testcases/plist.out.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ SELECT * FROM Artifact.MacOS.System.Users(UserPlistGlob=srcDir + '/artifacts/tes
"AppleId": null,
"CreationTime": null,
"FailedLoginCount": 0,
"FailedLoginTimestamp": null,
"FailedLoginTimestamp": "0001-01-01T00:00:00Z",
"PasswordLastSetTime": "2017-11-25T00:36:29.728411912Z",
"_Source": "MacOS.System.Users"
}
Expand Down
3 changes: 3 additions & 0 deletions artifacts/testdata/server/testcases/time.in.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ Queries:
format="1/2/2006 3:04:05 PM") AS FormattedTime
FROM scope()
# Start the clock immediately - this should not block due to LIMIT 1
- SELECT Unix > 1630414425 FROM clock(period=60, start=0) LIMIT 1
4 changes: 4 additions & 0 deletions artifacts/testdata/server/testcases/time.out.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@ FROM scope()
"Time3": "2021-08-31T12:53:45Z",
"FormattedTime": "2021-08-30T08:01:28Z"
}
]SELECT Unix > 1630414425 FROM clock(period=60, start=0) LIMIT 1[
{
"Unix \u003e 1630414425": true
}
]
Loading

0 comments on commit 6b70865

Please sign in to comment.