Logging WordPress activity to OSSEC

Today I came across this blog article, explaining how to make WordPress log suspicious activity to an audit log file, which in turn can be monitored by OSSEC. Everything mentioned in the article was all fine and dandy, until I read the last paragraph: “Note that for this feature to work, you have to use our fork of OSSEC […]“.

Being less than enthusiastic about replacing my existing OSSEC (version 2.8.3) installation with a fork (even if the fork happens to originate from OSSEC’s founder), I wanted to make this work with what I’ve already got. Following the main instructions from the blog article, I installed the sucuri-scanner plugin but did not request an API key – at this point, at least. Then, by providing an absolute path to an existing log file, to which the web server has write access, I activated the plugin’s audit log exporter.

The same absolute path was added to the OSSEC agent‘s ossec.conf (/var/ossec/etc/ossec.conf) file as a syslog file:

 <localfile>
   <log_format>syslog</log_format>
   <location>/var/log/wp/site/audit.log</location>
 </localfile>

 

So far, so good – now to make the OSSEC manager correctly decode and parse the log events.

First, I replaced the whole wordpress_rules.xml file with the one provided by the OSSEC fork. I found the updated wordpress_rules.xml file on https://bitbucket.org/dcid/ossec-hids/, and from there by navigating the source tree (source → ossec-hids/etc/rules/). The exact file location in the repository could change with future versions and commits, so there’s not much of a point in providing an exact URL. Apart from a signature ID collision (two signatures had sid 9507) this updated file was an improvement over the wordpress_rules.xml that came with OSSEC 2.8.3. The file is too large to inline here.

The final piece of the puzzle was to provide a useful decoder. I’ve added the following to the manager‘s /var/ossec/rules/local_decoder.xml:

<decoder name="wordpressaudit">
 <parent>windows-date-format</parent>
 <use_own_name>true</use_own_name>
 <prematch offset="after_parent">WordPressAudit </prematch>
 <regex offset="after_prematch">^\S+ \S+ : (\w+): (\S+); </regex>
 <order>action, srcip</order>
</decoder>

 

And bingo, it works. Failed WordPress logins, along with some other weird activities – and normal as well, if you so wish – will now be identified by OSSEC and you can set the severity levels accordingly. Here’s an example of the OSSEC alert log’s detection of a failed login (formatted for readability):

** Alert 1454537692.8654637: mail - syslog,wordpress,authentication_failed,
2016 Feb 03 23:14:52 (webserver.example.com) 10.0.0.10->/var/log/wp/site/audit.log
Rule: 9501 (level 7) -> 'WordPress authentication failed.'
Src IP: 192.168.0.42
2016-02-03 22:14:51 WordPressAudit www.example.com bjorn@ruberg.no : Error:
  192.168.0.42; User authentication failed: EvilUser

 

and even

** Alert 1454541645.146379: mail - syslog,wordpress,syscheck,
2016 Feb 04 00:20:45 (webserver.example.com) 10.0.0.10->/var/log/wp/site/audit.log
Rule: 9508 (level 7) -> 'WordPress post updated.'
2016-02-03 23:20:44 WordPressAudit www.example.com bjorn@ruberg.no : Notice:
  bjorn, 192.168.100.100; Post was updated; identifier: 4096; name: Some Article Name