0x00 前言
OSS滲透目前最常見的方式就是得到Secret Key,那么如果Secret Key并沒有被泄露難道就不可以被利用了嗎?答案是否定的。
自筆者上篇文章末尾的“全域名”泛濫后,筆者來給大家通過官方給出的API代碼分析的方式分析一下Secret Key的復用問題,因為在這里,某里云官方給的demo同樣是存在此問題的。
0x01 環境布局
在這里,筆者準備了一個購買了ECS的賬號來跟大家進行演示。這個賬號的資產為:
一臺ECS
兩臺OSS
0x02 常見姿勢總結
在真正的實戰中,遇到我們喜愛的上傳點時,我們會發現類似于如下HTTP請求:
當Options請求完畢后會發現一個上傳包,并且攜帶了key:
那么此時已經可以確定為OSS上傳點。
針對于類似于這種的包,我們會第一時間去翻看網站所引入的所有JavaScript外聯,去查看是否在前端泄露了Secret Key。
在這里筆者先給大家簡單的敘述一下查找到Secret Key意味著什么。
Access Key可以看作是阿里云的另一種賬戶密碼。
OSS,ECS等等是阿里云賬戶下的產品,
當這個賬戶下有OSS產品,我們就可以用accesskey訪問這個oss,
如果這個賬戶下有ECS,我們就能通過這個accesskey去操控ecs,執行命令。
在這里為了方便演示,我們首先將兩臺服務器設置跨域請求:
然后創建規則:
下面筆者創建一個實戰模擬代碼
源代碼來自:https://files.cnblogs.com/files/ossteam/oss-h5-upload-js-direct.tar.gz
參考:https://www.cnblogs.com/ossteam/p/4942227.html
情況一:Secret Key 泄露
使用F12進行搜索Secret Key:
這是實戰中一個典型的Secret Key泄露,也是能讓大家眼前一亮的信息,那么我們下一步應該怎么做呢?
使用 oss-browser 來進行管理 oss 服務器
下載地址:http://gosspublic.alicdn.com/oss-browser/1.9.4/oss-browser-win32-x64.zip
在這里我們只需要將阿里云的AccessKeyId與AccessKeySecret填入就可以了。
這里我們就可以對這兩臺OSS服務器進行增刪改查操作。
使用行云管家進行重置ECS密碼信息
當然如果只可以管理兩臺靜態服務器,那么這點權限也太小了,我們可以通過行云管家來進行管理ECS。
登陸行云管家:https://yun.cloudbility.com/
填入Access Key ID 與 Access Key Secret 即可接管ECS服務器。
導入成功后這里可以重置系統密碼。
重置后ssh登錄:
登錄成功,但是顯然這種非常大的動靜并不是我們想要的。那么我們則需要使用OpenApi來實現命令執行。
使用OpenApi來進行命令執行
在OpenApi官網:https://api.aliyun.com/中,存在 CreateCommand 與 InvokeCommand Api,我們可以借用這兩個來實現命令執行。
參考文章:https://www.cnblogs.com/J0ng/p/13210147.html
只不過這些步驟太麻煩了,不如編寫為POC來進行本地調用。
下面是筆者做好的POC:
#!/usr/bin/env python
#coding=utf-8
import?json, base64
from?aliyunsdkcore.client import?AcsClient
from?aliyunsdkcore.acs_exception.exceptions import?ClientException
from?aliyunsdkcore.acs_exception.exceptions import?ServerException
from?aliyunsdkecs.request.v20140526.CreateCommandRequest import?CreateCommandRequest
from?aliyunsdkecs.request.v20140526.InvokeCommandRequest import?InvokeCommandRequest
ID?= ”?# Access Id
KEY?= ”?# Access Key
reGon?= ”?? ? ? ? ? ?# 地區
InstanceId?= [“”] # 實例ID
CmdBytes?= b”’ls /
”’# 要執行的命令
Cmd?= base64.b64encode(CmdBytes).decode(‘utf-8′)
CmdType?= “RunShellScript”
# RunBatScript:創建一個在Windows實例中運行的 Bat 腳本。
# RunPowerShellScript:創建一個在Windows實例中運行的PowerShell腳本。
# RunShellScript:創建一個在Linux實例中運行的Shell腳本。
client?= AcsClient(ID, KEY, reGon)
request?= CreateCommandRequest()
request.set_accept_format(‘json’)
request.set_Name(“123123″)
request.set_Type(“RunShellScript”)
request.set_CommandContent(Cmd)
response?= client.do_action_with_exception(request)
print(str(response, encoding=’utf-8′))
request2?= InvokeCommandRequest()
request2.set_accept_format(‘json’)
request2.set_CommandId((json.loads(response))[‘CommandId’])
request2.set_InstanceIds(InstanceId)
response?= client.do_action_with_exception(request2)
print(str(response, encoding=’utf-8′))
只需要簡單配置一下就可以了,配置如圖:
配置好之后進行執行:
可以從云管理這邊看到所執行的命令。
PS: 如果使用POC的方式注意安裝Python庫:
pip3 install aliyun-python-sdk-core-v3
pip3 install aliyun-python-sdk-cdn
pip3 install aliyun-python-sdk-ecs
情況二:Secret Key 沒有泄露
毫無卵用的XSS
既然OSS可以上傳任意mime類型,那么我們可以直接上傳text/html來進行XSS操作,如圖:
參考文章:http://pirogue.org/2017/09/29/aliyunoss/
不知為何,筆者這里復現失敗,就不去嘗試了。
根據上傳點的回顯來構造XSS
這也是筆者看到的另一種場景,也就是說,當你上傳“1.jpg<script>alert(1)</script>”之后,隨后輸出在頁面上,從而導致XSS,筆者這里也不進行復現了。
參考文章:https://www.freebuf.com/vuls/288206.html
0x03 無需SecretKey的利用方法
好了,總結以上需要SecretKey的攻擊手法后,我們再來看一下筆者今天想要說的“無需SecretKey”的利用方式。
根據以上種種案例跡象表明,只有當我們拿到SecretKey后才可以進行更危險的操作。
但是我們根據官方提供的PHP上傳API來探究,事情到底是不是得有SecretKey才可以進行利用。
開發人員對待OSS的三種情況:
通過JavaScript直接進行上傳
繪圖如下:
當然這種方式是最危險的,在前面也講過利用方式了。
通過Json輪詢的方式來進行直接上傳
這種方式是筆者見過開發者最多的一種方式,也是某云推薦的使用方式,咱們先看一下例圖再進行挖掘它其中的問題。
通過服務器單條線路直接上傳
這種方式也是最安全的方式了,大致如下:
在前面的圖中我們也看到了,輪詢的方式也是一種比較推薦的方式哈,只不過,這個服務器返回給我們的“密鑰”到底是什么,我們還真不清楚。
分析問題
那么我們查看官方文檔:
那么筆者下載下來之后進行分析源代碼:
我們可以看到,ID字段未經任何處理就拼接到了返回包中,signature存放了“密鑰能存活多久”的key以及AccessSecretKey,將它們進行sha1加密,可以發現,host確確實實的是一動不動的,該密鑰與Host沒有一點關系。
那么我們可以猜想:這條密鑰就是為了短暫的使用一下AccessKey,過期不候。
那么如果一個人有多臺OSS呢?這條密鑰是否可以復用。
那么我們捕獲該php文件的返回結果,我們觀察一下policy的base64解碼值,如圖:
policy值:
JTdCJTIyZXhwaXJhdGlvbiUyMiUzQSUyMjUxOTAtMDktMjNUMjAlM0ExNyUzQTI0LjAwMFolMjIlMkMlMjJjb25kaXRpb25zJTIyJTNBJTVCJTVCJTIyY29udGVudC1sZW5ndGgtcmFuZ2UlMjIlMkMwJTJDMTA0ODU3NjAwMCU1RCUyQyU1QiUyMnN0YXJ0cy13aXRoJTIyJTJDJTIyJTI0a2V5JTIyJTJDJTIydXNlci1kaXItcHJlZml4JTVDLyUyMiU1RCU1RCU3RA==
Base解密:
那么我們使用它們對tester1服務器進行文件上傳操作:
可以看到,成功上傳,那么我們將目標改為tester2,看返回結果:
可以看到,同一份密鑰是可以上傳多個服務器的。
利用場景
根據筆者所發布的《記一次授權導致的全域名淪陷》:https://www.freebuf.com/vuls/303620.html,例圖可以為:
簡單的過濾繞過:
如果手上已經持有了密鑰,通過這次實驗,則可以向該KeyId使用者的任意OSS服務器上傳任意文件,只不過這里還有一點,有些上傳點是必須要指明目錄的,例如:
則key只能為Temp下的,但是我們可以生成帶有../的文件名,如圖:
這樣依然可以生成憑據,從而進行任意目錄上傳。
來源:FREEBUF