見出し画像

TWLogEye開発26日目:昨日見つけた難題をコツコツと解決しています

今朝は、4時前に起きました。コヒーを淹れに1階の台所に行くと、助手の猫さんも起きていて、暗闇で爪とぎしていました。猫さんは5時前に一度、かみさんを起こそうと騒いでいました。私が呼ばれてお世話したあと、かみさんの布団で寝たようです。

昨日見つけた難題を調べて解決しています。

Sigmaルールの判定時のエラー

読み込み時には、エラーはなかったのですが、判定する時に

2025/02/08 06:17:29 sigma matches err=error evaluating search keywords: keywords unsupported
2025/02/08 06:17:29 sigma matches err=error evaluating search filter_optional_generic: keywords unsupported

のようなエラーが出ている問題です。go-sigma

のソースコードを真面目に読んでみると、

	if len(search.Keywords) > 0 {
		return false, fmt.Errorf("keywords unsupported")
	}

というエラーでした。フィールドを指定しないキーワードだけ指定したルールはサポートしていないということです。
エラーログが大量にでないように、このような定義はルールの読み込みの時にエラーにするよう修正しました。ついでに、

  • IDが重複するルールは複数読み込まない

  • IDとタイトルの重複をチェックできるようにした

  • ルールの動作をテストするコマンドを追加

を行いました。

WindowsイベントログのJSON化がおかしい

セキュリティーのログを監視してJSON化していますが、クライアントから読み出すと

2025-02-08T06:00:26.8822441+09:00 Security {"Event": {"-xmlns": "http://schemas.microsoft.com/win/2004/08/events/event", "System": {"Execution": {"-ProcessID": 4, "-ThreadID": 972}, "Security": "", "TimeCreated": {"-SystemTime": "2025-02-07T21:00:26.8822441Z"}, "EventRecordID": 13648186, "Computer": "YMIRYZ", "EventID": 4689, "Opcode": 0, "Keywords": "0x8020000000000000", "Correlation": "", "Channel": "Security", "Version": 0, "Level": 0, "Task": 13313, "Provider": {"-Name": "Microsoft-Windows-Security-Auditing", "-Guid": "{54849625-5478-4994-a5ba-3e3b0328c30d}"}}, "EventData": {"Data": [{"#content": "S-1-5-21-1734809770-1267934487-2188562794-1001", "-Name": "SubjectUserSid"}, {"#content": "ymi", "-Name": "SubjectUserName"}, {"#content": "YMIRYZ", "-Name": "SubjectDomainName"}, {"#content": "0x162cc6", "-Name": "SubjectLogonId"}, {"#content": "0x0", "-Name": "Status"}, {"#content": "0x2048", "-Name": "ProcessId"}, {"#content": "C:\\Windows\\System32\\conhost.exe", "-Name": "ProcessName"}]}}}

のような感じでJSON化がおかしい問題です。
こちらは、WindowsのイベントログのXMLからJSONに変換する処理を真面目に作ることにしました。

のような感じの処理です。
元のXMLは、

<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>
    <System>
        <Provider Name='Microsoft-Windows-HttpService' Guid='{dd5ef90a-6398-47a4-ad34-4dcecdef795f}' />
        <EventID>113</EventID>
        <Version>0</Version>
        <Level>4</Level>
        <Task>5</Task>
        <Opcode>122</Opcode>
        <Keywords>0x4000000000000040</Keywords>
        <TimeCreated SystemTime='2023-08-18T00:24:21.1687683Z' />
        <EventRecordID>9925</EventRecordID>
        <Correlation />
        <Execution ProcessID='4212' ThreadID='15676' />
        <Channel>System</Channel>
        <Computer>YMIRYZ</Computer>
        <Security UserID='S-1-5-19' />
    </System>
    <EventData>
        <Data Name='UrlGroupId'>18302628890465533987</Data>
        <Data Name='Url'>http://*:2869/upnp/eventing/</Data>
        <Data Name='Status'>0</Data>
        <Data Name='ProcessId'>4212</Data>
        <Data Name='ExecutablePath'>\Device\HarddiskVolume3\Windows\System32\svchost.exe</Data>
        <Data Name='UserSid'>S-1-5-19</Data>
    </EventData>
</Event>

のような感じです。このXMLからGo言語のデータ(struct)を作るよいツールを見つけました。

です。Webでできます。
変換したGo言語のデータ定義は、

// Event was generated 2025-02-09 05:23:05 by https://xml-to-go.github.io/ in Ukraine.
type Event struct {
	XMLName xml.Name `xml:"Event"`
	Text    string   `xml:",chardata"`
	Xmlns   string   `xml:"xmlns,attr"`
	System  struct {
		Text     string `xml:",chardata"`
		Provider struct {
			Text string `xml:",chardata"`
			Name string `xml:"Name,attr"`
			Guid string `xml:"Guid,attr"`
		} `xml:"Provider"`
		EventID     string `xml:"EventID"`
		Version     string `xml:"Version"`
		Level       string `xml:"Level"`
		Task        string `xml:"Task"`
		Opcode      string `xml:"Opcode"`
		Keywords    string `xml:"Keywords"`
		TimeCreated struct {
			Text       string `xml:",chardata"`
			SystemTime string `xml:"SystemTime,attr"`
		} `xml:"TimeCreated"`
		EventRecordID string `xml:"EventRecordID"`
		Correlation   string `xml:"Correlation"`
		Execution     struct {
			Text      string `xml:",chardata"`
			ProcessID string `xml:"ProcessID,attr"`
			ThreadID  string `xml:"ThreadID,attr"`
		} `xml:"Execution"`
		Channel  string `xml:"Channel"`
		Computer string `xml:"Computer"`
		Security string `xml:"Security"`
	} `xml:"System"`
	EventData struct {
		Text string `xml:",chardata"`
		Data []struct {
			Text string `xml:",chardata"`
			Name string `xml:"Name,attr"`
		} `xml:"Data"`
	} `xml:"EventData"`
} 

です。これを

の例のようなJSONに変換するプログラムを作りました。

package main

import (
	"encoding/json"
	"encoding/xml"
	"log"
	"os"
)

type Event struct {
	XMLName xml.Name `xml:"Event"`
	Text    string   `xml:",chardata"`
	Xmlns   string   `xml:"xmlns,attr"`
	System  struct {
		Text     string `xml:",chardata"`
		Provider struct {
			Text string `xml:",chardata"`
			Name string `xml:"Name,attr"`
			Guid string `xml:"Guid,attr"`
		} `xml:"Provider"`
		EventID     string `xml:"EventID"`
		Version     string `xml:"Version"`
		Level       string `xml:"Level"`
		Task        string `xml:"Task"`
		Opcode      string `xml:"Opcode"`
		Keywords    string `xml:"Keywords"`
		TimeCreated struct {
			Text       string `xml:",chardata"`
			SystemTime string `xml:"SystemTime,attr"`
		} `xml:"TimeCreated"`
		EventRecordID string `xml:"EventRecordID"`
		Correlation   string `xml:"Correlation"`
		Execution     struct {
			Text      string `xml:",chardata"`
			ProcessID string `xml:"ProcessID,attr"`
			ThreadID  string `xml:"ThreadID,attr"`
		} `xml:"Execution"`
		Channel  string `xml:"Channel"`
		Computer string `xml:"Computer"`
		Security struct {
			Text   string `xml:",chardata"`
			UserID string `xml:"UserID,attr"`
		} `xml:"Security"`
	} `xml:"System"`
	EventData struct {
		Text string `xml:",chardata"`
		Data []struct {
			Text string `xml:",chardata"`
			Name string `xml:"Name,attr"`
		} `xml:"Data"`
	} `xml:"EventData"`
}

func main() {
	b, err := os.ReadFile(os.Args[1])
	if err != nil {
		log.Fatalln(err)
	}
	var x Event
	if err := xml.Unmarshal(b, &x); err != nil {
		log.Fatalln(err)
	}
	edmap := make(map[string]interface{})
	for _, d := range x.EventData.Data {
		edmap[d.Name] = d.Text
	}
	m := map[string]interface{}{
		"Event": map[string]interface{}{
			"System": map[string]interface{}{
				"Channel":       x.System.Channel,
				"Computer":      x.System.Computer,
				"Correlation":   x.System.Correlation,
				"EventID":       x.System.EventID,
				"EventRecordID": x.System.EventRecordID,
				"Execution": map[string]interface{}{
					"ProcessID": x.System.Execution.ProcessID,
					"ThreadID":  x.System.Execution.ThreadID,
				},
				"Keywords": x.System.Keywords,
				"Level":    x.System.Level,
				"Opcode":   x.System.Opcode,
				"Provider": map[string]interface{}{
					"Guid": x.System.Provider.Guid,
					"Name": x.System.Provider.Name,
				},
				"Security": map[string]interface{}{
					"UserID": x.System.Security.UserID,
				},
				"Task": x.System.Task,
				"TimeCreated": map[string]interface{}{
					"SystemTime": x.System.TimeCreated.SystemTime,
				},
				"Version": x.System.Version,
			},
			"EventData": edmap,
		},
	}
	j, err := json.MarshalIndent(&m, "", "  ")
	if err != nil {
		log.Fatalln(err)
	}
	log.Printf("j=%s", string(j))

}

です。変換結果は、

{
  "Event": {
    "EventData": {
      "ProcessId": "0x4220",
      "ProcessName": "C:\\Program Files\\Docker\\Docker\\resources\\bin\\docker.exe",
      "Status": "0x0",
      "SubjectDomainName": "YMIRYZ",
      "SubjectLogonId": "0x162cc6",
      "SubjectUserName": "ymi",
      "SubjectUserSid": "S-1-5-21-1734809770-1267934487-2188562794-1001"
    },
    "System": {
      "Channel": "Security",
      "Computer": "YMIRYZ",
      "Correlation": "",
      "EventID": "4689",
      "EventRecordID": "13971171",
      "Execution": {
        "ProcessID": "4",
        "ThreadID": "15464"
      },
      "Keywords": "0x8020000000000000",
      "Level": "0",
      "Opcode": "0",
      "Provider": {
        "Guid": "{54849625-5478-4994-a5ba-3e3b0328c30d}",
        "Name": "Microsoft-Windows-Security-Auditing"
      },
      "Security": {
        "UserID": ""
      },
      "Task": "13313",
      "TimeCreated": {
        "SystemTime": "2025-02-08T17:04:32.8719251Z"
      },
      "Version": "0"
    }
  }
}

になりました。いい感じだと思いますが、EventIDなどは数値にしたほうがよいかもしれません。
調子がでてきましたが、今朝は、ここまで

明日に続く

いいなと思ったら応援しよう!

twsnmp
開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。