Tracking Processes/Malwares Using OSSEC

TerminatorFor a while, malwares are in front of the security stage and the situation is unlikely to change in the coming months. When I give presentations about malwares, I always like to report two interesting statistics in my slides. They come from the 2012 Verizon DBIR: In 66% of investigated incidents, detection was a matter of months or even more and 69% of data breaches are discoverd by third parties. The problem of malwares can be addressed at two levels: infection & detection. To protect against infection, more and more solutions are provided by security vendors and some are quite performant but they don’t fully protect you. To contain the malware, the detection process is also critical. If you can’t prevent some malwares to be installed, at least let’s try to detect them as soon as possible. To track malicious activity, there is no magic: you have to search for what’s abnormal, to look for stuff occurring below the radar. Malwares try to remain stealthy but they have to perform some actions like altering the operating system and contacting their C&C. To detect such activity, OSSEC is a wonderful tool. I already blogged about a way to detect malicious DNS traffic with OSSEC and the help of online domains blacklists like malwaredomains.com.

Today, I’ll show you how to track programs started in a Windows environment. If the primary goal is to track programs execurted by a user, it could easily be extended to “malicious” programs (malwares). To achieve this, there is no magic, we will just interconnect existing tools to get some valuable data. First, let’s use an interesting feature of the latest Microsoft operating systems: AppLocker. This feature has been introduced since Windows 7 and Windows Server 2008 R2. It allows you to control which users or groups can run which applications in your organization based on unique identities of files. Rules can be created to allow or deny applications from running. The following files can be controlled:

  • Executable files (.exe and .com),
  • Scripts (.js, .ps1, .vbs, .cmd, and .bat),
  • Windows Installer files (.msi and .msp),
  • DLL files (.dll and .ocx).

AppLocker is easy to configure via the Local Policy Manager (secpol.msc) but it can also be deployed using GPO’s:

LocalSecurityPolicy
(Click to zoom)

Don’t forget to start the “Application Identity” service and enable it at boot type. Once done, new events will be created in the EventViewer:

EventID8002
(Click to zoom)

Note: I won’t cover how to implement an AppLocker policy here. My configuration is very simple: allow any executables because I’m just looking at collecting information and not enforcing any security policy.

As you can see in the screenshot, AppLocker events are created in a specific channel called “Microsoft-Windows-AppLocker/EXE and DLL“. Until now, nothing special, it’s quite easy to configure but we have a problem with the current version of OSSEC. The latest release uses the old API calls to read Windows events and only the classic logs can be processed (the well-known Application, System and Security). To read the channels like the one used by AppLocker, new functions are available. A few weeks ago, I quickly looked at the OSSEC source code to implement them but my Windows development skills were too limited. Hopefully, my friends of Sekoia implemented exactly what I needed and their changes have been implemented in the OSSEC development branch. If you can’t wait for the next release, here is a quick how-to to compile a new windows agent with support of event channels.

First, download the latest source tree from GitHub. I used an Ubuntu server to compile the code (using MinGW).

# wget https://github.com/ossec/ossec-hids/archive/master.zip
# apt-get install  mingw-w64 nsis # If not yet installed...
# unzip master.zip
# cd ossec-hids-master/src/win32
# ./gen_win.sh
# cd ../win-pkg
# ./make.sh

If everything went smoothly, the compilation job will deliver a Windows installation package called “ossec-win32-agent.exe“. This is the new one that must be deployed on your Windows 7 or 2008R2 systems to read event channels. No panic, if you can’t compile the new agent, here is my version (sha1: a2e0315edda8d6913da7895ed51fe8f9f86cd8f0). This one is provided “as is” of course. Now, we are ready to configure our OSSEC as usual:

  • Collect events
  • Write a decoder
  • Write rules

To collect information about allowed (or deny) programs, add the following lines into your Windows agent ossec.conf. To read channels, a new type of log_format is available (“eventchannel“):

<ossec_config>
  <localfile>
    <location>Microsoft-Windows-AppLocker/EXE and DLL</location>
    <log_format>eventchannel</log_format>
  </localfile>
  <localfile>
    <location>Microsoft-Windows-AppLocker/MSI and Script</location>
    <log_format>eventchannel</log_format>
  </localfile>
</ossec_config>

Restart your OSSEC agent and from now, events with ID 8002 should be catched by your OSSEC server and reported with a default rule ID 18101 (“Windows informational event“):

2014 Feb 09 10:08:37 (e6500) any->WinEvtLog WinEvtLog: \
  Microsoft-Windows-AppLocker/EXE and DLL: Information(8002): \
    no source: xavier: E6500: E6500: %SYSTEM32%\CALC.EXE was allowed to run.

The next step is to extract a very important field: the name of the executable. Let’s write a new decoder to catch it under the “url” variable. In your $OSSEC_HOME/etc/local_decoder.xml file, add a new one:

<decoder name="windows-applocker">
  <parent>windows</parent>
  <type>windows</type>
  <use_own_name>true</use_own_name>
  <prematch>^WinEvtLog: </prematch>
  <regex offset="after_prematch">^\.+: (\w+)\((\d+)\): (\.+): </regex>
  <regex>(\.+): \.+: (\S+): (\S+) was allowed to run.</regex>
  <order>status, id, extra_data, user, system_name, url</order>
  <fts>name, location, user, system_name</fts>
</decoder>

To generate efficient alerts, the best way is to create a CDB list. We can use two different approaches:

  • A white list with an (exhaustive) list of allowed executables
  • A black list with a list of prohibited executables.

Which approach is the best? Depending on your environment and users, it’s up to you to decide. In my case, I implemented a white-list. From a freshly installed Windows 7 with all the classic tools and applications, I generated a list of all executable. I hope I don’t have to insist on the fact that it it’s mandatory to use a clean system for this operation! With PowerShell, you can grab a list of all executable files:

PS C:\> Get-ChildItem -path c:\ \
-include *.exe,*.com,*.msi,*.msp,*.dll,*.ocx,*.scr,*.ps1,*.bat \
-recurse \
-name \
| Out-File -encoding ascii c:\windows-exec.tmp

To give you an idea, my test Windows 7 laptop generated a 26000+ lines file. Transfer this file to your OSSEC server and create a new CDB list with allowed files. AppLocker uses macros in filenames like %SYSTEM32%, %OSDRIVE%, %WINDIR% or %PROGRAMFILES%. You need to process the file before creating the CDB. This is easily performed via a small bash script:

#!/bin/bash
# gen-windows-exec.sh
# Generate the OSSEC CDB list
cat $1 | sed 's/\r$//' | while read -r P
do
  L="C:\\$P"
  L=`echo $L|tr '[:lower:]' '[:upper:]'`
  case $L in
    C:\\PROGRAM\ FILES\\*)
      if [[ "$L" =~ "PROGRAM FILES (X86)" ]]; then
        echo "%PROGRAMFILES%${L:22}:Allowed"
      else
        echo "%PROGRAMFILES%${L:16}:Allowed"
      fi
      ;;
    C:\\WINDOWS\\SYSTEM32\\*)
      echo "%SYSTEM32%${L:19}:Allowed"
      ;;
    C:\\WINDOWS\\*) 
      echo "%WINDIR%${L:10}:Allowed"
      ;;
    C:\\*)
      echo "%OSDRIVE%${L:2}:Allowed"
     ;;
    *)
      echo "%L:Allowed"
      ;;
  esac
done

Add a new CDB list in your $OSSEC_HOME/etc/osssec.conf:

<ossec_config>
  <rules>
    <list>lists/windows-exec.cdb</list>
  </rules>
</ossec_config>

And finally create the CDB list:

# ./gen-windows-exec.sh <windows-exec.tmp >$OSSEC_HOME/lists/windows-exec
# $OSSEC_HOME/bin/ossec-makelists
 * File lists/windows-exec.cdb need to be compiled

Now, you can create your rules. Example:

<!-- Detect if a suspicious program is executed -->
<rule id="100601" level="10">
  <if_sid>18101</if_sid>
  <id>^8002$</id>
  <list field="url" lookup="not_match_key">lists/windows-exec</list>
  <description>AppLocker:  Suspicious executable started.</description>
  <group>win_applocker,</group>
</rule>
<!-- Detect if a suspicious program is executed with SYSTEM/Admin privileges -->
<rule id="100602" level="15">
  <if_sid>18101</if_sid>
  <id>^8002$</id>
  <user>SYSTEM|Administrator</user>
  <list field="url" lookup="not_match_key">lists/windows-exec</list>
  <description>AppLocker:  Suspicious executable started.</description>
  <group>win_applocker,</group>
</rule>

Let’s test:

# $OSSEC_HOME/bin/ossec-logtest 
2014/02/09 14:48:23 ossec-testrule: INFO: Reading local decoder file.
2014/02/09 14:48:23 ossec-testrule: INFO: Reading the lists file: 'lists/windows-exec.cdb'
2014/02/09 14:48:23 ossec-testrule: INFO: Started (pid: 18910).
ossec-testrule: Type one log per line.

WinEvtLog: Microsoft-Windows-AppLocker/EXE and DLL: Information(8002): no source: xavier: E6500: E6500: %SYSTEM32%\MALWARE.EXE was allowed to run.

**Phase 1: Completed pre-decoding.
 full event: 'WinEvtLog: Microsoft-Windows-AppLocker/EXE and DLL: Information(8002): no source: xavier: E6500: E6500: %SYSTEM32%\MALWARE.EXE was allowed to run.'
 hostname: 'boogey'
 program_name: '(null)'
 log: 'WinEvtLog: Microsoft-Windows-AppLocker/EXE and DLL: Information(8002): no source: xavier: E6500: E6500: %SYSTEM32%\MALWARE.EXE was allowed to run.'

**Phase 2: Completed decoding.
 decoder: 'windows'
 status: 'Information'
 id: '8002'
 extra_data: 'no source'
 dstuser: 'xavier'
 system_name: 'E6500'
 url: '%SYSTEM32%\MALWARE.EXE'

**Phase 3: Completed filtering (rules).
 Rule id: '100601'
 Level: '10'
 Description: 'AppLocker: Suspicious executable started.'
**Alert to be generated.

Challenge completed! Now your OSSEC will notify you when a user started an unknow (and today, what is unknown should considered as suspicious!) executable. Again, this solution does not pretend to replace other solutions to protect against malwares but it’s a nice way to increase the visibility of what’s happening in your Windows environments and integrate the events in a central solution. Happy tracking!

6 comments

  1. Very clever how you decoded the file name as URL so it could be used within CBD. I don’t think I would have thought of that.

    Very nice integration of a Windows feature with OSSEC.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.