[程式碼修訂版] Python 踩坑之旅 [程式篇其四] 踩透 uid euid suid gid egid sgid的坑坑窪窪

mythmgn發表於2019-06-06
程式碼示例支援
平臺: Centos 6.3
Python: 2.7.14
程式碼示例: 公眾號點選 踩坑之旅選單 或者 https://github.com/mythmgn/awesome_py_traps

1.1 踩坑案例

小明是個伺服器管理員, 他從老管理員手裡接手了一個非常繁瑣的運維工作: 短暫授權root 賬號給不同的 team 介面人執行備份任務

該運維任務有幾個特點:

  1. 任務需且僅需執行在 root 下
    • root 賬號只能短暫授權給各個小組
    • 通過賬號管理平臺, 提前申請一段時間的臨時密碼
    • 將臨時密碼提供給小組介面人
    • 時間超時後密碼自動變更
  2. 不同 team 分時使用, 無法併發使用

小明非常煩躁, 為了填上這個坑, 他調研了填坑解法.

1.2 填坑解法

填坑解法滿足:

  • 短時出借許可權
    • (在許可權範圍內)執行該任務時才能使用 root 許可權
    • 做完任務立即失去 root 許可權
  • 許可權範圍必須清晰
    • 能做什麼
      • 能做資料備份
    • 不能做什麼
      • 除了資料備份其他什麼都不在 root 許可權下做

具體做法:

  1. 利用c/c++程式出借部分 root 許可權 (完整程式碼關注公號點選選單檢視)

    • 該c程式限定執行的備份操作為 python 程式碼 euid_backup.py
    int main(int argc, char **argv){
        if(0==isRunUnderRoot()){
            fprintf(stderr,"does not run under +S attribute. Exiting....\n");
            return EXIT_FAILURE;
        }
        exit(runNewProcess("./", "env python ./euid_backup.py"));
    }
    • euid_backup.py owner 為 root, 非 root 使用者不準更改備份操作內容
  2. 為生成的執行檔案euid_cp及euid_backup.py 設定root許可權借用

    sudo rm -f ./euid_cp
    sudo gcc euid_cp.c -o euid_cp
    # 設定檔案owner為root, 非root使用者無法更改執行內容
    sudo chown root euid_cp euid_backup.py
    # 設定a. 非root只讀  b. 增加執行許可權
    sudo chmod 755 euid_cp
    # 設定stick bit, 執行euid_cp即可短暫獲取root 許可權, 執行任務
    sudo chmod +s euid_cp
  • euid_backup.py Python 程式碼執行具體的備份任務

    from __future__ import print_function
    import os
    import time
    
    print('euid is {0}'.format(os.geteuid()))
    
    if os.geteuid() == 0:
        print('start to copy under root')
        print('do some operations here')
        time.sleep(2)
        print('end copying things')
        print('drop privileges from root')
    else:
        print('non-root, euid {0} will exit'.format(os.geteuid()))

執行試驗:

  1. 通過 ./euid_cp 執行, 可以在非 root 下執行 root 許可權才能執行的備份任務(euid_backup.py)
    • 執行環境: Mac 10.14.4 (18E226)
    • [程式碼修訂版] Python 踩坑之旅 [程式篇其四] 踩透 uid euid suid gid egid sgid的坑坑窪窪
  2. 直接執行備份任務(euid_backup.py) 會失敗, 沒有許可權
    • 執行環境: 同上
    • [程式碼修訂版] Python 踩坑之旅 [程式篇其四] 踩透 uid euid suid gid egid sgid的坑坑窪窪

1.3 坑位分析

  1. uid / euid / suid 是什麼

    • uid 是使用者的 userid
      • 登陸後, 在不切換使用者情況下 uid 一般不變
    • euid 是使用者的有效 id
      • euid 在正常執行情況下一般等於uid
      • euid 一般決定了使用者對系統中儲存介質的access (訪問) 許可權
    • suid (saved uid) 是檔案在被訪問過程中的短暫切換使用者euid的屬性設定
      • 簡單來說, suid讓本沒有許可權的使用者可以短暫訪問這些資源
      • suid 在執行過程中進行了許可權切換
        • 執行之初, 切換到這個saved uid(文中為 root)
        • fork執行過程中, euid == suid
        • 執行完成後, euid 在切換回 uid
  2. gid, egid 等同理, [*]uid的判斷優先

1.4 技術關鍵字

  • uid euid suid
  • gid egid sgid

1.5 坑後思考

  1. 為什麼本文沒有直接對euid_backup.py檔案進行設定+s操作, 而是用可執行的c/c++程式做執行器

  2. Linux 系統裡的passwd 程式是否也是這個原理? 它跟哪些檔案/命令相關

下期坑位預告

程式篇其五之眼花繚亂的程式間通訊


Life is short. We use Python.

相關文章