Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error (Hit/Block) Logs in JSON Format #1151

Open
superstes opened this issue Sep 21, 2024 · 5 comments
Open

Error (Hit/Block) Logs in JSON Format #1151

superstes opened this issue Sep 21, 2024 · 5 comments
Assignees

Comments

@superstes
Copy link

superstes commented Sep 21, 2024

Summary

I have not seen any option in the documentation to change the error/block log format.

JSON format would make sense for many use-cases. Also the audit-logs seem to already support it.

Basic example

It would be nice to get this as json object:
[client \"::ffff:95.214.55.x\"] Coraza: Warning. Host header is a numeric IP address [file \"/etc/coraza-spoa/coreruleset/rules/@owasp_crs/REQUEST-920-PROTOCOL-ENFORCEMENT.conf\"] [line \"1772\"] [id \"920350\"] [rev \"\"] [msg \"Host header is a numeric IP address\"] [data \"159.69.187.x\"] [severity \"warning\"] [ver \"OWASP_CRS/4.0.0-rc2\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-protocol\"] [tag \"paranoia-level/1\"] [tag \"OWASP_CRS\"] [tag \"capec/1000/210/272\"] [tag \"PCI/6.5.10\"] [hostname \"::ffff:159.69.187.x\"] [uri \"/\"] [unique_id \"FMPGEMUVBOHBCEMH\"]

Motivation

JSON is much easier to parse than the stringified format.
Log systems like Graylog and Grafana-Loki/-Agent can parse JSON natively & performant. That is very convenient - especially as such security-logs are very important to process.

Users could compile coraza with a error-callback, but that is only a workaround and not that easy/clean to implement when using a 'connector' like coraza-spoa

From what I've read into the source - this is where the logs are written: https://github.com/corazawaf/coraza/blob/main/internal/corazarules/rule_match.go#L254

Related to: #856, corazawaf/coraza-caddy#20, corazawaf/coraza-spoa#91, #1150

I'm open to contribute.

@superstes
Copy link
Author

Of course - one could use WithErrorCallback to override it with a custom format - but that might not be doable or be favourable for 'users'.

@superstes
Copy link
Author

superstes commented Sep 21, 2024

Basic callback for reference:

func createWAF() coraza.WAF {
	waf, err := coraza.NewWAF(
		coraza.NewWAFConfig().
			WithErrorCallback(logErrorJSON),
	)
	if err != nil {
		log.Fatal(err)
	}
	return waf
}

type errorLogJSON struct {
	File       string   `json:"file"`
	Line       int      `json:"line"`
	ID         int      `json:"rule_id"`
	Revision   string   `json:"rev"`
	Msg        string   `json:"msg"`
	Data       string   `json:"data"`
	SeverityID int      `json:"sev_id"`
	Severity   string   `json:"sev"`
	Version    string   `json:"ver"`
	Maturity   int      `json:"mat"`
	Accuracy   int      `json:"acc"`
	Client     string   `json:"client"`
	Disruptive bool     `json:"disruptive"`
	Tags       []string `json:"tags"`
	Server     string   `json:"server"`
	URI        string   `json:"uri"`
	UniqueID   string   `json:"unique_id"`
}

func logErrorJSON(mr types.MatchedRule) {
	r := mr.Rule()
	j, _ := json.Marshal(errorLogJSON{
		File:       r.File(),
		Line:       r.Line(),
		ID:         r.ID(),
		Revision:   r.Revision(),
		Msg:        mr.Message(),
		Data:       mr.Data(),
		Severity:   r.Severity().String(),
		SeverityID: r.Severity().Int(),
		Version:    r.Version(),
		Maturity:   r.Maturity(),
		Accuracy:   r.Accuracy(),
		Client:     mr.ClientIPAddress(),
		Server:     mr.ServerIPAddress(),
		Disruptive: mr.Disruptive(),
		Tags:       r.Tags(),
		URI:        mr.URI(),
		UniqueID:   mr.TransactionID(),
	})
	fmt.Println(string(j[:]))
}

Results in:
{"file":"coreruleset/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf","line":1210,"rule_id":941160,"rev":"","msg":"NoScript XSS InjectionChecker: HTML Injection","data":"Matched Data: \u003cscript found within REQUEST_HEADERS:Referer: http://localhost:8090/?a=\u003cscript\u003ealert(1)\u003c/script\u003e","sev_id":2,"sev":"critical","ver":"OWASP_CRS/4.7.0-dev","mat":0,"acc":0,"client":"[::1]","disruptive":false,"tags":["application-multi","language-multi","platform-multi","attack-xss","xss-perf-disable","paranoia-level/1","OWASP_CRS","capec/1000/152/242"],"server":"","uri":"/favicon.ico","unique_id":"YuxjbYnedOyrPYNkyFy"}

@superstes
Copy link
Author

BTW: Looks like the ocsf-auditlog does something similar - https://github.com/corazawaf/coraza/blob/main/internal/auditlog/formats_ocsf.go#L84

@superstes superstes changed the title Error (Block-) Logs in JSON Format Error (Hit/Block) Logs in JSON Format Oct 23, 2024
@fzipi
Copy link
Member

fzipi commented Oct 27, 2024

This is normally handled by using the SecAuditLogFormat directive.

@fzipi fzipi self-assigned this Oct 27, 2024
@superstes
Copy link
Author

Thank you for responding. I appreciate it!

I've actually tested using the SecAuditLogFormat and it works fine for the AuditLogs but does not change the format of the error logs. Reference: #1150

As the AuditLogs include the body, they might be too verbose for some users/environments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants