前提說明:5月26日,該漏洞已被修復。環境的功能,當你點擊時,它能夠實現一鍵化配置和部署第三方組件、函數庫和應用。比如說你可以在如下頁面中看到這個標志https://dashboard.heroku.com/new?button-url=https%3A%2F%2Fgithub.com%2FParsePlatform%2Fparse-server-example&template=https%3A%2F%2Fgithub.com%2FParsePlatform%2Fparse-server-example
每個開發者都可以創建像上面那樣的“一鍵部署”按鈕,你可以從下面這個鏈接中看到更多說明。
我創建了一個“一鍵部署”按鈕,它只包含一個文件app.json,Heroku會從這個文件中讀取到該按鈕的相關信息。
一開始,我嘗試在app.json中插入HTML標簽和屬性來實現XSS,結果發現JavaScript會將特殊字符進行轉義。后來我發現某個URL中的“logo”可以被設置成任何值,然后當頁面被加載時,該URL會被設置成img標簽中的data-src的值。
當img標簽加載時,瀏覽器會向服務器發起獲取圖片的請求,這時候會帶上Referer的值,這時候只需要在服務器監聽該請求,即可獲取該Referer的值。
有關HTTP導致的信息泄露,可以參考cure53的搜集。漏洞
到目前為止,當我對下面這個進行加載時https://dashboard.heroku.com/new?template=https%3A%2F%2Fgithub.com%2FParsePlatform%2Fparse-server-example&other_parameter=with_value
如下的img標簽會被建立
https://avatars0.githubusercontent.com/u/1294580?v=3&s=200
這時候HTTP頭會帶上Referer的值,如下:
你也可以看到這里并沒有什么有用的數據。
接下來我去測試了一下Heroku的OAuth認證過程,當我將redirect_uri設置成如下時:https://dashboard.heroku.com/new?template=https%3A%2F%2Fgithub.com%2FParsePlatform%2Fparse-server-example&other_parameter=with_value
本以為可以成功從Referer獲取到有用的數據,但是卻沒有成功。
后來不知道什么時候,我注意到在身份驗證成功后[path_requested]會帶上一個參數code,這個參數的值在發送的時候并沒有防護CSRF攻擊,然后會以JSON的格式返回一個權限為“global”的“access_token”,這個“global”權限允許你通過API執行所有操作!但是我卻不能修改賬號的密碼或者綁定的郵箱…攻擊
只有當用戶登錄后攻擊才會生效。
1、先讓用戶訪問如下鏈接:
state=https%3A%2F%2Fdashboard.heroku.com%2Fnew%3Ftemplate%3Dhttps%253A%252F%252Fgithub.com%252Fesevece%252Fheroku_test
2、用戶會被重定向到如下地址:https://id.heroku.com/oauth/autorize?client_id=....
3、用戶再次被重定向到:https://longboard.heroku.com/auth/heroku/callback?code=....
4、最后,用戶被重定向到https://dashboard.heroku.com/new?template=https%3A%2F%2Fgithub.com%2Fesevece%2Fheroku_test&code=...
5、一旦頁面被加載,應用就會自動向Github的API發起獲取app.json的請求:https://api.github.com/repos/esevece/heroku_test/contents/app.json?ref=master
6、這時候如下payload被創建,然后發起獲取圖片的請求,Referer中會包含code。
7、我服務器上的文件poc.php 會截獲該img請求,獲取Referer中的code的值,然后發起如下POST請求:
來獲取token。將password參數的值設置為code的值
8、poc.php 獲取到7中得到的“access_token”,將頭部Authorization:設置成Bearer [獲取到的token],然后發起如下請求:
9、poc.php 獲取到上一步返回的“email”的值,然后自動發送一封提醒郵件給我。
上面說到我不能修改用戶的綁定郵箱,但是最后面我發現通過將密碼設置成access_token,居然就成功了!