# SIEM Command Line Auditing 4688 - 4689

**URL:** <https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656>\
**Category:** SIEM\
**Created:** [October 8, 2019, 11:49am UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656 "2019-10-08T11:49:19Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![willemdh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/willemdh/32/16922_2.png) [@willemdh](https://discuss.elastic.co/u/willemdh)\
**Post date:** [October 8, 2019, 11:49am UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/1 "2019-10-08T11:49:19Z")

</div>

Hello,

2 of the most interesting event id's in siem are 4688 and 4689, which can be enabled with a gpo and enable us to monitor every command used in your network.

Interesting fields are:

```
winlog.event_data.NewProcessName
winlog.event_data.ParentProcessName
winlog.event_data.ProcessName

```

Unfortunately some of the processes audited are located in %USERPROFILE% folder, which means it looks like this:

`C:\Users\username\AppData\Local\GitHubDesktop\app-2.2.0\resources\app\git\mingw64\bin\git.exe`

It would be nice if the security processor of Winlogbeat could get expanded and the executable itself could be extracted to process.name

That would enable us to do all kinds of siem related interesting analytics on them.

Is this already on a to do? Should I make a GitHub issue?

Grtz

Willem

---

<div class="post-metadata">

**Author:** ![willemdh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/willemdh/32/16922_2.png) [@willemdh](https://discuss.elastic.co/u/willemdh)\
**Post date:** [October 11, 2019, 8:26am UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/2 "2019-10-11T08:26:19Z")

</div>

Some extra documentation =\> [https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/event.aspx?eventID=4688](https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/event.aspx?eventID=4688)

It would be even better if fields such as Token Elevation Type and Mandatory Label would be translated to a readable value.

| SID | RID | RID label | Meaning |
| --- | --- | --- | --- |
| S-1-16-0 | 0x00000000 | SECURITY\_MANDATORY\_UNTRUSTED\_RID | Untrusted. |
| S-1-16-4096 | 0x00001000 | SECURITY\_MANDATORY\_LOW\_RID | Low integrity. |
| S-1-16-8192 | 0x00002000 | SECURITY\_MANDATORY\_MEDIUM\_RID | Medium integrity. |
| S-1-16-8448 | 0x00002100 | SECURITY\_MANDATORY\_MEDIUM\_PLUS\_RID | Medium high integrity. |
| S-1-16-12288 | 0X00003000 | SECURITY\_MANDATORY\_HIGH\_RID | High integrity. |
| S-1-16-16384 | 0x00004000 | SECURITY\_MANDATORY\_SYSTEM\_RID | System integrity. |
| S-1-16-20480 | 0x00005000 | SECURITY\_MANDATORY\_PROTECTED\_PROCESS\_RID | Protected process. |

**Token Elevation Type** : Token elevation is about User Account Control

- %% **1936** - Type 1 is a full token with no privileges removed or groups disabled. A full token is only used if User Account Control is disabled or if the user is the built-in Administrator account or a service account.
- %% **1937** - Type 2 is an elevated token with no privileges removed or groups disabled. An elevated token is used when User Account Control is enabled and the user chooses to start the program using Run as administrator. An elevated token is also used when an application is configured to always require administrative privilege or to always require maximum privilege, and the user is a member of the Administrators group.
- %% **1938** - Type 3 is the normal value when UAC is enabled and a user simply starts a program from the Start Menu. It's a limited token with administrative privileges removed and administrative groups disabled. The limited token is used when User Account Control is enabled, the application does not require administrative privilege, and the user does not choose to start the program using Run as administrator.

Grtz

---

<div class="post-metadata">

**Author:** ![tudor](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/tudor/32/3753_2.png) [@tudor](https://discuss.elastic.co/u/tudor)\
**Post date:** [October 14, 2019, 10:41am UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/3 "2019-10-14T10:41:12Z")

</div>

As a workaround, I'm thinking you might be able to use either the [Dissect processor](https://www.elastic.co/guide/en/beats/winlogbeat/master/dissect.html) or the [script processor](https://www.elastic.co/guide/en/beats/winlogbeat/master/processor-script.html) to extract the name of the process like you want it. You can use those in the Winlogbeat config.

---

<div class="post-metadata">

**Author:** ![willemdh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/willemdh/32/16922_2.png) [@willemdh](https://discuss.elastic.co/u/willemdh)\
**Post date:** [October 14, 2019, 11:15am UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/4 "2019-10-14T11:15:41Z")

</div>

@tudor Thanks for the tip. Tried using dissect to get the filename, but failed for now.

```
- dissect:
when:
  equals:
    event.code: 4688
tokenizer: "%{myprocess.path}\\%{myprocess.file}"
field: "winlog.event_data.NewProcessName"

```

How can I configure the tokenizer so it saves the path untill the last '\'?

Result now:

![image](https://us1.discourse-cdn.com/elastic/original/3X/0/b/0b3e3f3d4648fcf867a8706029f63afa4d79009b.png)

Please note that I don't know beforehand from what path commands will be executed.. So there could be x number of subfolders...

Also tried with:

```
tokenizer: "%{myprocess.path}\\%{myprocess.file/1}.%{myprocess.file/2}"

```

WHich is able to extract . extension somehow , but the moment there is a '.' in the path, it fails again (such as C:\Users\mysuer\AppData\Local\GitHubDesktop\app-2.2.1\GitHubDesktop.exe)

![image](https://us1.discourse-cdn.com/elastic/original/3X/5/d/5d8ffd9cc7fe96445b98b1c5dea8d2fb3c7f9cff.png)

Starting to doubt this is even possible with dissect, I tried updating the security js file to this:

```
var securitycommand = (function () {
    var path = require("path");
    var processor = require("processor");
    var winlogbeat = require("winlogbeat");

    var addAuthSuccess = new processor.AddFields({
        fields: {
            "event.category": "authentication",
            "event.type": "authentication_success",
        },
        target: "",
    });

    var addAuthFailed = new processor.AddFields({
        fields: {
            "event.category": "authentication",
            "event.type": "authentication_failure",
        },
        target: "",
    });

    var convertAuthentication = new processor.Convert({
        fields: [
            {from: "winlog.event_data.TargetUserSid", to: "user.id"},
            {from: "winlog.event_data.TargetUserName", to: "user.name"},
            {from: "winlog.event_data.TargetDomainName", to: "user.domain"},
            {from: "winlog.event_data.ProcessId", to: "process.pid", type: "long"},
            {from: "winlog.event_data.ProcessName", to: "process.executable"},
            {from: "winlog.event_data.IpAddress", to: "source.ip", type: "ip"},
            {from: "winlog.event_data.IpPort", to: "source.port", type: "long"},
            {from: "winlog.event_data.WorkstationName", to: "source.domain"},
        ],
        mode: "rename",
        ignore_missing: true,
        fail_on_error: false,
    });

    var setProcessNameUsingExe = function(evt) {
        var name = evt.Get("process.name");
        if (name) {
            return;
        }
        var exe = evt.Get("process.executable");
        evt.Put("process.name", path.basename(exe));
    };

    var setProcessNameUsingNewProcessName = function(evt) {
        var processnamefull = evt.Get("winlog.event_data.NewProcessName");
        evt.Put("process.name", path.basename(processnamefull));
    };

    var logonSuccess = new processor.Chain()
        .Add(addAuthSuccess)
        .Add(convertAuthentication)
        .Add(setProcessNameUsingExe)
        .Build();

    var logonFailed = new processor.Chain()
        .Add(addAuthFailed)
        .Add(convertAuthentication)
        .Add(setProcessNameUsingExe)
        .Build();

    var processCreated = new processor.Chain()
        .Add(setProcessNameUsingNewProcessName)
        .Build();
		
    return {
        // 4624 - An account was successfully logged on.
        4624: logonSuccess.Run,

        // 4625 - An account failed to log on.
        4625: logonFailed.Run,

        // 4648 - A logon was attempted using explicit credentials.
        4648: logonSuccess.Run,
		
		// 4688 - A process was created
		4688: processCreated.Run,

        process: function(evt) {
            var event_id = evt.Get("winlog.event_id");
            var processor = this[event_id];
            if (processor === undefined) {
                return;
            }
            processor(evt);
        },
    };
})();

function process(evt) {
    return securitycommand.process(evt);
}

```

But the result is that process.name seems to be `null` all the time..

Any advice to get this working is welcome. 🙂

Tx

Willem

---

<div class="post-metadata">

**Author:** ![willemdh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/willemdh/32/16922_2.png) [@willemdh](https://discuss.elastic.co/u/willemdh)\
**Post date:** [October 14, 2019, 12:34pm UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/5 "2019-10-14T12:34:55Z")

</div>

Seems I gave up too early.. The events are forwarded with WEF and have some latency..

So this works perfectly:

```
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

var securitycommand = (function () {
    var path = require("path");
    var processor = require("processor");
    var winlogbeat = require("winlogbeat");

    var addAuthSuccess = new processor.AddFields({
        fields: {
            "event.category": "authentication",
            "event.type": "authentication_success",
        },
        target: "",
    });

    var addAuthFailed = new processor.AddFields({
        fields: {
            "event.category": "authentication",
            "event.type": "authentication_failure",
        },
        target: "",
    });

    var convertAuthentication = new processor.Convert({
        fields: [
            {from: "winlog.event_data.TargetUserSid", to: "user.id"},
            {from: "winlog.event_data.TargetUserName", to: "user.name"},
            {from: "winlog.event_data.TargetDomainName", to: "user.domain"},
            {from: "winlog.event_data.ProcessId", to: "process.pid", type: "long"},
            {from: "winlog.event_data.ProcessName", to: "process.executable"},
            {from: "winlog.event_data.IpAddress", to: "source.ip", type: "ip"},
            {from: "winlog.event_data.IpPort", to: "source.port", type: "long"},
            {from: "winlog.event_data.WorkstationName", to: "source.domain"},
        ],
        mode: "rename",
        ignore_missing: true,
        fail_on_error: false,
    });

    var setProcessNameUsingExe = function(evt) {
        var name = evt.Get("process.name");
        if (name) {
            return;
        }
        var exe = evt.Get("process.executable");
        evt.Put("process.name", path.basename(exe));
    };

    var setProcessNameUsingNewProcessName = function(evt) {
        var processnamefull = evt.Get("winlog.event_data.NewProcessName");
        evt.Put("process.name", path.basename(processnamefull));
    };

    var logonSuccess = new processor.Chain()
        .Add(addAuthSuccess)
        .Add(convertAuthentication)
        .Add(setProcessNameUsingExe)
        .Build();

    var logonFailed = new processor.Chain()
        .Add(addAuthFailed)
        .Add(convertAuthentication)
        .Add(setProcessNameUsingExe)
        .Build();

    var processCreated = new processor.Chain()
        .Add(setProcessNameUsingNewProcessName)
        .Build();
		
    return {
        // 4624 - An account was successfully logged on.
        4624: logonSuccess.Run,

        // 4625 - An account failed to log on.
        4625: logonFailed.Run,

        // 4648 - A logon was attempted using explicit credentials.
        4648: logonSuccess.Run,
		
		// 4688 - A process was created
		4688: processCreated.Run,

        process: function(evt) {
            var event_id = evt.Get("winlog.event_id");
            var processor = this[event_id];
            if (processor === undefined) {
                return;
            }
            processor(evt);
        },
    };
})();

function process(evt) {
    return securitycommand.process(evt);
}

```

Result:

 ![image](https://us1.discourse-cdn.com/elastic/original/3X/b/8/b8a769b9d5b6e2f1b453b8ad138d4b4ad61de6ae.png)

Is this something that could be added to the security module? Imho knowing what commands are launched in your network is very useful for SIEM. Let me know if I should make a feature request?

Grtz

Willem

---

<div class="post-metadata">

**Author:** ![andrewkroh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/andrewkroh/32/3784_2.png) [@andrewkroh](https://discuss.elastic.co/u/andrewkroh)\
**Post date:** [October 14, 2019, 12:39pm UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/6 "2019-10-14T12:39:33Z")

</div>

4688 and 4689 would be excellent additions to the Security module. And what you're attempting should be possible with the `path` module via [`basename(path)`](https://github.com/elastic/beats/blob/93d32099b83b86f1208ca10ad3d4563eafa82a36/libbeat/processors/script/javascript/module/path/path.go#L47).

The module already has some definitions for the token elevation codes. You might just need to do a lookup in the module to use them. [https://github.com/elastic/beats/blob/93d32099b83b86f1208ca10ad3d4563eafa82a36/x-pack/winlogbeat/module/security/config/winlogbeat-security.js#L173-L175](https://github.com/elastic/beats/blob/93d32099b83b86f1208ca10ad3d4563eafa82a36/x-pack/winlogbeat/module/security/config/winlogbeat-security.js#L173-L175)

---

<div class="post-metadata">

**Author:** ![andrewkroh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/andrewkroh/32/3784_2.png) [@andrewkroh](https://discuss.elastic.co/u/andrewkroh)\
**Post date:** [October 14, 2019, 12:45pm UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/7 "2019-10-14T12:45:27Z")

</div>

Yeah, please open up a pull request and we can discuss the changes a bit more.

> [@willemdh](#):
>
> The events are forwarded with WEF

And regarding WEF there's a known issue with the `host.name` value is the value of the forwarder and not the machine that produced the event. [https://github.com/elastic/beats/issues/13920](https://github.com/elastic/beats/issues/13920) As a work-around we have been copying the computer\_name field over to the `host.name` for the ForwardedEvents channel via processor config.

---

<div class="post-metadata">

**Author:** ![willemdh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/willemdh/32/16922_2.png) [@willemdh](https://discuss.elastic.co/u/willemdh)\
**Post date:** [October 14, 2019, 12:45pm UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/8 "2019-10-14T12:45:33Z")

</div>

@andrewkroh Check my latest response, I just needed a little patience. Should I make a feature request in the Beats repo to add 4688 and 4689 to the security module?

---

<div class="post-metadata">

**Author:** ![willemdh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/willemdh/32/16922_2.png) [@willemdh](https://discuss.elastic.co/u/willemdh)\
**Post date:** [October 14, 2019, 12:51pm UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/9 "2019-10-14T12:51:16Z")

</div>

@andrewkroh Seems we crossed paths again... 🙂

I'll start with opening an enhancement request. Afaik you guys are already working on enhancing the security module, see [https://github.com/elastic/beats/pull/13530](https://github.com/elastic/beats/pull/13530)

Not sure yet how my changes should fit into the full story atm..

---

<div class="post-metadata">

**Author:** ![andrewkroh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/andrewkroh/32/3784_2.png) [@andrewkroh](https://discuss.elastic.co/u/andrewkroh)\
**Post date:** [October 14, 2019, 12:54pm UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/10 "2019-10-14T12:54:04Z")

</div>

Your changes should fit in well. You might want to wait until we hit merge on that PR just so that we don't run into a bunch of merge conflicts.

---

<div class="post-metadata">

**Author:** ![willemdh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/willemdh/32/16922_2.png) [@willemdh](https://discuss.elastic.co/u/willemdh)\
**Post date:** [October 14, 2019, 1:01pm UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/11 "2019-10-14T13:01:09Z")

</div>

@andrewkroh For now I created [https://github.com/elastic/beats/issues/14038](https://github.com/elastic/beats/issues/14038)

Once PR 13530 has been done, I'll see if I can create a PR if I find some spare time

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [November 11, 2019, 1:01pm UTC](https://discuss.elastic.co/t/siem-command-line-auditing-4688-4689/202656/12 "2019-11-11T13:01:13Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
