I'm an active contributor to the DeepBlueCLI project, a PowerShell module for threat hunting via Windows event logs. I don't mean for people to think that makes me a PowerShell developer because I'm not. I just Google things, look at how someone else solved the problem, then copy/transform/combine my way to success.
NOTE: I did a keynote presentation a few years ago on propelling your cyber security career that goes into the power of copy/transform/combine as a personal strategy for success. If you check out those slides, be sure to have audio turned up and look at the slides in presentation view.
In the spirit of the Month of PowerShell, I thought it would be a good idea to look at how I apply this in practice to solve problems. I think this will be immediately relatable to everyone -- at the end of the day, we learn a technology to help us solve problems, and PowerShell is no different. Hopefully my process will help you pick up some tips, or at least just be relatable in how you go about solving your own technical challenges.
The Question
I saw a GitHub email for a DeepBlueCLI ticket with a question:
I want to forward the DeepBlueCLI output into a logfile which can then be sent to a Syslog Server. Is there a way to do it? @therajriva
I didn't know the answer to this question, but I thought I'd see what I could figure out. I Google'd powershell syslog.
This search led me to the Posh-SYSLOG. I scrolled through the README.MD file first, but the project doesn't include any use directions in the documentation. Fortunately, the project includes the next-best thing to good documentation: test cases.
The test case script Send-SyslogMessage.Tests.ps1 shows a sample use case for the module:
Send-SyslogMessage -Server $null -Message 'Test Syslog Message' -Severity 'Alert' -Facility 'auth'}
That looks promising, let's test it out!
Testing the Theory
Since DeepBlueCLI is a PowerShell module, it creates objects as the output. The working solution for this question is that we can DeepBlue.ps1 and send the pipeline output to a ForEach-Object loop, sending the DeepBlueCLI alert to a specified Syslog server. First, download DeepBlueCLI and Posh-SYSLOG, unzipping the files to a local directory. For testing purposes, you can also download the free Windows software Kiwi Syslog Server Free Edition from Solarwinds (I installed Kiwi as an application during the installation choices).
NOTE: DeepBlueCLI doesn't have an official release version, but you can still download the module as a zip file by clicking the green Code button and selecting Download ZIP from the drop-down menu.
After downloading DeepBlueCLI and Posh-SYSLOG modules, unzip the files. For this article, I'll assume you have the DeepBlueCLI and Posh-SYSLOG directories in your Downloads folder. Start PowerShell as an administrator by right-clicking on the PowerShell icon and select Run as administrator. Change to your Downloads folder:
PS C:\WINDOWS\system32> cd ~/Downloads PS C:\Users\Sec504\Downloads> dir Directory: C:\Users\Sec504\Downloads Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 6/13/2022 5:02 PM DeepBlueCLI d----- 7/14/2019 11:21 AM Posh-SYSLOG
PowerShell Execution Mode
By default, PowerShell works in the restricted execution mode, where it will not allow third-party, unsigned scripts to execute. This has little practical benefit, since an attacker has many options to bypass this restriction. For this article, we'll change the execution policy to unrestricted (you can always change it back to restricted when you finish with this exercise):
PS C:\Users\Sec504\Downloads> Set-ExecutionPolicy unrestricted -Force PS C:\Users\Sec504\Downloads>
TIP: I added -Force as an argument to avoid the interactive prompt when using this command. Leave -Force off if you feel inclined to read Microsoft's warning about changing the execution policy mode.
Run DeepBlue.ps1
Next, change to the DeepBlue directory and run the DeepBlue.ps1 script, using one of the sample EVTX files included for testing:
PS C:\Users\Sec504\Downloads\DeepBlueCLI> .\DeepBlue.ps1 .\evtx\metasploit-psexec-native-target-security.evtx Date : 9/21/2016 3:41:13 AM Log : Security EventID : 4688 Message : Suspicious Command Line Results : Metasploit-style cmd with pipe (possible use of Meterpreter 'getsystem') Command : cmd.exe /c echo hgabms > \\.\pipe\hgabms Decoded : Date : 9/21/2016 3:40:37 AM Log : Security EventID : 1102 Message : Audit Log Clear Results : The Audit log was cleared. Account Name: IEUser Command : Decoded :
TIP: You can choose any of the sample files in the DeepBlue evtx directory; they all generate at least one detection event.
Here we see a few alerts from DeepBlue, corresponding to a Metasploit-style getsystem attack. Next, let's look at sending this data to the Syslog server.
Import Posh-SYSLOG
We need to import the Posh-SYSLOG command to invoke it as part of the DeepBlueCLI pipeline. Do that by running Import-Module, followed by the path to the Posh-SYSLOG module:
PS C:\Users\Sec504\Downloads\DeepBlueCLI> Import-Module ..\Posh-SYSLOG\Posh-SYSLOG.psd1 PS C:\Users\Sec504\Downloads\DeepBlueCLI>
NOTE: Posh-SYSLOG distributes the PowerShell module as a module manifest data file, which uses the extension .psd1 as opposed to the more familiar .ps1 extension.
Send Syslog Messages
Press the up arrow a few times to recall that previous DeepBlue.ps1 command, then add Send-SysLogMessage to the pipeline in the style we saw in the Posh-SYSLOG test case, as shown here:
PS C:\Users\Sec504\Downloads\DeepBlueCLI> .\DeepBlue.ps1 .\evtx\metasploit-psexec-native-target-security.evtx | ForEach-Object { Send-SyslogMessage -Server '127.0.0.1' -Message "$_.Message - $_.Results" -Severity 'Alert' -Facility 'Local0' }
Let's break down this command step-by-step:
- \DeepBlue.ps1 .\evtx\metasploit-psexec-native-target-security.evtx | : Run DeepBlueCLI, reading from an EVTX file; start a pipeline
- ForEach-Object { : Start a loop for object returned by DeepBlue.ps1, executing the code block until the closing } for each object
- Send-SyslogMessage : Invoke the Send-SyslogMessage cmdlet, part of the Posh-SYSLOG module
- -Server '127.0.0.1' : Specify the destination Syslog server (our Kiwi server at 127.0.0.1 or the local system)
- -Message "\(_.Message - $_.Results" : Specify the message to send in the Syslog payload where \)_ is the current object in the ForEach-Object loop; I opted to concatenate the DeepBlueCLI Message and Results parameter with a hyphen separating the two values using PowerShell string interpolation.
- -Severity 'Alert' : Specify the Syslog message severity level
- -Facility 'Local0': Specify the Syslog message facility code
- }: End the ForEach-Object block.
Checking the Kiwi server shows success!
The Solution
Success! 🙌
The Add-On Question
The Add-On Solution
Once you learn some of the constructs of PowerShell like working with the pipeline, and some of the built-in commands such as ConvertTo-JSON, the pieces come together without too much difficulty. The question doesn't specify whether all of the output from DeepBlueCLI should be one JSON blob and one Syslog message, or a different JSON blob and Syslog message for each alert, but we can compose both pretty easily.
First, let's look at taking the DeepBlueCLI output and converting it to JSON. This is pretty straightforward:
PS C:\Users\Sec504\Downloads\DeepBlueCLI> .\DeepBlue.ps1 .\evtx\metasploit-psexec-native-target-security.evtx | ConvertTo-Json [ { "Date": "\/Date(1474429273078)\/", "Log": "Security", "EventID": 4688, "Message": "Suspicious Command Line", "Results": "Metasploit-style cmd with pipe (possible use of Meterpreter \u0027getsystem\u0027)\n", "Command": "cmd.exe /c echo hgabms \u003e \\\\.\\pipe\\hgabms", "Decoded": "" }, { "Date": "\/Date(1474429237088)\/", "Log": "Security", "EventID": 1102, "Message": "Audit Log Clear", "Results": "The Audit log was cleared.\nAccount Name:\tIEUser", "Command": "", "Decoded": "" } ]
JSON isn't always the nicest to look at, but it is a powerful way to encode data for compatibility between applications. Here, sending the DeepBlueCLI output to ConvertTo-Json in the pipeline is all that is needed to produce JSON-encoded output. Next, we need to send this output with Send-SyslogMessage. At first, I tried this:
PS C:\Users\Sec504\Downloads\DeepBlueCLI> .\DeepBlue.ps1 .\evtx\metasploit-psexec-native-target-security.evtx | ConvertTo-Json | Send-SyslogMessage -Server '127.0.0.1' -Severity 'Alert' -Facility 'Local0' Send-SyslogMessage : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
This produced an error The input object cannot be bound to any parameters for the command. Note to that I didn't specify the -Message argument in Send-SyslogMessage in this example -- I hoped that Send-SyslogMessage would support parameter binding and accept the output of ConvertTo-JSON as the message. Sadly, this is not a feature of Posh-SYSLOG, but we can work around it.
NOTE: Parameter binding is pretty graceful when it is supported by PowerShell commands. We'll investigate it in another #MOPS article later this month.
PS C:\Users\Sec504\Downloads\DeepBlueCLI> .\DeepBlue.ps1 .\evtx\metasploit-psexec-native-target-security.evtx | ConvertTo-JSON -OutVariable json [ { "Date": "\/Date(1655033354955)\/", "Log": "Security", "EventID": 4672, "Message": "Multiple admin logons for one account", "Results": "Username: Sec504\nUser SID Access Count: 2", "Command": "", "Decoded": "" }, { "Date": "\/Date(1655033354955)\/", "Log": "Security", "EventID": 4672, "Message": "Multiple admin logons for one account", "Results": "Username: Sec504\nUser SID Access Count: 2", "Command": "", "Decoded": "" } ] PS C:\Users\Sec504\Downloads\DeepBlueCLI> Send-SyslogMessage -Server '127.0.0.1' -Facility local0 -severity alert -message $json
This solution is written in two PowerShell commands for clarity. Let's break down the first, step-by-step:
- .\DeepBlue.ps1 .\evtx\metasploit-psexec-native-target-security.evtx | - Run DeepBlueCLI, reading from the specified EVTX file, starting a PowerShell pipeline
- ConvertTo-JSON - Convert the data to JSON format
- -OutVariable json Display the JSON output to the screen AND save it to a variable called json (that we can reference as $json in subsequent commands); -OutVariable is a common argument, meaning it is almost universally accessible for different PowerShell commands
The next command is similar to what we've seen before except for the -message $json piece. Here, we're specifying the variable $json as the message for Send-SyslogMessage with the other familiar -server, -facility, and -severity arguments.
This works, but it sends all of the alerts in a single Syslog message. Since the message size for Syslog is limited to 16,384 bytes (for TCP) and 4,096 bytes (for UDP), this might produce truncated JSON output.
As an alternative, we can use the ForEach-Object loop again, sending each alert from DeepBlueCLI as a Syslog message:
PS C:\Users\Sec504\Downloads\DeepBlueCLI> .\DeepBlue.ps1 .\evtx\metasploit-psexec-native-target-security.evtx | ForEach-Object { $_ | ConvertTo-Json -outvariable json ; Send-SyslogMessage -Server '127.0.0.1' -Facility local0 -severity alert -message $json } { "Date": "\/Date(1474429273078)\/", "Log": "Security", "EventID": 4688, "Message": "Suspicious Command Line", "Results": "Metasploit-style cmd with pipe (possible use of Meterpreter \u0027getsystem\u0027)\n", "Command": "cmd.exe /c echo hgabms \u003e \\\\.\\pipe\\hgabms", "Decoded": "" } { "Date": "\/Date(1474429237088)\/", "Log": "Security", "EventID": 1102, "Message": "Audit Log Clear", "Results": "The Audit log was cleared.\nAccount Name:\tIEUser", "Command": "", "Decoded": "" }
Let's break this command down step-by-step as well:
- .\DeepBlue.ps1 .\evtx\metasploit-psexec-native-target-security.evtx | - Run DeepBlueCLI, reading from the specified EVTX file, starting a PowerShell pipeline
- ForEach-Object { : Start a loop for object returned by DeepBlue.ps1, executing the code block until the closing } for each object
- \(_ | : Use the current object \)_, starting another pipeline, independent of the earlier one because it is in the {} block
- ConvertTo-Json -outvariable json: Convert the object (the DeepBlueCLI alert) into JSON, saving it in a variable called json
- ;: End the pipeline, starting a new command -- still within the ForEach-Object block {}
- Send-SyslogMessage -Server '127.0.0.1' -Facility local0 -severity alert -message $json: Send a syslog message with the message using the $json variable
- }: End the ForEach-Object block
Personally I think this works a little nicer, and it keeps the message size down for the Syslog messages.
Again here, developing some understanding of the PowerShell pipeline and looping using ForEach-Object gives you a lot of flexibility to solve your tasks.
The Takeaway
There's a lot of great community support for PowerShell. This is one of my favorite things about Python as my preferred programming language too: someone else has probably already done what you need to do. It's often just a matter of finding the solution that will work for you, and copy/transform/combine to produce the best solution that will work for you.
Summary
In this article we look a look at a problem: How can we take the output of DeepBlueCLI and send it via Syslog? After a quick search we discovered the Posh-SYSLOG module, and even some test cases quickly revealed sample use. Then it was a matter of putting it into practice, testing with a sample Syslog server to verify functionality. We also looked at a follow-on request to convert the Syslog message to JSON format, building on the Send-SyslogMessage functionality using ConvertTo-Json. Throughout, we leveraged the PowerShell pipeline as the building blocks to make the challenging, attainable.
Until next time!
-Joshua Wright
Return to Getting Started With PowerShell
Joshua Wright is the author of SANS SEC504: Hacker Tools, Techniques, and Incident Handling, a faculty fellow for the SANS Institute, and a senior technical director at Counter Hack.