Skip to content

ExplainGlobExpression endpoint resolves client KnowledgeBase variables without requiring client approval #1166

Description

@geo-chen

Summary

The ExplainGlobExpression API endpoint (POST /api/v2/clients/<client_id>/glob-expressions:explain) does not require a client approval. When a glob expression containing KnowledgeBase interpolation variables (e.g., %%users.homedir%%, %%users.username%%, %%fqdn%%) is submitted, the handler expands those variables against the client's stored KnowledgeBase -- exposing user account details, home directories, domain names, and environment paths to any authenticated GRR user without an approval.

Details

Every other client-data endpoint in ApiCallRouterWithApprovalChecks calls self.approval_checker.CheckClientAccess(context, args.client_id) before delegating to the handler. ExplainGlobExpression at lines 687-694 has an explicit comment acknowledging no approval is done, but the justification is that it "only exposes the KnowledgeBase":

grr/server/grr_response_server/gui/api_call_router_with_approval_checks.py, lines 687-694:

def ExplainGlobExpression(
    self,
    args: api_flow_pb2.ApiExplainGlobExpressionArgs,
    context: Optional[api_call_context.ApiCallContext] = None,
) -> api_flow.ApiExplainGlobExpressionHandler:
    # ExplainGlobExpression only exposes the KnowledgeBase, which does not need
    # approval.
    return self.delegate.ExplainGlobExpression(args, context=context)

The handler (ApiExplainGlobExpressionHandler, flow.py, lines 1356-1373) calls GetClientKnowledgeBase(args.client_id) (data_store_utils.py, line 49), which reads the full ClientSnapshot.knowledge_base from the database and passes it to GlobExpression.ExplainComponents. The KnowledgeBase proto (knowledge_base.proto, lines 99-204) includes:

  • users[].username, users[].homedir, users[].userprofile, users[].userdomain, users[].sid
  • fqdn, os, os_major_version, os_minor_version
  • environ_path, environ_temp, environ_allusersprofile
  • Windows-specific: environ_commonprogramfiles, environ_windir, environ_programfiles

The KnowledgeBase is populated by the Interrogate flow and often contains detailed enumeration of all local user accounts. This data is normally protected by the approval requirement on all client endpoints that return ClientSnapshot or ClientFullInfo.

The assessment that the KnowledgeBase "does not need approval" is incorrect: it discloses the usernames and home directories of all accounts on the monitored endpoint, which is sensitive information in a DFIR context (investigators may be monitoring specific accounts, and the KnowledgeBase enumeration reveals the full account list to any peer analyst).

PoC

Prerequisites: GRR server with ApiCallRouterWithApprovalChecks, an enrolled client C.aabbccddeeff0011 whose KnowledgeBase has been populated (via Interrogate flow). User bob has no approval on this client.

Bob calls ExplainGlobExpression with a KB-variable glob:

POST /api/v2/clients/C.aabbccddeeff0011/glob-expressions:explain HTTP/1.1
Authorization: Basic Ym9iOi4uLg==
X-CSRFToken: <bob's csrf token>
Content-Type: application/json

{"globExpression": "%%users.homedir%%/.bash_history", "exampleCount": 5}

Response (HTTP 200) -- returns expanded examples drawn from the client's KnowledgeBase:

{"components": [{"globExpression": "%%users.homedir%%", "examples": ["/home/alice", "/home/bob.admin", "/root", "/home/svc-backup"]}, {"globExpression": ".bash_history"}]}

The response reveals all usernames/home directories stored in the KnowledgeBase without an approval. For comparison, GET /api/v2/clients/C.aabbccddeeff0011/flows (which also reads client data) returns HTTP 403 for bob.

Additionally, simpler globs (e.g., /etc/*.conf) that do not use KB variables still succeed with HTTP 200, confirming the endpoint is entirely unapproved:

POST /api/v2/clients/C.1234567890abcdef/glob-expressions:explain
Authorization: Basic <bob>
{"globExpression": "/etc/*.conf", "exampleCount": 3}

Response: HTTP 200, {"components": [{"globExpression": "/etc/"}, {"globExpression": "*"}, {"globExpression": ".conf"}]}

Tested live on commit 9f8f797 (GRR 4.0.0.0).

Impact

Any authenticated GRR user can read the KnowledgeBase of any enrolled client (usernames, home directories, domain membership, OS details) by submitting a glob expression with KnowledgeBase interpolation variables. In incident-response contexts, the KnowledgeBase enumerates all user accounts on a monitored endpoint. This information is normally gated behind the approval workflow; this endpoint bypasses it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions