Josix is Only Joking

Chroot 指令與 SSH 設置 ChrootDirectory

August 04, 2020

chroot 是什麼

chroot 是一個限於 superuser 執行的 UNIX 指令,即代表 change root directory ,主要用途為使用提供的目錄作為根目錄來執行指令或開啟可互動的 shell。使用 chroot 後,離開該根目錄的檔案都將無法進行存取。

chroot 使用語法如下:

chroot [OPTION] NEWROOT [COMMAND [ARG]...]
chroot OPTION 
(Note. 如果沒有給定指令,則執行 `${SHELL} -i`)

OPTION:
    --groups=G_LIST 
    以 g1,g2,..,gN 格式提供附加的群組 

    --userspec=USER:GROUP
    給定使用者和群組 (ID 或名稱) 使用該環境

    --skip-chdir
    不要更換工作目錄至 '/'
    Note. 只有當 NEWROOT 為 "/" 才允許,因此較常搭配 --groups, --userspec 使用

    --help
    輸出使用說明

    --version
    輸出版本號

chroot 常被用於下列情境:

  • 建立開發、測試環境:使用 chroot 建立的環境中測試軟體,避免直接部署到完整的生產環境當中。
  • 修復系統:當一系統故障時,可以透過 chroot 在其他目錄開啟系統,最後再回到故障系統中進行修復。
  • 相依性控制:不同軟體可能產生的相依性可以透過 chroot 建立的不同根目錄環境來進行分隔。
  • 權限分離:將特定使用者允許存取的檔案放入 chroot 的目錄當中,當使用者使用 ssh 登入後限制其所能存取的環境僅限於該 chroot 的目錄下。

執行 chroot

在執行 chroot 之前,首先要確定該 chroot 所需執行到的指令已經放入該新的根目錄下。 以下假設 chroot 後要使用到 /bin/bash, /usr/bin/rsync,先手動建置該檔案:

Note. 除了所需的程式外基本的 /dev 節點設置,也都需要透過 mknode 建立

  1. 複製原系統的檔案位置 (/bin/bash) 至 CHROOT 對應的目錄位置下 ($CHROOT/bin/bash)
cp /bin/bash $CHROOT/bin
cp /usr/bin/rsync $CHROOT/usr/bin
  1. 複製指令使用到的 shared object。可以使用 ldd 來找到所需要複製的檔案(也就是相依的 shared object)。
ldd /bin/bash
#	linux-vdso.so.1 (0x00007ffee39e4000)
#	libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f7722ca5000)
#	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f7722aa1000)
#	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f77226b0000)
#	/lib64/ld-linux-x86-64.so.2 (0x00007f77231e9000)

需要複製這些檔案到 CHROOT 對應的目錄下 (例如 /lib/x86_64-linux-gnu/libtinfo.so.5 需要複製到 $CHROOT/lib/x86_64-linux-gnu) 相同的步驟也需要對 /usr/bin/rsync 做一遍。

Note. 上述複製的檔案與目錄需確認權限是 root

  1. 準備好所需執行的指令後,便可以使用 chroot 了,並且只能夠執行先前提供的指令。
chroot $CHROOT
# or
chroot $CHROOT /bin/bash

小結

在現在容器盛行的情況下,使用 chroot 來進行測試、開發及相依性維護已經較不大需要,更多時候會是在維護、修復系統、開設 guset 帳戶時使用。另外,使用 chroot 並非完全安全的,需要特別移除會使用到 setuid 的程式、編譯器等任何可能在 chroot 後又獲得 root 權限逃離 chroot jail 的漏洞。

ChrootDirectory 用途及使用情境

除了於登入後使用 chroot 指令可以執行更換根目錄,也可以在登入過程中使用 chroot

ChrootDirectory 是在 sshd_config (OpenSSH SSH daemon configuration) 可以設定的一個關鍵字,通常搭配 Match 來使用,針對 Match 到的使用者參考 ChrootDirectory 後帶的參數(NEWROOT 位置)執行 chroot,主要目的為針對特定的使用者,讓其登入後所能存取的檔案及指令皆限制在 chroot 的根目錄下。

設置 ChrootDirectory 限制特定使用者存取目錄

下面例子將從零開始創建一個 Chroot SFTP 使用者帳號(參考這篇文章):

  1. 新增一個使用者及群組
groupadd sftpusers
useradd -g sftpusers -d /incoming -s /sbin/nologin $USERNAME
passwd $USERNAME

groupadd sftpusers: 新增 sftpusers 這個 group

useradd -g sftpusers -d /incoming -s /sbin/nologin $USERNAME: 新增名稱為 $USERNAME 的使用者,並設置其群組為 sftpusers、家目錄為 /incoming 並用無法登入的 Shell 作為這個帳號的 Shell

passwd $USERNAME: 設置該帳號的密碼

  1. 設置該使用者 chroot jail
mkdir -p /sftp/$USERNAME/incoming
chown $USERNAME:sftpusers /sftp/$USERNAME/incoming

mkdir -p /sftp/$USERNAME/incoming: 先建立該帳戶登入後會進入的目錄

chown $USERNAME:sftpusers /sftp/$USERNAME/incoming: 修改該目錄權限供該帳戶使用

Note. /sftp/$USERNAME/ 目錄下除了使用者可存取的位置外,都需要為 root 權限

  1. 修改 /etc/ssh/sshd_config
vim /etc/ssh/sshd_config
  1. 使用 openssh 提供之 sftp 服務
#Subsystem      sftp    /usr/libexec/openssh/sftp-server
Subsystem       sftp    internal-sftp

internal-sftp 是 openssh 提供的關鍵字用於辨認使用 sshd 內部的 sftp 服務

關於 sftp-server 與 internal-sftp 的差別,參照這裏

  1. 設置 ChrootDirectory
Match Group sftpusers
    ChrootDirectory /sftp/%u
    ForceCommand internal-sftp

Match Group sftpusers: 選取符合群組為 sftpusers 的使用者

ChrootDirectory /sftp/%u: 設置更換根目錄到 /sftp/%u%u會被代換為該使用者名稱

ForceCommand internal-sftp: 強制使用執行 internal-sftp 指令忽略其他定義在 .ssh/rc 的指令

  1. 重啟 sshd
service sshd restart

其他 chroot 環境設定

  • 若有使用外部目錄的需要,需要透過 Bind Mount 到新根目錄下的任意位置,作法如下:
  1. 修改 /etc/fstab(假設外部目錄為 /var/www/html)
vim /etc/fstab
# Add
# /var/www/html   $CHROOT/mounted_folder        none    bind    0 0
  1. 將該外部目錄掛載到指定位置下
mkdir $CHROOT/mounted_folder
mount $CHROOT/mounted_folder

參考資料


Hi, I'm Josix 興趣是沒事把玩各式各樣的 FOSS ,喜愛專研技術、參與社群交流,有著各種天馬行空的 Idea 想去實現

Josix Wang © 2021