Contextual Commands

노션으로 옮김·2023년 11월 19일
0

Case 1. Search event logs that contain specific domains

In Boss Of The Soc Version 1(2015)

Outbound communication has been detected from the web server 192.168.250.70 to prankglassinebracket.jumpingcrab.com.
We need to identify the request packet associated with this outbound activity.

Use foreach to iterate through all fields, extracting domain values into temp_domain_addr using rex command.
Then, store them into domain_addr if there's no same value, and separate domain_addr into each domain using the split command for identification

index=* dest_ip=192.168.250.70 OR dest=192.168.250.70 sourcetype IN ("fgt_utm", "stream:http", "suricata") "prankglassinebracket.jumpingcrab.com"
| eval domain_addr=""
| foreach * 
    [ rex field=<<FIELD>> "(?:https*://)*(?P<temp_domain_addr>[\w\-0-9]+?\.[\w\-0-9]+?\.[\w\-0-9]+(?:\:\d+)*)" 
    | eval temp_domain_addr=if(isnull(temp_domain_addr), "", temp_domain_addr)
    | eval domain_addr=if(like(domain_addr, "%".temp_domain_addr."%"), domain_addr, domain_addr.";".temp_domain_addr)]
| eval domain_addr=split(domain_addr, ";") 
| mvexpand domain_addr
| stats values(sourcetype) values(dest_ip) c by domain_addr

Case 2. Verify event logs in chronological order based on sourcetypes

index="index" "src" "dest"
| bin span=3m _time 
| eval src_ip = if(isnull(src_ip), if(isnull(src), s_ip, src), src_ip) 
| eval src_port = if(isnull(src_port), s_port, src_port) 
| eval dest_ip = if(isnull(dest_ip), if(isnull(dest), d_ip, dest), dest_ip) 
| eval dest_port = if(isnull(dest_port), d_port, dest_port) 
| stats values(*) as * c by _time src_ip src_port 
| eval src_port = mvindex(src_port, 0, 4)
| eval dest_port = mvindex(dest_port, 0, 4)
| table _time sourcetype src_ip src_port dest_ip dest_port 
| sort _time

Additionally, if you add specified fields, you can visibly trace the change in its value, such as:

Basic search
| bin span=10m _time 
| rename http.* as sc_http_* 
| rename *{} as *_ 
|  rename alert.* as alert_*
| eval time=strftime(_time, "%Y-%m-%d %H-%M")
| eval src_ip = if(isnull(src_ip), if(isnull(src), s_ip, src), src_ip) 
| eval src_ip = if(src_ip="192.168.250.100" or c_ip="192.168.250.100", "192.168.250.100", src_ip) 
| eval src_port = if(isnull(src_port), s_port, src_port) 
| eval dest_ip = if(isnull(dest_ip), if(isnull(dest), d_ip, dest), dest_ip) 
| eval dest_ip = if(src_ip="192.168.250.100", dest_ip, "192.168.250.100") 
| eval dest_port = if(isnull(dest_port), d_port, dest_port) 
| eval site = if(like(sourcetype, "suricata") and like(event_type, "http"), sc_http_hostname, site) 
| eval uri = if(like(sourcetype, "suricata") and like(event_type, "http"), url, uri) 
| eval filename = if(isnull(filename), "None", filename)
| eval command_ = if(isnull(command_), "None", command_)
| eval answer = if(isnull(answer), "None", answer) | eval record_type = if(isnull(record_type), "None",  record_type)  | eval query = if(isnull(query), if(isnull(hostname_), "None", hostname_),  query)
| mvexpand command_
| mvexpand answer
| mvexpand query
| mvexpand record_type
| strcat "[" command_ "] " filename smb_status
| strcat http_method " " site uri " -> " status HTTP_request
| strcat "[" record_type "] " query " -> " answer dns_qr
| eval sourcetype=case(like(sourcetype, "suricata"), sourcetype." : ".event_type, 1=1, sourcetype)
| stats values(*) as * c by _time src_ip dest_ip sourcetype 
| eval src_port = mvindex(src_port, 0, 4) 
| eval dest_port = mvindex(dest_port, 0, 4) 
| eval info = if(like(sourcetype, "stream:http") or (like(sourcetype, "suricata%") and (like(event_type, "http") or like(event_type, "fileinfo"))), HTTP_request, "")
| eval info = if(like(sourcetype, "stream:dns"), dns_qr, info) 
| eval signature = if(like(sourcetype, "suricata%") and like(event_type, "alert"), alert_signature, "") 
| eval info = if(like(sourcetype, "stream:smb") , smb_status, info) 
| table time sourcetype signature info src_ip src_port dest_ip dest_port 
| sort time

It will display information about a HTTP traffic and a DNS Query, in addition to the previous showed fields src, dest, and sourcetype:

Case 3. Verify all columns contained in each source type

index=* sourcetype IN ("suricata" "fgt_utm" "iis" "stream:http")
|  rename *{} as *_temp
|  rename tag::* as tag_*
|  eval sourcetype=if(like(sourcetype, "%suricata%"), "suricata_".event_type, sourcetype)
|  stats values(*) as * by sourcetype
| foreach * 
    [ eval <<FIELD>>=mvindex(<<FIELD>>, 0, 0)]
|  transpose 0 header_field=sourcetype
|  fillnull value=" "

If you are dealing with a single field, type the following command:

Basic search
| fieldsummary
| search values!="[]"
| fields field values
| rex field=values max_match=0 "\{\"value\":\"(?<extract_values>[^\"]+)\""
| fields field extract_values
| eval extract_values=mvdedup(extract_values)

As a reference, you can check the categories of sourcetypes using the command metadata as follows:

| metadata type=sourcetypes index=botsv1
| stats values(sourcetype)

Case 4. Display all parameters of the HTTP URL and HTTP Body transmitted within the HTTP Requests

If uri field exists, you can examine the names and values of all URL parameter to trace a brute force attack as follows:

"site"
|  rex field=uri "\/.+?\?(?P<prs>.+)"
|  search prs=*
|  eval prs=split(prs, "&") 
|  where mvcount(prs)>1  ``` If there's only one parameter, the likelihood of a brute force attack is low```
|  stats c by prs
|  eval temp = split(prs, "=")
|  eval pr_n=mvindex(temp,0) 
|  eval pr_v=mvindex(temp,1) 
|  stats values(pr_v) as pr_v c by pr_n

"site" "method" "src_content"
| rex field="src_content" "(?P<matched>[^&=]+\=[^&=]*(?:\&[^&=]+\=[^&=]*)+)" | where not isnull(matched) | sort -c
| stats values("src_content") as "src_content" c by matched
| eval matched=split(matched, "&")
| mvexpand matched
| eval temp = split(matched, "=")
| eval matched_n=mvindex(temp, 0)
| eval matched_v=mvindex(temp, 1)
| stats values(matched_v) as matched_v by matched_n 
| where mvcount(matched_v)>10 
| eval matched_v=mvindex(matched_v, 0, 9)

Case 5. Get the elapsed time between two events

basic search
| stats latest(_time) as time_login by cs_username 
| join cs_username 
    [ search index=iis a_action=event_status cs_username=* 
    | stats latest(_time) as time_finish by cs_username ] 
| eval difference=time_finish-time_login 
| eval difference=strftime(difference,"%d-%m-%Y %H:%M:%S")

Case 6. Find event logs which have fields with a length of 32 bits.

"exe file"
| rename *{} as *_brace 
| rename tag::* as tag__* 
| eval check_length = 0 
| eval check_values = "" 
| foreach * 
    [ eval check_length = if(len(<<FIELD>>)=32, 1, check_length) 
    | eval check_values=if(len(<<FIELD>>)=32, check_values."; ".<<FIELD>>, check_values)] 
| search check_length=1 

Appendix

  • | rename "*: *" AS *_*
    iterate through all the column names and replace space with underscore and replace :(colon space) with an underscore
  • highlight keyword1, keyword2, ...
  • reverse
    reverse command only affects the order of results, not which events are returned by the search.

0개의 댓글