Saturday, November 28, 2015

Vendor lookup for AT&T: Who's on your network?

Happy Thanksgiving! 


Hope you enjoyed time with family, friends, relaxing or shopping this weekend.

Many times I find myself looking up a mac address on a network to figure out who the vendor is.
Identifying the vendor for a mac address is helpful when trying to identify nodes on your network which have obscure hostnames. This can also help identify mac spoofing and make investigating devices on your network much easier.

Typically, if I find myself performing a repetitive task I try to automate it using python. So let's get started. 

AT&T Provides their users with a nice table at the home page of the router which requires no authentication. Just access to the network.

AT&T Homepage Screenshot (Hostnames and second half of MAC omitted)

GOAL: Load table into dataframe and perform vendor lookup for each MAC

If you're not familiar with dataframes, I encourage you to read pandas data structures intro. At it's core a dataframe is a container for Series objects (lists) within pandas. The value of converting a table into a dataframe is the powerful collection of analytical methods associated with each dataframe object. 

For a while, I've looked for reasons to try pandas read_html method. Finally... the perfect occasion! read_html uses python modules such as lmxl, beautifulSoup, and html5lib to extract attributes out of a web page, transform the data, and load it into a dataframe.

Using chrome's inspection tool to look for a unique attribute I found width=800 was unique to the table.
Chrome inspector

TIP: read_html requires the <table> tag in your data. If you want to use pd.read_html and your data does not have a table tag you can add it by concatenating your data '<table> %s </table>' % data

Let's extract and load the data:

import requests
import pandas as pd

#Address for AT&T Modem
pull_macs_url = 'http://192.168.1.254/cgi-bin/home.ha'


#load data into dataframe using the width attribute
df = pd.read_html(pull_macs_url, attrs={'width':'800'}, header=0)[0]

Let's verify our data loaded by printing out the dataframe.

print(df)

Device IPv4 Address / Name MAC Address Status Connection Allocation
0 192.168.1.64 / removed 40:b7:f3:removed on Ethernet dhcp
1 192.168.1.68 / removed bc:c8:10:removed on Ethernet dhcp
2 192.168.1.71 / removed 00:23:74:removed on HPNA dhcp
3 192.168.1.72 / removed 00:1f:c4:removed on HPNA dhcp

Success! We have our dataframe, now we need to:

  1. Isolate the MAC Addresses into a single Series
  2. Find a MAC database
  3. Write a function to apply to our dataframe which will run against the MAC Addresses
  4. Add the vendor to a new Series (column) in the dataframe.
To Isolate the MAC Addresses we simply retrieve the column in the dataframe (This can be done in one step later, but for clarity I've made this a separate step)
mac_addresses = df['MAC Address']

The MAC Vendor API I found is located at www.macvendors.com. They provide 10,000 requests per day and no registration or API key is required. A sample request might look like: http://api.macvendors.com/FC-A1-3E-2A-1C-33

If macvendor.com cannot associate a vendor to a MAC it will return a 404. This is good to know so we can check the status code in our function.

Here is the function I went with:

def vendor_loookup(mac):
    from urllib.parse import quote_plus
    vendor = None
    try:
        vendor_lookup = 'http://api.macvendors.com/%s' % quote_plus(mac)
        vendor_response = requests.get(vendor_lookup)
        if vendor_response.status_code != 200:
            vendor = 'No Vendor Found'
        else:
            vendor = vendor_response.text
    except:
        vendor = 'Error'
    return vendor

Now we need to apply our function to the MAC addresses, add the vendor to a new column and display the results


df['Vendor'] = mac_addresses.apply(vendor_loookup)

Device IPv4 Address / Name MAC Address Status Connection Allocation Vendor
1 192.168.1.68 / removed bc:c8:10:removed on Ethernet dhcp CISCO SPVTG
2 192.168.1.71 /removed00:23:74:removed on HPNA dhcp ARRIS GROUP, INC.
5 192.168.1.76 / removed 00:19:9d:removed off Wireless dhcp VIZIO, INC.
14 192.168.1.98 / removed 90:b6:86:removed off Wireless dhcp MURATA MANUFACTURING CO., LTD.
15 192.168.1.101 / removed 00:22:5f:removed on Wireless dhcp LITEON TECHNOLOGY CORPORATION
16 192.168.1.106 / removed 5c:f6:dc:removed on Wireless static SAMSUNG ELECTRONICS CO.,LTD
17 192.168.1.107 / removed c6:12:f5:removed on Ethernet dhcp No Vendor Found
18 192.168.1.112 / removed 18:59:33:removed on Ethernet dhcp CISCO SPVTG
19 192.168.1.114 / removed bc:c8:10:removed on Ethernet dhcp CISCO SPVTG
20 192.168.1.115 / removed 00:1f:a7:removed on Wireless dhcp SONY COMPUTER ENTERTAINMENT INC.
21 192.168.1.117 / removed f0:24:75:removed off Wireless dhcp APPLE, INC.
22 192.168.1.118 / removed 30:59:b7:removed off Wireless dhcp MICROSOFT

Now we have our mac addresses associated with vendors. Time to harness the power of pandas and group by vendor to help illustrate groupings.


Vendor_DF = pd.DataFrame(df.groupby(['Vendor', 'Device IPv4 Address / Name', 'MAC Address']).size())
Vendor_DF = Vendor_DF.drop(0, axis=1)

And finally... we have MAC addresses grouped by vendor. This can help identify rogue nodes and provide insight to what devices are on your network. 

Vendor Device IPv4 Address / Name MAC Address
APPLE, INC. 192.168.1.117 / bobs-iPad f0:24:75:removed
192.168.1.183 / macbook ac:bc:32:removed
192.168.1.92 / removed 7c:d1:c3:removed
ARRIS GROUP, INC. 192.168.1.64 / removed 40:b7:f3:removed
192.168.1.71 / removed 00:23:74:removed
192.168.1.72 / removed 00:1f:c4:removed
192.168.1.74 / removed 00:25:f1:removed
192.168.1.82 / removed cc:7d:37:removed
CISCO SPVTG 192.168.1.112 / removed 18:59:33:removed
192.168.1.114 / removed bc:c8:10:removed
192.168.1.68 / Cisco_AP_ATT bc:c8:10:removed
GAINSPAN CORP. 192.168.1.97 / removed 00:1d:c9:removed
H&D WIRELESS 192.168.1.87 / removed 78:c4:0e:removed
HEWLETT PACKARD 192.168.1.90 / removed 6c:c2:17:removed
192.168.1.93 / removed 3c:4a:92:removed
LG INNOTEK 192.168.1.175 / removed 94:44:44:removed
LITEON TECHNOLOGY CORPORATION 192.168.1.101 / Toms-PC 00:22:5f:removed
MICROSOFT 192.168.1.118 / Xbox-SystemOS 30:59:b7:removed
192.168.1.173 / Xbox-SystemOS 30:59:b7:removed
MURATA MANUFACTURING CO., LTD. 192.168.1.192 / removed 90:b6:86:removed
192.168.1.98 / removed 90:b6:86:removed
No Vendor Found 192.168.1.107 / removed c6:12:f5:removed
192.168.1.181 / removed c6:12:f5:removed
192.168.1.182 / removed c6:12:f5:removed
192.168.1.184 / removed c6:12:f5:removed
192.168.1.189 / removed c6:12:f5:removed
192.168.1.190 / removed c6:12:f5:removed
192.168.1.193 / removed c6:12:f5:removed
192.168.1.196 / removed c4:2f:ac:removed
SAMSUNG ELECTRO MECHANICS 192.168.1.88 / removed dc:71:44:removed
SAMSUNG ELECTRO MECHANICS CO., LTD. 192.168.1.185 / removed f0:25:b7:removed
SAMSUNG ELECTRONICS CO.,LTD 192.168.1.106 / removed 5c:f6:dc:removed
192.168.1.177 / removed 38:2d:e8:removed
SHENZHEN BILIAN ELECTRONIC CO.,LTD 192.168.1.180 / removed 20:f4:1b:removed
SONY COMPUTER ENTERTAINMENT INC. 192.168.1.115 / removed 00:1f:a7:removed
VIZIO, INC. 192.168.1.76 / removed 00:19:9d:removed
192.168.1.83 / removed 00:19:9d:removed

This was a basic introduction to identifying nodes on your network and how to correlate mac addresses to vendors using pandas with python.

All code can found on my github account.

No comments:

Post a Comment