Detection rules › Panther

Panther rules: mongodb

MongoDB 2FA Disabled

#
Severity
medium
Log types
MongoDB.OrganizationEvent
Reference
www.mongodb.com
Source
github.com/panther-labs/panther-analysis

2FA was disabled.

Detection logic

from panther_mongodb_helpers import mongodb_alert_context


def rule(event):
    return event.get("eventTypeName", "") == "ORG_TWO_FACTOR_AUTH_OPTIONAL"


def title(event):
    user = event.get("username", "<USER_NOT_FOUND>")
    return f"MongoDB Atlas: [{user}] has disabled 2FA"


def alert_context(event):
    return mongodb_alert_context(event)

Rule specification

AnalysisType: rule
Description: "2FA was disabled."
DisplayName: "MongoDB 2FA Disabled"
Enabled: true
Filename: mongodb_2fa_disabled.py
Severity: Medium
Reference: https://www.mongodb.com/docs/atlas/security-multi-factor-authentication/
DedupPeriodMinutes: 60
LogTypes:
  - MongoDB.OrganizationEvent
RuleID: "MongoDB.2FA.Disabled"
Threshold: 1

Stages and Predicates

Fires on MongoDB.OrganizationEvent events when the condition below holds.

Condition

  • eventTypeName is ORG_TWO_FACTOR_AUTH_OPTIONAL

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
username
target_usernametargetUsername
org_idorgId
remote_addressremoteAddress

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "created": "2023-06-07 16:57:55",
  "currentValue": {},
  "eventTypeName": "ORG_TWO_FACTOR_AUTH_OPTIONAL",
  "id": "6480b7139bd8a012345ABCDE",
  "isGlobalAdmin": false,
  "links": [
    {
      "href": "https://cloud.mongodb.com/api/atlas/v1.0/orgs/12345xyzlmnce4f17d6e8e130/events/6480b7139bd8a012345ABCDE",
      "rel": "self"
    }
  ],
  "orgId": "12345xyzlmnce4f17d6e8e130",
  "p_event_time": "2023-06-07 16:57:55",
  "p_log_type": "MongoDB.OrganizationEvent",
  "p_parse_time": "2023-06-07 17:04:42.59",
  "p_row_id": "ea276b16216684d9e198c0d0188a3d",
  "p_schema_version": 0,
  "p_source_id": "7c3cb124-9c30-492c-99e6-46518c232d73",
  "p_source_label": "MongoDB",
  "remoteAddress": "1.2.3.4",
  "targetUsername": "outsider@other.com",
  "userId": "647f654f93bebc69123abc1",
  "username": "user@company.com"
}

MongoDB access allowed from anywhere

#
Severity
high
Log types
MongoDB.ProjectEvent
Tags
MongoDB, Persistence, Remote Services, Modify Authentication Process - Conditional Access Policies
Reference
www.mongodb.com
Source
github.com/panther-labs/panther-analysis

Atlas only allows client connections to the database deployment from entries in the project's IP access list. This rule detects when 0.0.0.0/0 is added to that list, which allows access from anywhere.

MITRE ATT&CK coverage

Detection logic

from panther_mongodb_helpers import mongodb_alert_context


def rule(event):
    if (
        event.get("eventTypeName", "") == "NETWORK_PERMISSION_ENTRY_ADDED"
        and event.get("whitelistEntry", "") == "0.0.0.0/0"
    ):
        return True
    return False


def title(event):
    user = event.get("username", "<USER_NOT_FOUND>")
    group_id = event.get("groupId", "<GROUP_NOT_FOUND>")
    return f"MongoDB: [{user}] has allowed access to group [{group_id}] from anywhere"


def alert_context(event):
    context = mongodb_alert_context(event)
    context["groupId"] = event.get("groupId", "<GROUP_NOT_FOUND>")
    return context

Rule specification

AnalysisType: rule
Description: Atlas only allows client connections to the database deployment from entries in the project's IP access list. This rule detects when 0.0.0.0/0 is added to that list, which allows access from anywhere.
DisplayName: "MongoDB access allowed from anywhere"
Enabled: true
LogTypes:
  - MongoDB.ProjectEvent
RuleID: "MongoDB.Access.Allowed.From.Anywhere"
Filename: mongodb_access_allowed_from_anywhere.py
Severity: High
Tags:
  - MongoDB
  - Persistence
  - Remote Services
  - Modify Authentication Process - Conditional Access Policies
Reports:
  MITRE ATT&CK:
    - TA0003:T1556.009 # Modify Authentication Process - Conditional Access Policies
    - TA0008:T1021.007 # Remote Services
Reference: https://www.mongodb.com/docs/atlas/security/ip-access-list/
Runbook: Check if this activity was legitimate. If not, delete 0.0.0.0/0 from the list of allowed ips.
DedupPeriodMinutes: 60
Threshold: 1

Stages and Predicates

Fires on MongoDB.ProjectEvent events when all of the conditions below hold.

Condition

  • eventTypeName is NETWORK_PERMISSION_ENTRY_ADDED
  • whitelistEntry is 0.0.0.0/0

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
username
target_usernametargetUsername
org_idorgId
remote_addressremoteAddress
groupId

Response runbook

Check if this activity was legitimate. If not, delete 0.0.0.0/0 from the list of allowed ips.

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "created": "2024-04-03 11:13:04.000000000",
  "currentValue": {},
  "eventTypeName": "NETWORK_PERMISSION_ENTRY_ADDED",
  "groupId": "some_group_id",
  "id": "123abc",
  "isGlobalAdmin": false,
  "remoteAddress": "1.2.3.4",
  "userId": "123abc",
  "username": "some_user@company.com",
  "whitelistEntry": "0.0.0.0/0"
}

MongoDB Atlas API Key Created

#
Severity
medium
Log types
MongoDB.OrganizationEvent
Reference
www.mongodb.com
Source
github.com/panther-labs/panther-analysis

A MongoDB Atlas api key's access list was updated

Detection logic

from panther_mongodb_helpers import mongodb_alert_context


def rule(event):
    return event.get("eventTypeName", "") == "API_KEY_ACCESS_LIST_ENTRY_ADDED"


def title(event):
    user = event.get("username", "<USER_NOT_FOUND>")
    public_key = event.get("targetPublicKey", "<PUBLIC_KEY_NOT_FOUND>")
    return f"MongoDB Atlas: [{user}] updated the allowed access list for API Key [{public_key}]"


def alert_context(event):
    context = mongodb_alert_context(event)
    links = event.deep_walk("links", "href", return_val="first", default="<LINKS_NOT_FOUND>")
    extra_context = {
        "links": links,
        "event_type_name": event.get("eventTypeName", "<EVENT_TYPE_NOT_FOUND>"),
        "target_public_key": event.get("targetPublicKey", "<PUBLIC_KEY_NOT_FOUND>"),
    }
    context.update(extra_context)

    return context

Rule specification

AnalysisType: rule
Description: A MongoDB Atlas api key's access list was updated
DisplayName: "MongoDB Atlas API Key Created"
Enabled: true
Filename: mongodb_atlas_api_key_created.py
Severity: Medium
Reference: https://www.mongodb.com/docs/atlas/configure-api-access/#std-label-about-org-api-keys
DedupPeriodMinutes: 60
LogTypes:
  - MongoDB.OrganizationEvent
RuleID: "MongoDB.Atlas.ApiKeyCreated"
Threshold: 1

Stages and Predicates

Fires on MongoDB.OrganizationEvent events when the condition below holds.

Condition

  • eventTypeName is API_KEY_ACCESS_LIST_ENTRY_ADDED

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
username
target_usernametargetUsername
org_idorgId
remote_addressremoteAddress
targetPublicKey

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "created": "2023-06-14 15:47:15",
  "currentvalue": {},
  "eventtypename": "API_KEY_ACCESS_LIST_ENTRY_ADDED",
  "id": "1234abcd13f2804962409423",
  "isglobaladmin": false,
  "links": [
    {
      "href": "https://cloud.mongodb.com/api/atlas/v1.0/orgs/9876xyz123lmnop0/events/1234abcd13f2804962409423",
      "rel": "self"
    }
  ],
  "orgid": "9876xyz123lmnop0",
  "p_event_time": "2023-06-14 15:47:15",
  "p_log_type": "MongoDB.OrganizationEvent",
  "p_parse_time": "2023-06-14 15:53:42.415",
  "p_row_id": "5ad9c2df49e19aac98def9e118e236",
  "p_schema_version": 0,
  "p_source_id": "a2e8f928-c6e5-4110-b6f9-1b741176041d",
  "p_source_label": "mongo-test-2",
  "remoteaddress": "1.2.3.4",
  "targetpublickey": "xfvcfwtt",
  "userid": "abcd1234userid988",
  "username": "user@company.com",
  "whitelistentry": "1.2.3.4"
}

MongoDB External User Invited

#
Severity
medium
Log types
MongoDB.OrganizationEvent
Tags
Configuration Required
Reference
www.mongodb.com
Source
github.com/panther-labs/panther-analysis

An external user has been invited to a MongoDB org.

Detection logic

import json
from unittest.mock import MagicMock

from panther_mongodb_helpers import mongodb_alert_context

# Set domains allowed to join the organization ie. company.com
ALLOWED_DOMAINS = []


def rule(event):
    global ALLOWED_DOMAINS  # pylint: disable=global-statement
    if isinstance(ALLOWED_DOMAINS, MagicMock):
        ALLOWED_DOMAINS = json.loads(ALLOWED_DOMAINS())  # pylint: disable=not-callable
    if event.get("eventTypeName", "") == "INVITED_TO_ORG":
        target_user = event.get("targetUsername", "")
        target_domain = target_user.split("@")[-1]
        return target_domain not in ALLOWED_DOMAINS
    return False


def title(event):
    actor = event.get("username", "<USER_NOT_FOUND>")
    target = event.get("targetUsername", "<USER_NOT_FOUND>")
    org_id = event.get("orgId", "<ORG_NOT_FOUND>")
    return f"MongoDB Atlas: [{actor}] invited external user [{target}] to the org [{org_id}]"


def alert_context(event):
    return mongodb_alert_context(event)

Rule specification

AnalysisType: rule
Description: "An external user has been invited to a MongoDB org. "
DisplayName: "MongoDB External User Invited"
Enabled: true
Filename: mongodb_external_user_invited.py
Severity: Medium
Reference: https://www.mongodb.com/docs/v4.2/tutorial/create-users/
Tags:
  - Configuration Required
DedupPeriodMinutes: 60
LogTypes:
  - MongoDB.OrganizationEvent
RuleID: "MongoDB.External.UserInvited"
Threshold: 1

Stages and Predicates

Fires on MongoDB.OrganizationEvent events when the condition below holds.

Condition

  • eventTypeName is INVITED_TO_ORG

This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
username
target_usernametargetUsername
org_idorgId
remote_addressremoteAddress

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "created": "2023-06-07 16:57:55",
  "currentValue": {},
  "eventTypeName": "INVITED_TO_ORG",
  "id": "6480b7139bd8a012345ABCDE",
  "isGlobalAdmin": false,
  "links": [
    {
      "href": "https://cloud.mongodb.com/api/atlas/v1.0/orgs/12345xyzlmnce4f17d6e8e130/events/6480b7139bd8a012345ABCDE",
      "rel": "self"
    }
  ],
  "orgId": "12345xyzlmnce4f17d6e8e130",
  "p_event_time": "2023-06-07 16:57:55",
  "p_log_type": "MongoDB.OrganizationEvent",
  "p_parse_time": "2023-06-07 17:04:42.59",
  "p_row_id": "ea276b16216684d9e198c0d0188a3d",
  "p_schema_version": 0,
  "p_source_id": "7c3cb124-9c30-492c-99e6-46518c232d73",
  "p_source_label": "MongoDB",
  "remoteAddress": "1.2.3.4",
  "targetUsername": "outsider@other.com",
  "userId": "647f654f93bebc69123abc1",
  "username": "user@company.com"
}

MongoDB External User Invited (no config)

#
Severity
high
Log types
MongoDB.OrganizationEvent
Reference
www.mongodb.com
Source
github.com/panther-labs/panther-analysis

An external user has been invited to a MongoDB org (no config).

Detection logic

from panther_mongodb_helpers import mongodb_alert_context


def rule(event):
    if event.get("eventTypeName", "") != "INVITED_TO_ORG":
        return False

    user_who_sent_an_invitation = event.get("username", "")
    user_who_was_invited = event.get("targetUsername", "")
    domain = user_who_sent_an_invitation.split("@")[-1]

    email_domains_are_different = not user_who_was_invited.endswith(domain)
    return email_domains_are_different


def title(event):
    actor = event.get("username", "<USER_NOT_FOUND>")
    target = event.get("targetUsername", "<USER_NOT_FOUND>")
    org_id = event.get("orgId", "<ORG_NOT_FOUND>")
    return f"MongoDB Atlas: [{actor}] invited external user [{target}] to the org [{org_id}]"


def alert_context(event):
    return mongodb_alert_context(event)

Rule specification

AnalysisType: rule
Description: "An external user has been invited to a MongoDB org (no config)."
DisplayName: "MongoDB External User Invited (no config)"
Enabled: true
Filename: mongodb_external_user_invited_no_config.py
Severity: High
Reference: https://www.mongodb.com/docs/v4.2/tutorial/create-users/
DedupPeriodMinutes: 60
LogTypes:
  - MongoDB.OrganizationEvent
RuleID: "MongoDB.External.UserInvited.NoConfig"
Threshold: 1

Stages and Predicates

Fires on MongoDB.OrganizationEvent events when the condition below holds.

Condition

  • eventTypeName is INVITED_TO_ORG

This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
username
target_usernametargetUsername
org_idorgId
remote_addressremoteAddress

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "created": "2023-06-07 16:57:55",
  "currentValue": {},
  "eventTypeName": "INVITED_TO_ORG",
  "id": "6480b7139bd8a012345ABCDE",
  "isGlobalAdmin": false,
  "links": [
    {
      "href": "https://cloud.mongodb.com/api/atlas/v1.0/orgs/12345xyzlmnce4f17d6e8e130/events/6480b7139bd8a012345ABCDE",
      "rel": "self"
    }
  ],
  "orgId": "12345xyzlmnce4f17d6e8e130",
  "p_event_time": "2023-06-07 16:57:55",
  "p_log_type": "MongoDB.OrganizationEvent",
  "p_parse_time": "2023-06-07 17:04:42.59",
  "p_row_id": "ea276b16216684d9e198c0d0188a3d",
  "p_schema_version": 0,
  "p_source_id": "7c3cb124-9c30-492c-99e6-46518c232d73",
  "p_source_label": "MongoDB",
  "remoteAddress": "1.2.3.4",
  "targetUsername": "outsider@other.com",
  "userId": "647f654f93bebc69123abc1",
  "username": "user@company.com"
}

MongoDB Identity Provider Activity

#
Severity
medium
Log types
MongoDB.OrganizationEvent
Reference
attack.mitre.org
Source
github.com/panther-labs/panther-analysis

Changes to identity provider settings are privileged activities that should be carefully audited. Attackers may add or change IDP integrations to gain persistence to environments

MITRE ATT&CK coverage

Detection logic

from panther_mongodb_helpers import mongodb_alert_context


def rule(event):
    important_event_types = {
        "FEDERATION_SETTINGS_CREATED",
        "FEDERATION_SETTINGS_DELETED",
        "FEDERATION_SETTINGS_UPDATED",
        "IDENTITY_PROVIDER_CREATED",
        "IDENTITY_PROVIDER_UPDATED",
        "IDENTITY_PROVIDER_DELETED",
        "IDENTITY_PROVIDER_ACTIVATED",
        "IDENTITY_PROVIDER_DEACTIVATED",
        "IDENTITY_PROVIDER_JWKS_REVOKED",
        "OIDC_IDENTITY_PROVIDER_UPDATED",
        "OIDC_IDENTITY_PROVIDER_ENABLED",
        "OIDC_IDENTITY_PROVIDER_DISABLED",
    }
    return event.get("eventTypeName") in important_event_types


def title(event):
    target_username = event.get("targetUsername", "<USER_NOT_FOUND>")
    org_id = event.get("orgId", "<ORG_NOT_FOUND>")

    return f"MongoDB Atlas: User [{target_username}] roles changed in org [{org_id}]"


def alert_context(event):
    return mongodb_alert_context(event)

Rule specification

AnalysisType: rule
Description: "Changes to identity provider settings are privileged activities that should be carefully audited.  Attackers may add or change IDP integrations to gain persistence to environments"
DisplayName: "MongoDB Identity Provider Activity"
Enabled: true
Filename: mongodb_identity_provider_activity.py
Severity: Medium
Reference: https://attack.mitre.org/techniques/T1556/007/
DedupPeriodMinutes: 60
LogTypes:
  - MongoDB.OrganizationEvent
RuleID: "MongoDB.Identity.Provider.Activity"
Threshold: 1

Stages and Predicates

Fires on MongoDB.OrganizationEvent events when the condition below holds.

Condition

  • eventTypeName is one of FEDERATION_SETTINGS_CREATED, FEDERATION_SETTINGS_DELETED, FEDERATION_SETTINGS_UPDATED, IDENTITY_PROVIDER_CREATED, IDENTITY_PROVIDER_UPDATED (+7 more values, see Indicators below)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
eventTypeNamein
  • FEDERATION_SETTINGS_CREATED
  • FEDERATION_SETTINGS_DELETED
  • FEDERATION_SETTINGS_UPDATED
  • IDENTITY_PROVIDER_ACTIVATED
  • IDENTITY_PROVIDER_CREATED
  • IDENTITY_PROVIDER_DEACTIVATED
  • IDENTITY_PROVIDER_DELETED
  • IDENTITY_PROVIDER_JWKS_REVOKED
  • IDENTITY_PROVIDER_UPDATED
  • OIDC_IDENTITY_PROVIDER_DISABLED
  • OIDC_IDENTITY_PROVIDER_ENABLED
  • OIDC_IDENTITY_PROVIDER_UPDATED
field:"eventTypeName" kind:in

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
username
target_usernametargetUsername
org_idorgId
remote_addressremoteAddress

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "eventTypeName": "FEDERATION_SETTINGS_CREATED"
}

MongoDB logging toggled

#
Severity
low
Log types
MongoDB.ProjectEvent
Reference
attack.mitre.org
Source
github.com/panther-labs/panther-analysis

MongoDB logging toggled

MITRE ATT&CK coverage

Detection logic

from panther_mongodb_helpers import mongodb_alert_context


def rule(event):
    return event.get("eventTypeName", "") == "AUDIT_LOG_CONFIGURATION_UPDATED"


def title(event):
    user = event.get("username", "<USER_NOT_FOUND>")
    return f"MongoDB: [{user}] has changed logging configuration."


def alert_context(event):
    return mongodb_alert_context(event)

Rule specification

AnalysisType: rule
Description: "MongoDB logging toggled"
DisplayName: "MongoDB logging toggled"
Enabled: true
Filename: mongodb_logging_toggled.py
Severity: Low
Reference: https://attack.mitre.org/techniques/T1562/008/
DedupPeriodMinutes: 60
LogTypes:
  - MongoDB.ProjectEvent
RuleID: "MongoDB.Logging.Toggled"
Threshold: 1

Stages and Predicates

Fires on MongoDB.ProjectEvent events when the condition below holds.

Condition

  • eventTypeName is AUDIT_LOG_CONFIGURATION_UPDATED

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
username
target_usernametargetUsername
org_idorgId
remote_addressremoteAddress

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "created": "2023-06-07 16:57:55",
  "currentValue": {},
  "eventTypeName": "AUDIT_LOG_CONFIGURATION_UPDATED",
  "id": "6480b7139bd8a012345ABCDE",
  "isGlobalAdmin": false,
  "links": [
    {
      "href": "https://cloud.mongodb.com/api/atlas/v1.0/orgs/12345xyzlmnce4f17d6e8e130/events/6480b7139bd8a012345ABCDE",
      "rel": "self"
    }
  ],
  "orgId": "12345xyzlmnce4f17d6e8e130",
  "p_event_time": "2023-06-07 16:57:55",
  "p_log_type": "MongoDB.OrganizationEvent",
  "p_parse_time": "2023-06-07 17:04:42.59",
  "p_row_id": "ea276b16216684d9e198c0d0188a3d",
  "p_schema_version": 0,
  "p_source_id": "7c3cb124-9c30-492c-99e6-46518c232d73",
  "p_source_label": "MongoDB",
  "remoteAddress": "1.2.3.4",
  "targetUsername": "insider@company.com",
  "userId": "647f654f93bebc69123abc1",
  "username": "user@company.com"
}

MongoDB org membership restriction disabled

#
Severity
high
Log types
MongoDB.OrganizationEvent
Tags
MongoDB, Persistence, Modify Authentication Process, Conditional Access Policies
Reference
www.mongodb.com
Source
github.com/panther-labs/panther-analysis

You can configure Atlas to require API access lists at the organization level. When you enable IP access list for the Atlas Administration API, all API calls in that organization must originate from a valid entry in the associated Atlas Administration API key access list. This rule detects when IP access list is disabled

MITRE ATT&CK coverage

Detection logic

from panther_mongodb_helpers import mongodb_alert_context


def rule(event):
    return event.get("eventTypeName", "") == "ORG_PUBLIC_API_ACCESS_LIST_NOT_REQUIRED"


def title(event):
    user = event.get("username", "<USER_NOT_FOUND>")
    return f"MongoDB: [{user}] has disabled IP access list for the Atlas Administration API"


def alert_context(event):
    return mongodb_alert_context(event)

Rule specification

AnalysisType: rule
Description:
  You can configure Atlas to require API access lists at the organization level.
  When you enable IP access list for the Atlas Administration API, all API calls in that organization must originate
  from a valid entry in the associated Atlas Administration API key access list.
  This rule detects when IP access list is disabled
DisplayName: "MongoDB org membership restriction disabled"
Enabled: true
LogTypes:
  - MongoDB.OrganizationEvent
RuleID: "MongoDB.org.Membership.Restriction.Disabled"
Filename: mongodb_org_membership_restriction_disabled.py
Severity: High
Tags:
  - MongoDB
  - Persistence
  - Modify Authentication Process
  - Conditional Access Policies
Reports:
  MITRE ATT&CK:
    - TA0003:T1556.009 # Modify Authentication Process
Reference: https://www.mongodb.com/docs/atlas/tutorial/manage-organizations/
Runbook: Check if this activity is legitimate. If not, re-enable IP access list for the Atlas Administration API
DedupPeriodMinutes: 60
Threshold: 1

Stages and Predicates

Fires on MongoDB.OrganizationEvent events when the condition below holds.

Condition

  • eventTypeName is ORG_PUBLIC_API_ACCESS_LIST_NOT_REQUIRED

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
eventTypeNameeq
  • ORG_PUBLIC_API_ACCESS_LIST_NOT_REQUIRED
field:"eventTypeName" kind:eq value:"ORG_PUBLIC_API_ACCESS_LIST_NOT_REQUIRED"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
username
target_usernametargetUsername
org_idorgId
remote_addressremoteAddress

Response runbook

Check if this activity is legitimate. If not, re-enable IP access list for the Atlas Administration API

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "created": "2024-04-03 15:03:51.000000000",
  "currentValue": {},
  "eventTypeName": "ORG_PUBLIC_API_ACCESS_LIST_NOT_REQUIRED",
  "id": "alert_id",
  "isGlobalAdmin": false,
  "orgId": "some_org_id",
  "remoteAddress": "1.2.3.4",
  "userId": "user_id",
  "username": "some_user@company.com"
}

MongoDB security alerts disabled or deleted

#
Severity
high
Log types
MongoDB.OrganizationEvent
Reference
www.mongodb.com
Source
github.com/panther-labs/panther-analysis

MongoDB provides security alerting policies for notifying admins when certain conditions are met. This rule detects when these policies are disabled or deleted.

MITRE ATT&CK coverage

TacticTechniques
Defense Impairment

Detection logic

from panther_mongodb_helpers import mongodb_alert_context


def rule(event):
    return event.get("eventTypeName", "") in [
        "ALERT_CONFIG_DISABLED_AUDIT",
        "ALERT_CONFIG_DELETED_AUDIT",
    ]


def title(event):
    user = event.get("username", "<USER_NOT_FOUND>")
    alert_id = event.get("alertConfigId", "<ALERT_NOT_FOUND>")
    return f"MongoDB: [{user}] has disabled or deleted security alert [{alert_id}]"


def alert_context(event):
    context = mongodb_alert_context(event)
    context["alertConfigId"] = event.get("alertConfigId", "<ALERT_NOT_FOUND>")
    return context

Rule specification

AnalysisType: rule
Description:
  MongoDB provides security alerting policies for notifying admins when certain conditions are met.
  This rule detects when these policies are disabled or deleted.
DisplayName: "MongoDB security alerts disabled or deleted"
Enabled: true
LogTypes:
  - MongoDB.OrganizationEvent
RuleID: "MongoDB.Alerting.Disabled.Or.Deleted"
Filename: mongodb_alerting_disabled.py
Severity: High
Reports:
  MITRE ATT&CK:
    - TA0005:T1562.001 # Impair Defenses: Disable or Modify Tools
Reference: https://www.mongodb.com/docs/atlas/configure-alerts/
Runbook: Re-enable security alerts
DedupPeriodMinutes: 60
Threshold: 1

Stages and Predicates

Fires on MongoDB.OrganizationEvent events when the condition below holds.

Condition

  • eventTypeName is one of ALERT_CONFIG_DISABLED_AUDIT, ALERT_CONFIG_DELETED_AUDIT

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
eventTypeNamein
  • ALERT_CONFIG_DELETED_AUDIT
  • ALERT_CONFIG_DISABLED_AUDIT
field:"eventTypeName" kind:in

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
username
target_usernametargetUsername
org_idorgId
remote_addressremoteAddress
alertConfigId

Response runbook

Re-enable security alerts

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "alertConfigId": "alert_id",
  "created": "2024-04-01 11:58:52.000000000",
  "currentValue": {},
  "eventTypeName": "ALERT_CONFIG_DELETED_AUDIT",
  "id": "alert_id",
  "isGlobalAdmin": false,
  "links": [],
  "orgId": "some_org_id",
  "remoteAddress": "1.2.3.4",
  "userId": "user_id",
  "username": "some_user@company.com"
}

MongoDB user roles changed

#
Severity
low
Log types
MongoDB.OrganizationEvent
Reference
www.mongodb.com
Source
github.com/panther-labs/panther-analysis

User roles changed.

Detection logic

from panther_mongodb_helpers import mongodb_alert_context


def rule(event):
    return event.get("eventTypeName") == "USER_ROLES_CHANGED_AUDIT"


def title(event):
    target_username = event.get("targetUsername", "<USER_NOT_FOUND>")
    org_id = event.get("orgId", "<ORG_NOT_FOUND>")

    return f"MongoDB Atlas: User [{target_username}] roles changed in org [{org_id}]"


def alert_context(event):
    return mongodb_alert_context(event)

Rule specification

AnalysisType: rule
Description: "User roles changed."
DisplayName: "MongoDB user roles changed"
Enabled: true
Filename: mongodb_user_roles_changed.py
Severity: Low
Reference: https://www.mongodb.com/docs/v4.2/tutorial/create-users/
DedupPeriodMinutes: 60
LogTypes:
  - MongoDB.OrganizationEvent
RuleID: "MongoDB.User.Roles.Changed"
Threshold: 1

Stages and Predicates

Fires on MongoDB.OrganizationEvent events when the condition below holds.

Condition

  • eventTypeName is USER_ROLES_CHANGED_AUDIT

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
username
target_usernametargetUsername
org_idorgId
remote_addressremoteAddress

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "created": "2023-06-07 16:57:55",
  "currentValue": {},
  "eventTypeName": "USER_ROLES_CHANGED_AUDIT",
  "id": "6480b7139bd8a012345ABCDE",
  "isGlobalAdmin": false,
  "links": [
    {
      "href": "https://cloud.mongodb.com/api/atlas/v1.0/orgs/12345xyzlmnce4f17d6e8e130/events/6480b7139bd8a012345ABCDE",
      "rel": "self"
    }
  ],
  "orgId": "12345xyzlmnce4f17d6e8e130",
  "p_event_time": "2023-06-07 16:57:55",
  "p_log_type": "MongoDB.OrganizationEvent",
  "p_parse_time": "2023-06-07 17:04:42.59",
  "p_row_id": "ea276b16216684d9e198c0d0188a3d",
  "p_schema_version": 0,
  "p_source_id": "7c3cb124-9c30-492c-99e6-46518c232d73",
  "p_source_label": "MongoDB",
  "remoteAddress": "1.2.3.4",
  "targetUsername": "insider@company.com",
  "userId": "647f654f93bebc69123abc1",
  "username": "user@company.com"
}

MongoDB user was created or deleted

#
Severity
medium
Log types
MongoDB.OrganizationEvent
Reference
www.mongodb.com
Source
github.com/panther-labs/panther-analysis

User was created or deleted.

Detection logic

from panther_mongodb_helpers import mongodb_alert_context


def rule(event):
    return event.get("eventTypeName", "") in ("JOINED_ORG", "REMOVED_FROM_ORG")


def title(event):
    event_name = event.get("eventTypeName")
    target_username = event.get("targetUsername", "<USER_NOT_FOUND>")
    org_id = event.get("orgId", "<ORG_NOT_FOUND>")
    action = "has joined org" if event_name == "JOINED_ORG" else "was removed from org"

    return f"MongoDB Atlas: [{target_username}] {action} [{org_id}]"


def alert_context(event):
    return mongodb_alert_context(event)

Rule specification

AnalysisType: rule
Description: "User was created or deleted."
DisplayName: "MongoDB user was created or deleted"
Enabled: true
Filename: mongodb_user_created_or_deleted.py
Severity: Medium
Reference: https://www.mongodb.com/docs/v4.2/tutorial/create-users/
DedupPeriodMinutes: 60
LogTypes:
  - MongoDB.OrganizationEvent
RuleID: "MongoDB.User.Created.Or.Deleted"
Threshold: 1

Stages and Predicates

Fires on MongoDB.OrganizationEvent events when the condition below holds.

Condition

  • eventTypeName is one of JOINED_ORG, REMOVED_FROM_ORG

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
eventTypeNamein
  • JOINED_ORG
  • REMOVED_FROM_ORG
field:"eventTypeName" kind:in

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
username
target_usernametargetUsername
org_idorgId
remote_addressremoteAddress

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "created": "2023-06-07 16:57:55",
  "currentValue": {},
  "eventTypeName": "JOINED_ORG",
  "id": "6480b7139bd8a012345ABCDE",
  "isGlobalAdmin": false,
  "links": [
    {
      "href": "https://cloud.mongodb.com/api/atlas/v1.0/orgs/12345xyzlmnce4f17d6e8e130/events/6480b7139bd8a012345ABCDE",
      "rel": "self"
    }
  ],
  "orgId": "12345xyzlmnce4f17d6e8e130",
  "p_event_time": "2023-06-07 16:57:55",
  "p_log_type": "MongoDB.OrganizationEvent",
  "p_parse_time": "2023-06-07 17:04:42.59",
  "p_row_id": "ea276b16216684d9e198c0d0188a3d",
  "p_schema_version": 0,
  "p_source_id": "7c3cb124-9c30-492c-99e6-46518c232d73",
  "p_source_label": "MongoDB",
  "remoteAddress": "1.2.3.4",
  "targetUsername": "insider@company.com",
  "userId": "647f654f93bebc69123abc1",
  "username": "user@company.com"
}