Uber 遠端代碼執行- Uber.com Remote Code Execution via Flask Jinja2 Template Injection

preview

好久沒 po 文了XD

幾天前,Uber 公佈了 Bug Bounty 計畫,從 Hackerone 上看到獎金不低,最少的 XSS / CSRF 都有 3000 美金起就跳下來看一下有什麼好玩的XD

從官方公佈的技術細節發現 Uber 主要網站是以 Python Flask 以及 NodeJS 為架構,所以在尋找漏洞的時候自然會比較偏以測試這兩種 Framework 的漏洞為主!

Uber 網站在進行一些動作如修改電話、姓名時,會以寄信及簡訊的方式告知使用者帳號進行了變更,在某次動作後發現 Uber 寄過來的信如下圖,怎麼名字會多個 “2” XDDDD

往前追查原因才發現進入點是在 Riders.uber.com,Riders.uber.com 為修改個人資料以及顯示帳單、行程行程的地方,在修改的姓名中,使用了

1
{{ 1+1 }}

這個 payload 導致的,漏洞大概成因是 Python Flask 中預設使用的模板引擎是 Jinja2,在 Jinja2 中可使用些許的 Python 語法來幫助產生 HTML (當然有 Sandbox)

所以 {{ 1+1 }} 就被 Python 解析成 2 並且放置信件中寄到我的信箱,更詳細的內容可參考由 PortSwigger (BurpSuite 開發人員) 在 BlackHat 2015 發表的 Server-Side Template Injection:RCE for the modern webapp

所以現在我可以使用 Jinja2 的語法有限度的在姓名欄位寫 Python 程式碼了! 如在姓名欄位依照 Jinja2 語法填入

1
{% for c in [1,2,3] %}{{ c,c,c }}{% endfor %}

利用模板引擎叫 Uber 伺服器幫我們跑個 FOR 迴圈,結果還會寄到你信箱XD

成功執行 FOR 迴圈! 不過在文章前面有提到,可以執行 Python Code 但並不是無限制,Jinja2 中有 Sandbox 來對危險的用法、函數進行防護。

不過這個對常玩 CTF 的人絕對不是問題,在各個比賽中很常出現 Python 的 Sandbox 繞過用到的手法可以直接拿來這裡用!

詳細技術細節可以參考

如使用

1
{{ [].__class__.__base__.__subclasses__() }}

可列出所有引用的模組, 如

會顯示是空的是因為被 HTML < > 包起來了,檢視原始信件就可以看到了XD

額外一提的是在引用模組中看到 Celery,因此可以猜測網站大致架構應該是:

從 Riders.uber.com 這個進入點修改姓名後存進資料庫

不過為了寄送簡訊以及信件等耗時的工作,使用 Asynchronous Task 機制交給後方的 Worker

而當 Worker 再從資料庫抓出姓名產生模板時使用串接的方式直接將模板產生所以導致了這次遠端代碼執行 :P

寫到這,最後廢言一下,對我來說,其實玩 Bug Bounty 獎金什麼都是額外的,最主要的是可以找出別人找不出、別人發現不了的漏洞,回報並且讓別人也認同你的發現,這其中得到的成就感才是最爽的XD