Skip to content

Commit

Permalink
Added a lockdown mode to the server config. (Velocidex#2619)
Browse files Browse the repository at this point in the history
When a server is locked down certain permissions are removed (even from
admins). The lockdown is set in the config file. This helps to mitigate
the risk of a Velociraptor server admin account compromise.

After initial deployment, the administrator can set the server in
lockdown by adding the following config directive:

lockdown: true

to the server.config.yaml. After this the following permissions will be
denied:

 - ARTIFACT_WRITER
 - SERVER_ARTIFACT_WRITER
 - EXECVE
 - SERVER_ADMIN
 - FILESYSTEM_WRITE
 - FILESYSTEM_READ
 - MACHINE_STATE

During an active IR the server may be taken out of lockdown by removing
the directive from the config file and restarting the service. Usually
the config file is only writable by root and the Velociraptor server is
running as a low privilege account which can not write to the config
file.

Also added Content-Length to VFS download handler.
  • Loading branch information
scudette authored Apr 11, 2023
1 parent 8deaf4d commit 29679c8
Show file tree
Hide file tree
Showing 28 changed files with 483 additions and 228 deletions.
24 changes: 24 additions & 0 deletions acls/lockdown.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package acls

import (
"sync"

acl_proto "www.velocidex.com/golang/velociraptor/acls/proto"
)

var (
mu sync.Mutex
lockdown_token *acl_proto.ApiClientACL
)

func LockdownToken() *acl_proto.ApiClientACL {
mu.Lock()
defer mu.Unlock()
return lockdown_token
}

func SetLockdownToken(token *acl_proto.ApiClientACL) {
mu.Lock()
defer mu.Unlock()
lockdown_token = token
}
54 changes: 27 additions & 27 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (self *ApiServer) CancelFlow(

perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to cancel flows.")
}

Expand Down Expand Up @@ -132,7 +132,7 @@ func (self *ApiServer) GetReport(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view reports.")
}

Expand Down Expand Up @@ -182,7 +182,7 @@ func (self *ApiServer) CollectArtifact(

perm, err := acl_manager.CheckAccess(permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to launch flows.")
}
}
Expand Down Expand Up @@ -236,7 +236,7 @@ func (self *ApiServer) ListClients(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view clients.")
}

Expand Down Expand Up @@ -279,7 +279,7 @@ func (self *ApiServer) NotifyClients(
permissions := acls.COLLECT_CLIENT
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to launch flows.")
}

Expand Down Expand Up @@ -365,7 +365,7 @@ func (self *ApiServer) GetFlowDetails(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to launch flows.")
}

Expand Down Expand Up @@ -397,7 +397,7 @@ func (self *ApiServer) GetFlowRequests(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view flows.")
}

Expand Down Expand Up @@ -494,7 +494,7 @@ func (self *ApiServer) VFSListDirectory(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view the VFS.")
}

Expand Down Expand Up @@ -524,7 +524,7 @@ func (self *ApiServer) VFSStatDirectory(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to launch flows.")
}

Expand Down Expand Up @@ -554,7 +554,7 @@ func (self *ApiServer) VFSStatDownload(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view the VFS.")
}

Expand Down Expand Up @@ -585,7 +585,7 @@ func (self *ApiServer) VFSRefreshDirectory(
permissions := acls.COLLECT_CLIENT
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to launch flows.")
}

Expand All @@ -611,7 +611,7 @@ func (self *ApiServer) VFSGetBuffer(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view the VFS.")
}

Expand Down Expand Up @@ -652,7 +652,7 @@ func (self *ApiServer) GetTable(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view results.")
}

Expand Down Expand Up @@ -681,7 +681,7 @@ func (self *ApiServer) GetArtifacts(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view custom artifacts.")
}

Expand Down Expand Up @@ -734,7 +734,7 @@ func (self *ApiServer) GetArtifactFile(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view custom artifacts.")
}

Expand Down Expand Up @@ -787,8 +787,8 @@ func (self *ApiServer) SetArtifactFile(

perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied, fmt.Sprintf(
"User is not allowed to modify artifacts (%v).", permissions))
return nil, PermissionDenied(err,
fmt.Sprintf("User is not allowed to modify artifacts (%v).", permissions))
}

definition, err := setArtifactFile(ctx, org_config_obj, principal, in, "")
Expand Down Expand Up @@ -873,8 +873,8 @@ func (self *ApiServer) GetServerMonitoringState(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied, fmt.Sprintf(
"User is not allowed to read results (%v).", permissions))
return nil, PermissionDenied(err,
fmt.Sprintf("User is not allowed to read results (%v).", permissions))
}

result, err := getServerMonitoringState(org_config_obj)
Expand All @@ -900,8 +900,8 @@ func (self *ApiServer) SetServerMonitoringState(
permissions := acls.COLLECT_SERVER
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied, fmt.Sprintf(
"User is not allowed to modify artifacts (%v).", permissions))
return nil, PermissionDenied(err,
fmt.Sprintf("User is not allowed to modify artifacts (%v).", permissions))
}

err = setServerMonitoringState(org_config_obj, principal, in)
Expand All @@ -924,8 +924,8 @@ func (self *ApiServer) GetClientMonitoringState(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied, fmt.Sprintf(
"User is not allowed to read monitoring artifacts (%v).", permissions))
return nil, PermissionDenied(err,
fmt.Sprintf("User is not allowed to read monitoring artifacts (%v).", permissions))
}

manager, err := services.ClientEventManager(org_config_obj)
Expand Down Expand Up @@ -959,8 +959,8 @@ func (self *ApiServer) SetClientMonitoringState(
permissions := acls.COLLECT_CLIENT
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied, fmt.Sprintf(
"User is not allowed to modify monitoring artifacts (%v).", permissions))
return nil, PermissionDenied(err,
fmt.Sprintf("User is not allowed to modify monitoring artifacts (%v).", permissions))
}

manager, err := services.ClientEventManager(org_config_obj)
Expand Down Expand Up @@ -991,8 +991,8 @@ func (self *ApiServer) CreateDownloadFile(ctx context.Context,
permissions := acls.PREPARE_RESULTS
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied, fmt.Sprintf(
"User is not allowed to create downloads (%v).", permissions))
return nil, PermissionDenied(err,
fmt.Sprintf("User is not allowed to create downloads (%v).", permissions))
}

// Log an audit event.
Expand Down
4 changes: 1 addition & 3 deletions api/artifacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ import (

"github.com/sirupsen/logrus"
context "golang.org/x/net/context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"www.velocidex.com/golang/velociraptor/acls"
actions_proto "www.velocidex.com/golang/velociraptor/actions/proto"
api_proto "www.velocidex.com/golang/velociraptor/api/proto"
Expand Down Expand Up @@ -314,7 +312,7 @@ func (self *ApiServer) LoadArtifactPack(
permissions := acls.SERVER_ARTIFACT_WRITER
perm, err := services.CheckAccess(org_config_obj, principal, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to upload artifact packs.")
}

Expand Down
10 changes: 4 additions & 6 deletions api/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ import (
"time"

"github.com/Velocidex/ordereddict"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
"www.velocidex.com/golang/velociraptor/acls"
api_proto "www.velocidex.com/golang/velociraptor/api/proto"
Expand Down Expand Up @@ -54,7 +52,7 @@ func (self *ApiServer) GetClientMetadata(

perm, err := services.CheckAccess(org_config_obj, user_name, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view clients.")
}

Expand Down Expand Up @@ -87,7 +85,7 @@ func (self *ApiServer) SetClientMetadata(
permissions := acls.LABEL_CLIENT
perm, err := services.CheckAccess(org_config_obj, user_name, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to modify client labels.")
}

Expand Down Expand Up @@ -126,7 +124,7 @@ func (self *ApiServer) GetClient(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, user_name, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view clients.")
}

Expand Down Expand Up @@ -179,7 +177,7 @@ func (self *ApiServer) GetClientFlows(
permissions := acls.READ_RESULTS
perm, err := services.CheckAccess(org_config_obj, user_name, permissions)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to view flows.")
}

Expand Down
8 changes: 4 additions & 4 deletions api/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (self *ApiServer) GetSubject(

perm, err := services.CheckAccessWithToken(token, acls.DATASTORE_ACCESS)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to access datastore.")
}

Expand Down Expand Up @@ -88,7 +88,7 @@ func (self *ApiServer) SetSubject(

perm, err := services.CheckAccessWithToken(token, acls.DATASTORE_ACCESS)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to access datastore.")
}

Expand Down Expand Up @@ -152,7 +152,7 @@ func (self *ApiServer) ListChildren(

perm, err := services.CheckAccessWithToken(token, acls.DATASTORE_ACCESS)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to access datastore.")
}

Expand Down Expand Up @@ -211,7 +211,7 @@ func (self *ApiServer) DeleteSubject(

perm, err := services.CheckAccessWithToken(token, acls.DATASTORE_ACCESS)
if !perm || err != nil {
return nil, status.Error(codes.PermissionDenied,
return nil, PermissionDenied(err,
"User is not allowed to access datastore.")
}

Expand Down
Loading

0 comments on commit 29679c8

Please sign in to comment.