Вопрос

Имея проблема с аналитическими журналами Snort, используя модуль Pyparsing.

Проблема состоит в том, что отделяя журнал Snort (в котором есть многолетние записи, разделенные пустой строкой) и получают pyparding для анализа каждой записи в целом кусок, а не прочитать в строке по линии и ожидаю, что грамматику работать с каждой строкой (очевидно, , Это не.)

Я попытался преобразовать каждую кусок на временную строку, раздавая новые линии внутри каждого куска, но он отказывается правильно обрабатывать. Я могу быть полностью на неправильном треке, но я так не думаю (аналогичная форма отлично работает для журналов Syslog-Type, но это однострочные записи, а это поддается вашему базовому файловому итератору / обработке линии / линии)

Вот образец журнала и кода, который у меня есть до сих пор:

[**] [1:486:4] ICMP Destination Unreachable Communication with Destination Host is Administratively Prohibited [**]
[Classification: Misc activity] [Priority: 3] 
08/03-07:30:02.233350 172.143.241.86 -> 63.44.2.33
ICMP TTL:61 TOS:0xC0 ID:49461 IpLen:20 DgmLen:88
Type:3  Code:10  DESTINATION UNREACHABLE: ADMINISTRATIVELY PROHIBITED HOST FILTERED
** ORIGINAL DATAGRAM DUMP:
63.44.2.33:41235 -> 172.143.241.86:4949
TCP TTL:61 TOS:0x0 ID:36212 IpLen:20 DgmLen:60 DF
Seq: 0xF74E606
(32 more bytes of original packet)
** END OF DUMP

[**] ...more like this [**]

И обновленный код:

def snort_parse(logfile):
    header = Suppress("[**] [") + Combine(integer + ":" + integer + ":" + integer) + Suppress("]") + Regex(".*") + Suppress("[**]")
    cls = Optional(Suppress("[Classification:") + Regex(".*") + Suppress("]"))
    pri = Suppress("[Priority:") + integer + Suppress("]")
    date = integer + "/" + integer + "-" + integer + ":" + integer + "." + Suppress(integer)
    src_ip = ip_addr + Suppress("->")
    dest_ip = ip_addr
    extra = Regex(".*")

    bnf = header + cls + pri + date + src_ip + dest_ip + extra

    def logreader(logfile):
        chunk = []
        with open(logfile) as snort_logfile:
            for line in snort_logfile:
                if line !='\n':
                    line = line[:-1]
                    chunk.append(line)
                    continue
                else:
                    print chunk
                    yield " ".join(chunk)
                    chunk = []

    string_to_parse = "".join(logreader(logfile).next())
    fields = bnf.parseString(string_to_parse)
    print fields

Любая помощь, указатели, RTFMS, вы делаете это неправильно, и т. Д., Очень ценится.

Это было полезно?

Решение

import pyparsing as pyp
import itertools

integer = pyp.Word(pyp.nums)
ip_addr = pyp.Combine(integer+'.'+integer+'.'+integer+'.'+integer)

def snort_parse(logfile):
    header = (pyp.Suppress("[**] [")
              + pyp.Combine(integer + ":" + integer + ":" + integer)
              + pyp.Suppress(pyp.SkipTo("[**]", include = True)))
    cls = (
        pyp.Suppress(pyp.Optional(pyp.Literal("[Classification:")))
        + pyp.Regex("[^]]*") + pyp.Suppress(']'))

    pri = pyp.Suppress("[Priority:") + integer + pyp.Suppress("]")
    date = pyp.Combine(
        integer+"/"+integer+'-'+integer+':'+integer+':'+integer+'.'+integer)
    src_ip = ip_addr + pyp.Suppress("->")
    dest_ip = ip_addr

    bnf = header+cls+pri+date+src_ip+dest_ip

    with open(logfile) as snort_logfile:
        for has_content, grp in itertools.groupby(
                snort_logfile, key = lambda x: bool(x.strip())):
            if has_content:
                tmpStr = ''.join(grp)
                fields = bnf.searchString(tmpStr)
                print(fields)

snort_parse('snort_file')

доходность

[['1:486:4', 'Misc activity', '3', '08/03-07:30:02.233350', '172.143.241.86', '63.44.2.33']]

Другие советы

У вас есть несколько Regex Unlearning, но, надеюсь, это не будет слишком больно. Самый большой виновник в вашем мышлении - это использование этой конструкции:

some_stuff + Regex(".*") + 
                 Suppress(string_representing_where_you_want_the_regex_to_stop)

Каждый подделкет в Pyparding Parser в значительной степени автономной, и последовательно работает через входящий текст. Поэтому термин Regex не имеет возможности осмотреть следующее выражение, чтобы увидеть, где '*' Повторение должно остановиться. Другими словами, выражение Regex(".*") собирается просто прочитать до конца линии, так как это где ".*" останавливается без уточнения многослойного.

В Pyparding эта концепция реализована с помощью Skipto. Вот как ваш заголовка написана:

header = Suppress("[**] [") + Combine(integer + ":" + integer + ":" + integer) + 
             Suppress("]") + Regex(".*") + Suppress("[**]") 

Ваш ". *" Проблема решается, изменив его на:

header = Suppress("[**] [") + Combine(integer + ":" + integer + ":" + integer) + 
             Suppress("]") + SkipTo("[**]") + Suppress("[**]") 

То же самое для CLS.

Одним из последних ошибок, ваше определение даты короткое время «:» + целое число:

date = integer + "/" + integer + "-" + integer + ":" + integer + "." + 
          Suppress(integer) 

должно быть:

date = integer + "/" + integer + "-" + integer + ":" + integer + ":" + 
          integer + "." + Suppress(integer) 

Я думаю, что эти изменения будут достаточными для начать распределение данных журнала.

Вот некоторые другие предложения стилей:

У вас много повторяется Suppress("]") выражения. Я начал определять всю мою подавляющую пунктуацию очень компактным и легко поддерживающим заявление, подобное это:

LBRACK,RBRACK,LBRACE,RBRACE = map(Suppress,"[]{}")

(Разверните, чтобы добавить любые другие символы пунктуации, которые вам нравятся). Теперь я могу использовать эти символы по их символическим именам, и я нахожу полученный код немного легче читать.

Вы начинаете от заголовка с header = Suppress("[**] [") + .... Отказ Я никогда не люблю видеть промежутки, встроенные в литерал, поскольку он обходил некоторые из разборки устойчивости Pyparding дает вам автоматическое пробеловое пробелование. Если по какой-то причине пространство между «[**]» и «[[» было изменено на использование 2 или 3 пробелов или вкладку, то ваше подавленное литерал не удастся. Объедините это с предыдущим предложением, а заголовок начнется с

header = Suppress("[**]") + LBRACK + ...

Я знаю, что это сгенерировано текст, поэтому изменение в этом формате маловероятно, но он лучше воспроизводится до сильных сторон Pyparding.

Как только у вас установлены ваши поля, начните назначить имена результатов различным элементам в вашем анализаторе. Это сделает это много легче получить данные позже. Например, измените CLS для:

cls = Optional(Suppress("[Classification:") + 
             SkipTo(RBRACK)("classification") + RBRACK) 

Позволит вам получить доступ к данных классификации, используя fields.classification.

Ну, я не знаю, фырк или pyparsing, Так что извиняюсь заранее, если я скажу что-то глупое. Я неясен относительно того, является ли проблема с pyparsing не в состоянии справиться с записями или с вами неспособным отправлять их на pyparsing в правильном формате. Если последний, почему бы не делать что-то подобное?

def logreader( path_to_file ):
    chunk = [ ]
    with open( path_to_file ) as theFile:
        for line in theFile:
            if line:
                chunk.append( line )
                continue
            else:
                yield "".join( *chunk )
                chunk = [ ]

Конечно, если вам нужно изменить каждый кусок, прежде чем отправлять его на pyparsing, вы можете сделать это раньше yieldего.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top