在 Snort 警报上执行脚本 [英] Execute script on Snort alert

查看:20
本文介绍了在 Snort 警报上执行脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在试验 Raspberry Pi.我正在运行 Snort,它是数据包检测软件.在 Snort 发出警报的情况下,我想执行一个(Python)脚本.

I currently am experimenting with a Raspberry Pi. I am running Snort, which is packet detection software. In the case Snort raises an alert, I would want to execute a (Python) script.

在树莓派上执行 Snort,如下所示:

Snort is executed, on a raspberry pi as followed:

sudo snort -q -A console -i eth0 -c /etc/snort/snort.conf

我创建了一个 python 脚本,当调用时,它控制树莓派的 GPIO 引脚.将其更多地放在上下文中;当树莓派接收到ping/ICMP数据包时,红色报警灯会亮起,并由同一设备控制.

I created a python script that, when called, controls a GPIO pin of a raspberry pi. To bring it more in context; When the raspberry pi receives a ping/ICMP packet, a red alarm light is illuminated and controlled by the same device.

snort 规则当前有效,当 ICMP 数据包到达时,将向控制台输出警报.但是我不知道如何让 snort 执行 python 脚本

The snort rule currently works, and when an ICMP packet arrives an alert is output to console. I however have no idea how to get snort to execute the python script

推荐答案

以下是 3 个选项,希望其中一个可行:

Below are 3 options, hopefully one will work:

  • 使用子流程的PIPEs
  • 的严格"subprocess方法
  • 使用 pexpect 的方法——Pexpect 是一个纯 Python 模块,用于生成子应用程序;控制它们;并响应其输出中的预期模式."-- 并不是说​​这是您必须与默认 python 安装分开获取的唯一非标准包.
  • 使用伪终端和古老的select来读取文件描述符的方法
  • "Strict" subprocess approach using subprocess's PIPEs
  • Approach using pexpect -- "Pexpect is a pure Python module for spawning child applications; controlling them; and responding to expected patterns in their output." -- not that this is the only non-standard package you would have to grab separately from the default python install.
  • Approach using pseudoterminals and good-old select to read file descriptors

每种方法都捆绑在一个 try_[SOME APPROACH] 函数中.您应该能够更新顶部的 3 个参数,然后评论/取消评论底部的一种方法以试一试.

Each of the approaches is bundled in a try_[SOME APPROACH] function. You should be able to update the 3 parameters at the top, then comment/uncomment one approach at the bottom to give it a shot.

独立测试两半可能是值得的.换句话说,snort + 我的 rpi.py(如下).然后,如果可行,我的 timed_printer.py(如下)和你的 python 脚本来切换 RPi GPIO.如果它们都独立工作,那么您可以确信不需要做太多工作就可以使整个工作流程正常运行.

It may be worthwhile testing both halves independently. In other words snort + my rpi.py (below). Then, if that works, my timed_printer.py (below) and your python script to toggle the RPi GPIO. If they both work independently, then you can be confident not much will need to be done to get the entire workflow operating properly.

代码

import subprocess

_cmd_lst = ['python', '-u', 'timed_printer.py']  # sudo snort -q -A console -i eth0 -c /etc/snort/snort.conf
_rpi_lst = ['python', '-u', 'rpi.py']            # python script that toggles RPi
_alert = 'TIME'                                  # The keyword you're looking for
                                                 #  in snort output

#===============================================================================

# Simple helper function that calls the RPi toggle script
def toggle_rpi():
    subprocess.call(_rpi_lst)



def try_subprocess(cmd_lst, alert, rpi_lst):
    p = subprocess.Popen(' '.join(cmd_lst), shell=True, stdout=subprocess.PIPE, bufsize=1)

    try:
        while True:
            for line in iter(p.stdout.readline, b''):
                print("try_subprocess() read: %s" % line.strip())

                if alert in line:
                    print("try_subprocess() found alert: %s" % alert)
                    toggle_rpi()

    except KeyboardInterrupt:   print(" Caught Ctrl+C -- killing subprocess...")
    except Exception as ex:     print ex
    finally:
        print("Cleaning up...")
        p.kill()
        print("Goodbye.")



def try_pexpect(cmd_lst, alert, rpi_lst):
    import pexpect # http://pexpect.sourceforge.net/pexpect.html

    p = pexpect.spawn(' '.join(cmd_lst))

    try:
        while True:
            p.expect(alert)     # This blocks until <alert> is found in the output of cmd_str
            print("try_pexpect() found alert: %s" % alert)
            toggle_rpi()

    except KeyboardInterrupt:   print(" Caught Ctrl+C -- killing subprocess...")
    except Exception as ex:     print ex
    finally:
        print("Cleaning up...")
        p.close(force=True)
        print("Goodbye.")



def try_pty(cmd_lst, alert, rpi_lst, MAX_READ=2048):
    import pty, os, select

    mfd, sfd = pty.openpty()

    p = subprocess.Popen(' '.join(cmd_lst), shell=True, stdout=sfd, bufsize=1)

    try:
        while True:
            rlist, _, _, = select.select([mfd], [], [])

            if rlist:
                data = os.read(mfd, MAX_READ)
                print("try_pty() read: %s" % data.strip())
                if not data:
                    print("try_pty() got EOF -- exiting")
                    break
                if alert in data:
                    print("try_pty() found alert: %s" % alert)
                    toggle_rpi()
            elif p.poll() is not None:
                print("try_pty() had subprocess end -- exiting")
                break

    except KeyboardInterrupt:   print(" Caught Ctrl+C -- killing subprocess...")
    except Exception as ex:     print ex
    finally:
        print("Cleaning up...")
        os.close(sfd)
        os.close(mfd)
        p.kill()
        print("Goodbye.")

#===============================================================================

try_subprocess(_cmd_lst, _alert, _rpi_lst)
#try_pexpect(_cmd_lst, _alert, _rpi_lst)
#try_pty(_cmd_lst, _alert, _rpi_lst)

测试笔记

为了模拟你的 snort 脚本(一个挂起"的脚本,然后打印一些东西,然后回到挂起等状态),我编写了这个简单的 Python 脚本,我称之为 timed_printer.py:

To emulate your snort script (a script that "hangs", then prints something, then goes back to hanging, etc), I wrote this simple python script that I called timed_printer.py:

import time
while True:
    print("TIME: %s" % time.time())
    time.sleep(5)

而我的 rpi.py 文件很简单:

And my rpi.py file was simply:

print("TOGGLING OUTPUT PIN")

这里没有明确的输出刷新,以最好地模拟正常输出.

There's no explicit output flushing here, in an attempt to best emulate normal output.

最后的考虑

第一种方法将一次读取整行.因此,如果您希望 alert 包含在一行中,那就没问题了.

The first approach will read an entire line at a time. So if you expect your alert to be contained within a single line, you'll be fine.

第二种方法 (pexpect) 将阻塞,直到遇到 alert.

The second approach (pexpect) will block until alert is encountered.

第三种方法将读作一旦数据可用,我应该指出这不一定是完整的一行.如果您看到 try_pty() read: 带有 snort 输出行的片段,导致您错过警报,则需要添加某种缓冲解决方案.

The third approach will read as soon as data is available, which I should point out is not necessarily a full line. If you see try_pty() read: with fragments of the snort output lines, causing you to miss alerts, you'll need to add some sort of buffering solution.

文档

参考: 12

这篇关于在 Snort 警报上执行脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆