Created
November 2, 2018 02:04
-
-
Save paralax/d644bfa364fd4107713e93707bd08333 to your computer and use it in GitHub Desktop.
prototype code to convert a web client user-agent to a sequence of MITRE CPE strings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import shlex | |
# application-specific | |
def tocpe(prodstring): | |
if prodstring.startswith('Mozilla') or prodstring.startswith('Gecko'): | |
return None | |
templ = 'cpe:/a:{0}:{1}:{2}' | |
vendor = '*' | |
application = '*' | |
version = '*' | |
try: | |
application, version = prodstring.lower().split('/') | |
return templ.format(vendor, application, version) | |
except ValueError: | |
return None | |
def extract_os(uastring): | |
cpes = [] | |
# look for signs of an OS | |
vendor = '*' | |
version = '*' | |
ostmpl = 'cpe:/o:{0}:{1}:{2}' | |
if 'Windows' in uastring: | |
vendor = 'microsoft' | |
os = 'windows' | |
elif 'Linux' in uastring: | |
vendor = 'linux' | |
os = 'linux' | |
elif 'Mac OS X' in uastring: | |
vendor = 'apple' | |
os = 'mac_os_x' | |
try: | |
version = re.findall('Mac OS X (\d+_\d+_?\d+?)', uastring)[0].replace('_', '.') | |
except IndexError: | |
pass | |
if vendor != '*': | |
cpes.append(ostmpl.format(vendor, os, version)) | |
return cpes | |
def extract_browser(uastring): | |
cpes = [] | |
# opera and MSIE are odd, handle | |
apptmpl = 'cpe:/a:{0}:{1}:{2}' | |
if 'MSIE' in uastring: | |
vendor = 'microsoft' | |
application = 'internet_explorer' | |
try: | |
for version in re.findall('MSIE (\d+\.\d+)', uastring): | |
cpes.append(apptmpl.format(vendor, application, version)) | |
except IndexError: | |
pass | |
if 'Opera' in uastring: | |
vendor = 'opera' | |
application = 'opera_browser' | |
try: | |
version = re.findall('Opera (\d+\.\d+)', uastring)[0] | |
except IndexError: | |
version = '*' | |
cpes.append(apptmpl.format(vendor, application, version)) | |
return cpes | |
def parse_ua(uastring): | |
cpes = list(filter(None, map(tocpe, shlex.split(uastring)))) | |
cpes.extend(extract_browser(uastring)) | |
cpes.extend(extract_os(uastring)) | |
return cpes | |
def test(): | |
for ua in ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36", | |
"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0", | |
"Mozilla/5.0 (Windows NT 6.1; rv:34.0) Gecko/20100101 Firefox/34.0", | |
"Morfeus Fucking Scanner", | |
"PycURL/7.43.0 libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3", | |
"Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.01 [en]"): | |
print(ua) | |
print(parse_ua(ua)) | |
test() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment