Converting Notice::Info to JSON

I’m creating a script that hooks Notice notice/policy and executes an ActiveHTTP call to submit specific notice events to a REST endpoint. In the submission I’d like to include the Notice::Info object as a JSON data field so tried:

to_json(n)

But it produces the following error:

1485869266.028563 error in /Users/dave/Projects/bro/share/bro/base/utils/json.bro, line 26: wrong port format, must be /[0-9]{1,5}/(tcp|udp|icmp)/ (to_port(cat(v)))

Do I need to manually re-package all the fields the Notice::Info, and if so, has anyone already done this so I can borrow the code? :slight_smile:

This is the Notice::Info object I’m testing with:

[ts=1485872499.141021, uid=CSRU563utEL1B2yFl5, id=[orig_h=10.0.2.15, orig_p=1381/tcp, resp_h=199.192.156.134, resp_p=443/tcp], conn=, iconn=, f=, fuid=, file_mime_type=, file_desc=, proto=tcp, note=Signatures::Sensitive_Signature, msg=10.0.2.15: ATTACK-RESPONSES Microsoft cmd.exe banner (reverse-shell originator), sub=POST /bbs/info.asp HTTP/1.1\x0d\x0aHost: 199.192.156.134:443\x0d\x0aContent-Length: 165\x0d\x0aConnection: Keep-Alive\x0d\x0aCache-Control: no-cache\x0d\x0a\x0d\x0a3D333531501A…, src=10.0.2.15, dst=199.192.156.134, p=443/tcp, n=, src_peer=[id=0, host=127.0.0.1, p=0/unknown, is_local=T, descr=bro, class=], peer_descr=bro, actions={
Phantom::ACTION_PHANTOM,
Notice::ACTION_LOG
}, email_body_sections=[], email_delay_tokens={

}, identifier=, suppress_for=1.0 hr, dropped=F, remote_location=]

-Dave

This looks like a bug in to_json (or possibly to_port)... but it's harmless and there are some workarounds you can do.

The json.bro code does this to convert ports to strings for json

        case "port":
        return cat(port_to_count(to_port(cat(v))));

but the unknown/uninitialized port of 0/unknown breaks to_port. It seems to_port needs to account for 0/unknown or json.bro should just be doing

        case "port":
        return cat(port_to_count(v));

I'm not sure why it does a double conversion like that in the first place.

In any case, the code still works even though it outputs that error. Since it doesn't understand the port it returns 0/unknown anyway, so the end result is the same:

$ cat j.bro
event bro_init()
{
    local c: conn_id;
    c$orig_h=1.2.3.4;
    c$resp_p=0/unknown;
    print to_json(c);
}
$ bro j.bro
error in /usr/local/Cellar/bro/HEAD/share/bro/base/utils/json.bro, line 26: wrong port format, must be /[0-9]{1,5}\/(tcp|udp|icmp)/ (to_port(cat(v)))
{"orig_h": "1.2.3.4", "resp_p": 0}
$

You could probably avoid the whole issue by using to_json like this:

    to_json(note, T);

to set the only_loggable option to true which should cause it to ignore fields that aren't normally logged in the first place.

Thanks Justin, that did the trick.

-Dave

A follow-up question on to_json() is if the function is always producing valid JSON? As an example:

to_json(n, T)

Produces a few field values that aren’t properly quoted, or in the case of Booleans, not converting T/F to true/false:

{“proto”: tcp, “peer_descr”: “bro”, “id”: {“resp_h”: “199.192.156.134”, “resp_p”: 443, “orig_h”: “10.0.2.15”, “orig_p”: 1381}, “dst”: “199.192.156.134”, “p”: 443, “sub”: “POST /bbs/info.asp HTTP/1.1\x0d\x0aHost: 199.192.156.134:443\x0d\x0aContent-Length: 165\x0d\x0aConnection: Keep-Alive\x0d\x0aCache-Control: no-cache\x0d\x0a\x0d\x0a3D333531501A…”, “suppress_for”: “”, “src”: “10.0.2.15”, “msg”: “10.0.2.15: ATTACK-RESPONSES Microsoft cmd.exe banner (reverse-shell originator)”, “note”: Signatures::Sensitive_Signature, “ts”: 1485952936.47094, “uid”: “CZwEv13Gadjmnaf6W6”, “dropped”: F, “actions”: [Notice::ACTION_LOG, Phantom::ACTION_TEST]}

-Dave

That sounds like a bug to me: if it says JSON, it should be JSON.
Please file a ticket for that.

Robin

As requested. BIT-1789

-Dave

I've fixed this issue (see https://bro-tracker.atlassian.net/browse/BIT-1788).

-Daniel

Awesome, thanks Daniel. I closed my ticket as a duplicate and referenced your ticket.

-Dave