Detecting known bad actors with Wazuh and AbuseIPDB

100 views
Skip to first unread message

Henry Valero

unread,
Aug 1, 2025, 5:15:50 PM8/1/25
to Wazuh | Mailing List
Hi,
This blog shows how to identify malicious IPs with AbuseIPDB for SSH generated events. What changes would be necessary to identify malicious IPs with AbuseIPDB for web events?


Atte,
Henry
Message has been deleted

hasitha.u...@wazuh.com

unread,
Aug 2, 2025, 2:43:15 AM8/2/25
to Wazuh | Mailing List

Hi Henry

If the web logs decode the source IP as srcip, similar to the SSH decoder, you can use the same script. However, if the source IP is decoded under a different field name, replace srcip with the appropriate field name in the script. Then proceed with the remaining steps as usual.

Ref: https://wazuh.com/blog/detecting-known-bad-actors-with-wazuh-and-abuseipdb/

If you need further assistance on this, please share sample web logs from archives.json logs.

Enable archives.json log, set the <logall_json>yes</logall_json> to yes at /var/ossec/etc/ossec.conf file of the Wazuh manager.
Documentation:Wazuh Documentation | logall
<ossec_config>

 <global>

___________________

  <logall_json>yes</logall_json>

_______________

This option will allow you to see all the events being monitored by your manager in the /var/ossec/logs/archives/archives.json file. You will then be able to observe the incoming logs generated by your endpoints. After setting this option, restart the manager and check the archives.json file.
Note: Don't forget to disable the logall parameter once you have finished troubleshooting. Leaving it enabled could lead to high disk space consumption.
Look for if there are any logs inside the archive log which is relevant. Use grep parameters related to the log.
cat /var/ossec/logs/archives/archives.json | grep Keywoard

We can see the field full_log, which is the one being parsed by analysis, one of the archives.json events should look like this (the field of interest is in bold):
{"timestamp":"2023-09-05T02:47:40.074+0000","agent":{"id":"001","name":"abc","ip":"10.0.2.29},"manager":{"name":"Server85"},"id":"1693882060.373586","full_log ":"Sep 5 03:10:19 Server91 dbus-daemon[676]: [system] Successfully activated service 'org.freedesktop.UPower","predecoder":{"program_name":"dbus-daemon","timestamp":"Sep 5 03:10:19","hostname":"Server91"},"decoder":{},"location":"/var/log/syslog"}
Ref: https://wazuh.com/blog/creating-decoders-and-rules-from-scratch/

Please share the sample full_logs from archives.json log, so that I can assist you in customizing the script and rules.

Let me know the update on this.

On Saturday, August 2, 2025 at 12:12:46 PM UTC+5:30 hasitha.u...@wazuh.com wrote:

Hi Henry If the web logs decode the source IP as srcip, similar to the SSH decoder, you can use the same script. However, if the source IP is decoded under a different field name, replace srcip with the appropriate field name in the script. Then proceed with the remaining steps as usual.

Ref: https://wazuh.com/blog/detecting-known-bad-actors-with-wazuh-and-abuseipdb/

If you need further assistance on this, please share sample web logs from archives.json logs.

Enable archives.json log, set the <logall_json>yes</logall_json> to yes at /var/ossec/etc/ossec.conf file of the Wazuh manager.
Documentation:Wazuh Documentation | logall
<ossec_config>

 <global>

___________________

  <logall_json>yes</logall_json>

_______________

This option will allow you to see all the events being monitored by your manager in the /var/ossec/logs/archives/archives.json file. You will then be able to observe the incoming logs generated by your endpoints. After setting this option, restart the manager and check the archives.json file.
Note: Don't forget to disable the logall parameter once you have finished troubleshooting. Leaving it enabled could lead to high disk space consumption.
Look for if there are any logs inside the archive log which is relevant. Use grep parameters related to the log.
cat /var/ossec/logs/archives/archives.json | grep Keywoard

We can see the field full_log, which is the one being parsed by analysis, one of the archives.json events should look like this (the field of interest is in bold):
{"timestamp":"2023-09-05T02:47:40.074+0000","agent":{"id":"001","name":"abc","ip":"10.0.2.29},"manager":{"name":"Server85"},"id":"1693882060.373586","full_log ":"Sep 5 03:10:19 Server91 dbus-daemon[676]: [system] Successfully activated service 'org.freedesktop.UPower","predecoder":{"program_name":"dbus-daemon","timestamp":"Sep 5 03:10:19","hostname":"Server91"},"decoder":{},"location":"/var/log/syslog"}
Ref: https://wazuh.com/blog/creating-decoders-and-rules-from-scratch/

Please share the sample full_logs from archives.json log, so that I can assist you in customizing the script and rules.

Let me know the update on this.

Jorge Eduardo Silva Jackson

unread,
Aug 3, 2025, 8:38:11 AM8/3/25
to Wazuh | Mailing List
Hi Henry:

You can basically mirror the SSH-based AbuseIPDB setup for web traffic—just swap in HTTP-specific rules and update your integration block for those new rule IDs. The AbuseIPDB script itself remains unchanged; it just needs to receive the srcip from your HTTP event. Then add a final rule to check abuseipdb.abuse_confidence_score—if the IP has prior abuse history, fire the alert. I’ve attached sample config snippets for local_rules.xml and ossec.conf.

1. Add monitor web logs to agent
<ossec_config>
  <localfile>
    <log_format>syslog</log_format>
    <location>/var/log/nginx/access.log</location>
  </localfile>
</ossec_config>

2. Use built‑in HTTP decoders
Wazuh already decodes access logs into fields like srcip, url, status, and user_agent

3. Create custom rules for relevant web events
e.g.
<group name="local,web,bad_http,">
  <rule id="100102" level="5">
    <if_sid>21205</if_sid>    <!-- Default Nginx 403 rule -->
    <srcip negate="yes">^(10|192\.168|172\.(1[6-9]|2[0-9]|3[0-1]))</srcip>
    <description>HTTP auth failed (403) from public IP $(srcip)</description>
  </rule>
  <rule id="100103" level="5">
    <if_sid>21150</if_sid>    <!-- High-frequency 404 rule -->
    <srcip negate="yes">…</srcip>
    <description>HTTP 404 scan from public IP $(srcip)</description>
  </rule>
</group>

4. Configure the <integration> block in ossec.conf to include the new rule IDs:
e.g.
<integration>
  <name>custom-abuseipdb.py</name>
  <hook_url>https://api.abuseipdb.com/api/v2/check</hook_url>
  <api_key>TU_API_KEY</api_key>
  <rule_id>100102,100103</rule_id>
  <alert_format>json</alert_format>
</integration>

5. Add AbuseIPDB-based dependent rules, similar to 100004/100005 in the blog but referencing your new IDs:
e.g.

<rule id="100104" level="10">
  <field name="abuseipdb.source.rule">^100102$</field>
  <field name="abuseipdb.abuse_confidence_score" negate="yes">^0$</field>
  <description>AbuseIPDB: HTTP auth failure from $(abuseipdb.source.srcip), score=$(abuseipdb.abuse_confidence_score)%</description>
</rule>

Full example configuration in local_rules.xml
<group name="local,web,bad_http,">
  <rule id="100102" level="5">
    <if_sid>21205</if_sid>
    <srcip negate="yes">^(10|192\.168|172\.(1[6-9]|2[0-9]|3[0-1]))</srcip>
    <description>HTTP forbidden (403) from public IP $(srcip)</description>
  </rule>
</group>

<group name="local,web,abuseipdb,">
  <rule id="100104" level="10">
    <field name="abuseipdb.source.rule">^100102$</field>
    <field name="abuseipdb.abuse_confidence_score" negate="yes">^0$</field>
    <description>AbuseIPDB: HTTP 403 from $(abuseipdb.source.srcip), score=$(abuseipdb.abuse_confidence_score)%</description>
  </rule>
</group>

Full example block configuration in manager ossec.conf
<integration>
  <name>custom-abuseipdb.py</name>
  <hook_url>https://api.abuseipdb.com/api/v2/check</hook_url>
  <api_key>XXXXXXXXXXXXXX</api_key>
  <rule_id>100102</rule_id>
  <alert_format>json</alert_format>
</integration>

Best regards

Henry Valero

unread,
Aug 4, 2025, 10:32:29 AM8/4/25
to Wazuh | Mailing List
Hi Hasitha,

I attach a sample of the requested file

Atte,
Henry
sample-archives.json

hasitha.u...@wazuh.com

unread,
Aug 5, 2025, 1:49:54 AM8/5/25
to Wazuh | Mailing List
Hi  Henry

It appears that your logs do not match any default Wazuh decoders or rules. Therefore, I’ve created custom decoders to extract the relevant fields and written custom rules to generate alerts based on your specific scenario.

Please start by copying the following decoders into your custom decoder file.

nano /var/ossec/etc/decoders/local_decoder.xml

  1. <decoder name="weblog-custom">
  2.   <prematch>\d+/\S+/\d+:\d+:\d+:\d+\s\S+|</prematch>
  3. </decoder>
  4.  
  5. <decoder name="weblog-custom-child">
  6.   <parent>weblog-custom</parent>
  7.    <regex>(\d+/\S+/\d+:\d+:\d+:\d+\s\S+)\p</regex>
  8.   <order>log_time</order>
  9. </decoder>
  10.  
  11. <decoder name="weblog-custom-child">
  12.   <parent>weblog-custom</parent>
  13.    <regex>\d+/\S+/\d+:\d+:\d+:\d+\s\S+\p(\d+.\d+.\d+.\d+)</regex>
  14.   <order>srcip</order>
  15. </decoder>
  16.  
  17. <decoder name="weblog-custom-child">
  18.   <parent>weblog-custom</parent>
  19.    <regex>\.+\p\d+.\d+.\d+.\d+\p(\d+.\d+.\d+.\d+)</regex>
  20.   <order>dstip</order>
  21. </decoder>
  22.  
  23. <decoder name="weblog-custom-child">
  24.   <parent>weblog-custom</parent>
  25.    <regex>\.+\|\.+\|\.+\|(\.+)\|</regex>
  26.   <order>url</order>
  27. </decoder>
  28.  
  29. <decoder name="weblog-custom-child">
  30.   <parent>weblog-custom</parent>
  31.    <regex>\.+\|\.+\|\.+\|\.+\|(\S+)\|</regex>
  32.   <order>method</order>
  33. </decoder>
  34.  
  35. <decoder name="weblog-custom-child">
  36.   <parent>weblog-custom</parent>
  37.    <regex>\.+\|\.+\|\.+\|\.+\|\S+\|(\d+)\|</regex>
  38.   <order>http_status</order>
  39. </decoder>
  40.  
  41. <decoder name="weblog-custom-child">
  42.   <parent>weblog-custom</parent>
  43.    <regex>\.+\|\.+\|\.+\|\.+\|\S+\|\d+\|(\.+)\|</regex>
  44.   <order>response_time</order>
  45. </decoder>
  46.  
  47. <decoder name="weblog-custom-child">
  48.   <parent>weblog-custom</parent>
  49.    <regex>\.+\|\.+\|\.+\|\.+\|\S+\|\d+\|\.+\|(\.+)\|</regex>
  50.   <order>bytes</order>
  51. </decoder>
  52.  
  53. <decoder name="weblog-custom-child">
  54.   <parent>weblog-custom</parent>
  55.    <regex>\.+\|\.+\|\.+\|\.+\|\S+\|\d+\|\.+\|\.+\|(\.+)</regex>
  56.   <order>user_agent</order>
  57. </decoder>

You can refer to the Wazuh regular expressions documentation to understand how to tailor the regex pattern based on your actual log format.
For writing or modifying decoders, refer to the Wazuh decoder syntax documentation.

Next, copy the following rules into your custom rules file.
nano /var/ossec/etc/rules/local_rules.xml

  1. <group name="weblog-custom">
  2.  
  3.   <rule id="234100" level="3">
  4.     <decoded_as>weblog-custom</decoded_as>
  5.     <description>Weblog messages grouped.</description>
  6.   </rule>
  7.  
  8.   <rule id="235300" level="5">
  9.     <if_sid>234100</if_sid>
  10.     <match type="pcre2">\b(?!(10)|192\.168|172\.(2[0-9]|1[6-9]|3[0-1])|(25[6-9]|2[6-9][0-9]|[3-9][0-9][0-9]|99[1-9]))[0-9]{1,3}\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)</match>
  11.     <description>Weblog traffic from a public IP address $(srcip).</description>
  12.     <group>weblog</group>
  13.   </rule>
  14.  
  15.   <rule id="235350" level="10">
  16.     <field name="abuseipdb.source.rule" type="pcre2">^235300$</field>
  17.     <field name="abuseipdb.abuse_confidence_score" type="pcre2" negate="yes">^0$</field>
  18.     <description>AbuseIPDB: Web traffic from a public IP address $(abuseipdb.source.srcip) with $(abuseipdb.abuse_confidence_score)% confidence of abuse.</description>
  19.     <group>authentication_failed,pci_dss_10.2.4,pci_dss_10.2.5,</group>
  20.   </rule>
  21.  
  22. </group>
You can customize or add more rules based on your specific requirements by referring to the Wazuh rules syntax guide.

I have attached the custom script files. Please copy them to the /var/ossec/integrations/ directory, and then assign the appropriate permissions.
chmod 750 /var/ossec/integrations/custom-abuseipdb.py
chown root:wazuh /var/ossec/integrations/custom-abuseipdb.py


Then, restart the Wazuh manager to apply changes.
systemctl restart wazuh-manager

Feel free to let me know if you need any more help on this.

Screenshot 2025-08-05 111927.png
custom-abuseipdb
custom-abuseipdb.py
Reply all
Reply to author
Forward
0 new messages