Monitoring Domain Group Membership Changes With ELK

Khoa previously wrote about monitoring AD Group Membership changes using his Powershell script which can be found here.

In this article we will be setting up a Logstash filter that will look for Event Ids that match the Security Group Management logs generated by your Domain Controller for long term storage. This will allow us to look back through historical data and see when groups were created, deleted, and whether users were added/removed.

These are the Event ID’s that we’re interested in which can be found in this MS Technet article

ID Event Message
4727 A security-enabled global group was created
4728 A member was added to a security-enabled global group
4729 A member was removed from a security-enabled global group
4730 A security-enabled global group was deleted
4731 A security-enabled local group was created
4732 A member was added to a security-enabled local group
4733 A member was removed from a security-enabled local group
4734 A security-enabled local group was deleted
4735 A security-enabled local group was changed
4737 A security-enabled global group was changed
4754 A security-enabled universal group was created
4755 A security-enabled universal group was changed
4756 A member was added to a security-enabled universal group
4757 A member was removed from a security-enabled universal group
4758 A security-enabled universal group was deleted
4764 A group’s type was changed

Note: These events might not be setup to be audited by your Domain Controller, so ensure you are selecting the ones you are interested in.

Knowing these Event ID’s is great; however, it’s difficult just seeing the Event ID’s as they get generated, and having to look at each individual log to see the raw message which tells us what kind of event that is. This is time-consuming; therefore, let’s make it simpler by adding the following to your logstash configuration.

Logstash Config:

# Active Directory - Security Group Management

filter {
  if "winlogbeat" in [tags] and [event_id] == 4727  {
   mutate { 
   add_field => { "short_message" => "A security-enabled global group was created" }
  } 
 }
 else if [event_id] == 4728 {
   mutate { 
   add_field => { "short_message" => "A member was added to a security-enabled global group" }
  } 
 }
 else if [event_id] == 4729 {
   mutate { 
   add_field => { "short_message" => "A member was removed from a security-enabled global group" }
  } 
 }
 else if [event_id] == 4730 {
   mutate { 
   add_field => { "short_message" => "A security-enabled global group was deleted" }
  } 
 }
 else if [event_id] == 4731 {
   mutate { 
   add_field => { "short_message" => "A security-enabled local group was created" }
  } 
 }
 else if [event_id] == 4732 {
   mutate { 
   add_field => { "short_message" => "A member was added to a security-enabled local group" }
  } 
 }
 else if [event_id] == 4733 {
   mutate { 
   add_field => { "short_message" => "A member was removed from a security-enabled local group" }
  } 
 }
 else if [event_id] == 4734  {
   mutate { 
   add_field => { "short_message" => "A security-enabled local group was deleted" }
  } 
 }
 else if [event_id] == 4735 {
   mutate { 
   add_field => { "short_message" => "A security-enabled local group was changed" }
  } 
 }
 else if [event_id] == 4737 {
   mutate { 
   add_field => { "short_message" => "A security-enabled global group was changed" }
  } 
 }
 else if [event_id] == 4754 {
   mutate { 
   add_field => { "short_message" => "A security-enabled universal group was created" }
  } 
 }
 else if [event_id] == 4755 {
   mutate { 
   add_field => { "short_message" => "A security-enabled universal group was changed" }
  } 
 }
 else if [event_id] == 4756 {
   mutate { 
   add_field => { "short_message" => "A member was added to a security-enabled universal group" }
  } 
 }
 else if [event_id] == 4757 {
   mutate { 
   add_field => { "short_message" => "A member was removed from a security-enabled universal group" }
  } 
 }
 else if [event_id] == 4758 {
   mutate { 
   add_field => { "short_message" => "A security-enabled universal group was deleted" }
  } 
 }
 else if [event_id] == 4764 {
   mutate { 
   add_field => { "short_message" => "A group's type was changed" }
  } 
 }
 
}

Here’s a full Logstash config that includes these changes:

input {
  beats {
    port => 7510
	tags => [ "winlogbeat" ]
  }
}

# Active Directory - Security Group Management


filter {
  if "winlogbeat" in [tags] and [log_name] == "Security" and [event_id] == 4727  {
   mutate { 
   add_field => { "short_message" => "A security-enabled global group was created" }
  } 
 }
 else if [event_id] == 4728 {
   mutate { 
   add_field => { "short_message" => "A member was added to a security-enabled global group" }
  } 
 }
 else if [event_id] == 4729 {
   mutate { 
   add_field => { "short_message" => "A member was removed from a security-enabled global group" }
  } 
 }
 else if [event_id] == 4730 {
   mutate { 
   add_field => { "short_message" => "A security-enabled global group was deleted" }
  } 
 }
 else if [event_id] == 4731 {
   mutate { 
   add_field => { "short_message" => "A security-enabled local group was created" }
  } 
 }
 else if [event_id] == 4732 {
   mutate { 
   add_field => { "short_message" => "A member was added to a security-enabled local group" }
  } 
 }
 else if [event_id] == 4733 {
   mutate { 
   add_field => { "short_message" => "A member was removed from a security-enabled local group" }
  } 
 }
 else if [event_id] == 4734  {
   mutate { 
   add_field => { "short_message" => "A security-enabled local group was deleted" }
  } 
 }
 else if [event_id] == 4735 {
   mutate { 
   add_field => { "short_message" => "A security-enabled local group was changed" }
  } 
 }
 else if [event_id] == 4737 {
   mutate { 
   add_field => { "short_message" => "A security-enabled global group was changed" }
  } 
 }
 else if [event_id] == 4754 {
   mutate { 
   add_field => { "short_message" => "A security-enabled universal group was created" }
  } 
 }
 else if [event_id] == 4755 {
   mutate { 
   add_field => { "short_message" => "A security-enabled universal group was changed" }
  } 
 }
 else if [event_id] == 4756 {
   mutate { 
   add_field => { "short_message" => "A member was added to a security-enabled universal group" }
  } 
 }
 else if [event_id] == 4757 {
   mutate { 
   add_field => { "short_message" => "A member was removed from a security-enabled universal group" }
  } 
 }
 else if [event_id] == 4758 {
   mutate { 
   add_field => { "short_message" => "A security-enabled universal group was deleted" }
  } 
 }
 else if [event_id] == 4764 {
   mutate { 
   add_field => { "short_message" => "A group's type was changed" }
  } 
 }
 
}

output {
    elasticsearch {
    hosts => ["http://elasticsearchserver:9200"]
	index => "logstash-winlogbeat-%{+xxxx.ww}"

  }
 }

So what changed?

Now anytime a group membership activity is changed, the message will be parsed through logstash and based on the event ID, a short_message field will added which will indicate the type of action that occurred.

Here’s some example of the changes we can see.

  • A Security Group was created
  • A user was added or removed from that particular group

At the end you may create a Dashboard that displays the Event IDs that you might be interested in:

You may search by specific Usernames (Such as your Domain admins, and see who has made any changes).

Here’s the Raw logs along with the field names which will help in creating your Dashboard in Kibana.

Active directory is great, and leveraging Windows Event Forwarder + ELK is a great free alternative to purchasing an vendor-provided application; however, you do have to spend some time setting it up.

Since you read this far, I’ll show you how to create a simple visualization in Kibana to filter these Security Group Management events generated in your environment.

In Kibana

  1. Navigate to Visualization
  2. Create New Visualization
  3. Select “Data Table”
  4. Select your Index
  5. On the search bar paste the following query:
    event_id: 4727 OR event_id: 4728 OR event_id: 4729 OR event_id: 4730 OR event_id: 4731 OR event_id: 4732 OR event_id: 4733 OR event_id: 4734 OR event_id: 4735 OR event_id: 4737 OR event_id: 4754 OR event_id: 4755 OR event_id: 4756 OR event_id: 4757 OR event_id: 4758 OR event_id: 4764
  6. Click on Add Metrics:
    Aggregation: Terms
    Field: Event_id
  7. Add Metrics again
    Aggregation: Terms
    Field: short_message.keyword
  8. Click on the Search button to see your visualization generated. Here’s an example of the past 24 hours and the events it found.

You may then create a dashboard and add other visualizations that you might find interesting.

Note: You will need to forward your windows event logs using Winlogbeat so that your field names match the ones shown in this article. I wrote an article on setting that up in your endpoint which may be accessed here.

Here’s some useful fields to start off with:

event_data.SubjectUserName = The individual that made the changes (e.g. Domain Admin)

event_data.SamAccountName = The Group that was modified (e.g. SuperSecretGroup)

event_data.MemberName = The Individual that was added/removed to a group. (e.g. CN=Pablo Delgado,OU=Users,DC=SuperSecret,DC=com)

I hope this helps out, the next article I will be focusing on other Active directory dashboards such as Account Failure/Lockouts/Account Creations, etc.

Thank you

 

0 0 votes
Article Rating
Subscribe
Notify of
guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Andrew Wataszko
Andrew Wataszko
4 years ago

Hi,

For some reason this isn’t adding the short_message field. Logstash is processing the eventlogs, I can see everything, just no short_message. Any ideas?

Thanks,
Andrew