【问题标题】:Python: Convert multiple YAML documents to JSONPython:将多个 YAML 文档转换为 JSON
【发布时间】:2018-12-19 20:48:47
【问题描述】:

我目前正在尝试使用 python 将一些 YAML 转换为 JSON,并且很难正确格式化 JSON。我的 YAML 文件有多个如下所示的文档:

title: Windows Shell Spawning Suspicious Program
status: experimental
description: Detects a suspicious child process of a Windows shell
references:
    - https://mgreen27.github.io/posts/2018/04/02/DownloadCradle.html
author: Florian Roth
date: 20018/04/06
logsource:
    product: windows
    service: sysmon
detection:
    selection:
        EventID: 1
        ParentImage:
            - '*\mshta.exe'
            - '*\powershell.exe'
            - '*\cmd.exe'
            - '*\rundll32.exe'
            - '*\cscript.exe'
            - '*\wscript.exe'
            - '*\wmiprvse.exe'
        Image:
            - '*\schtasks.exe'
            - '*\nslookup.exe'
            - '*\certutil.exe'
            - '*\bitsadmin.exe'
            - '*\mshta.exe'
    condition: selection
fields:
    - CommandLine
    - ParentCommandLine
falsepositives:
    - Administrative scripts
level: medium
...

我正在尝试为每个文档提取检测、字段、误报和级别,并将它们作为单独的数组放入 JSON 文档中。我的第一次尝试很糟糕,只是将每个文档中的组集中到列表中:

data = {}
data['indicator'] = {}
data['indicator']['detection']=[]
data['indicator']['fields']=[]
data['indicator']['false positives']=[]
data['indicator']['level']=[]
with open(yaml_file, 'r') as yaml_in, open(json_file, 'a') as definition:
     loadyaml = yaml.safe_load_all(yaml_in)
     for item in loadyaml:
         for header, subsections in item.iteritems():
             if header == 'detection':
                 data['indicator']['detection'].append(subsections)
             elif header == 'fields':
                 data['indicator']['fields'].append(subsections)
             elif header == 'false positives':
                 data['indicator']['false positives'].append(subsections)
             elif header == 'level':
                 data['indicator']['level'].append(subsections)

     json.dump(data, definition, indent=4)

我希望将我的每个文档作为单独的指标输入到我的 json 文档中,并将它们的检测、字段、dalspositives 和级别都组合在一起——但是我的 python 能力让我失望了。

我将不胜感激!

【问题讨论】:

    标签: python json python-2.7 yaml


    【解决方案1】:

    您可以通过迭代.load_all() 和一个小得多的程序来获得您想要的输出:

    import sys
    import ruamel.yaml
    import json
    
    yaml = ruamel.yaml.YAML(typ='safe')
    ind = dict()
    data = dict(indicator=ind)
    for d in yaml.load_all(open('input.yaml')):
        for k in ('detection', 'fields', 'falsepositives', 'level'):
            ind.setdefault(k, []).append(d[k])
    
    json.dump(data, sys.stdout, indent=2)
    

    如果你有文件input.yaml:

    ---
    title: Windows Shell Spawning Suspicious Program
    status: experimental
    description: Detects a suspicious child process of a Windows shell
    references:
        - https://mgreen27.github.io/posts/2018/04/02/DownloadCradle.html
    author: Florian Roth
    date: 20018/04/06
    logsource:
        product: windows
        service: sysmon
    detection:
        selection:
            EventID: 1
            ParentImage:
                - '*\mshta.exe'
                - '*\powershell.exe'
                - '*\cmd.exe'
                - '*\rundll32.exe'
                - '*\cscript.exe'
                - '*\wscript.exe'
                - '*\wmiprvse.exe'
            Image:
                - '*\schtasks.exe'
                - '*\nslookup.exe'
                - '*\certutil.exe'
                - '*\bitsadmin.exe'
                - '*\mshta.exe'
        condition: selection
    fields:
        - CommandLine
        - ParentCommandLine
    falsepositives:
        - Administrative scripts
    level: medium
    ...
    ---
    title: Bash starting just what is asked
    status: stabel
    description: No negative side effects
    references:
        - https://nblue24.github.io/posts/2019/04/01/DownloadBed.html
    author: Axel Roth
    date: 2019/04/01
    logsource:
        product: linux
        service: good
    detection:
        selection:
            EventID: 42
            ParentImage:
                - '*/bash'
                - '*/ash'
            Image:
                - systemctl
                - init
        condition: selection
    fields:
        - Shell
        - ParentShell
    falsepositives:
        - root programs
    level: high
    ...
    

    您的输出将是:

    {
      "indicator": {
        "detection": [
          {
            "selection": {
              "EventID": 1,
              "ParentImage": [
                "*\\mshta.exe",
                "*\\powershell.exe",
                "*\\cmd.exe",
                "*\\rundll32.exe",
                "*\\cscript.exe",
                "*\\wscript.exe",
                "*\\wmiprvse.exe"
              ],
              "Image": [
                "*\\schtasks.exe",
                "*\\nslookup.exe",
                "*\\certutil.exe",
                "*\\bitsadmin.exe",
                "*\\mshta.exe"
              ]
            },
            "condition": "selection"
          },
          {
            "selection": {
              "EventID": 42,
              "ParentImage": [
                "*/bash",
                "*/ash"
              ],
              "Image": [
                "systemctl",
                "init"
              ]
            },
            "condition": "selection"
          }
        ],
        "fields": [
          [
            "CommandLine",
            "ParentCommandLine"
          ],
          [
            "Shell",
            "ParentShell"
          ]
        ],
        "falsepositives": [
          [
            "Administrative scripts"
          ],
          [
            "root programs"
          ]
        ],
        "level": [
          "medium",
          "high"
        ]
      }
    }
    

    这适用于 Python 2 和 3。

    【讨论】:

    • 非常感谢,这太完美了。
    • 您知道是否有办法将每个指标的标题/检测/归档/等...分开而不是放在一起?
    • 如果我知道你在问什么,我可能会。提出一个新问题,minimize 输入文件(我使用的比必要的要大得多,但我懒得把它剪下来回答我的问题,你的问题不应该这么懒惰),包括你拥有的程序(我的,改编的?),你得到的 JSON 输出和你想要的 JSON 输出。您可以将此问题/我的答案称为背景知识,但要使新问题自成一体。用 [python] 和 [ruamel.yaml] 标记它,我会自动收到通知。
    【解决方案2】:
    import yaml
    import json
    
    data = {}
    data['indicator'] = {}
    data['indicator']['detection']=[]
    data['indicator']['fields']=[]
    data['indicator']['falsepositives']=[]
    data['indicator']['level']=[]
    
    def parse_string(s, data):
        doc = next(yaml.safe_load_all(s))
    
        data['indicator']['detection'].append(doc['detection'])
        data['indicator']['fields'].append(doc['fields'])
        data['indicator']['falsepositives'].append(doc['falsepositives'])
        data['indicator']['level'].append(doc['level'])
    
    with open(yaml_file, 'r') as yaml_in, open(json_file, 'a') as definition:
        parse_string(yaml_in.read(), data)
        json.dump(data, definition, indent=4)
    

    【讨论】:

    • 所以这非常接近我的需要 - 但是,它不会向我的 json 文件写入任何内容,它只会将最终指标输出到我的 ipython 控制台:Out[47]: ' {"indicator": {"detection": [{"selection": {"EventID": 1, "Image": ["*\\\\schtasks.exe", "*\\\\nslookup.exe", "*\\\\certutil.exe"、"*\\\\bitsadmin.exe"、"*\\\\mshta.exe"]、"ParentImage": ["*\\\\mshta.exe", “*\\\\powershell.exe”、“*\\\\cmd.exe”、“*\\\\rundll32.exe”、“*\\\\cscript.exe”、“*\\\\ wscript.exe"、"*\\\\wmiprvse.exe"]}、"条件":"选择"}]、"字段":[["CommandLine"、"ParentCommandLine"]]、"级别":["中”], ...
    • @tparrott ups,最后一行的缩进,现在应该可以工作了
    • 其实——这仍然只是将其中一个yaml文档输出到json文件中,有没有办法全部打印出来?
    • @tparrott 你可以使用pprint 模块来打印它。
    猜你喜欢
    • 2016-02-16
    • 2019-01-04
    • 2018-11-23
    • 2012-12-16
    • 1970-01-01
    • 2020-04-01
    • 1970-01-01
    • 2012-10-12
    • 2017-06-01
    相关资源
    最近更新 更多