2011-06-02 35 views
4

即使在seteuid之後,root priv也不能放入python中。一個錯誤?即使在seteuid之後,root priv也不能放入python中。一個錯誤?

編輯摘要:我忘了放棄gid。雖然,接受的答案可能會對你有所幫助。

嗨。我無法在我的linux上刪除python 3.2的root權限。實際上,即使在seteuid(1000)之後,它也可以讀取根擁有的400模式文件。 euid肯定設置爲1000!

我在空os.fork()調用後發現,特權訪問被正確拒絕。 (但它只在父類中,孩子仍然可以非法讀取。)它是python中的bug還是linux?

請試試下面的代碼。在底部註釋掉三行中的一行,並以root身份運行。

預先感謝。

#!/usr/bin/python3 

# Python seteuid pitfall example. 
# Run this __as__ the root. 

# Here, access to root-owned files /etc/sudoers and /etc/group- are tried. 
# Simple access to them *succeeds* even after seteuid(1000) which should fail. 

# Three functions, stillRoot(), forkCase() and workAround() are defined. 
# The first two seem wrong. In the last one, access fails, as desired. 


# ***Comment out*** one of three lines at the bottom before execution. 

# If your python is < 3.2, comment out the entire def of forkCase() 

import os 

def stillRoot(): 
    """Open succeeds, but it should fail.""" 
    os.seteuid(1000) 
    open('/etc/sudoers').close() 

def forkCase(): 
    """Child can still open it. Wow.""" 
    # setresuid needs python 3.2 
    os.setresuid(1000, 1000, 0) 
    pid = os.fork() 
    if pid == 0: 
     # They're surely 1000, not 0! 
     print('uid: ', os.getuid(), 'euid: ', os.geteuid()) 
     open('/etc/sudoers').close() 
     print('open succeeded in child.') 
     exit() 
    else: 
     print('child pid: ', pid) 
     open('/etc/group-').close() 
     print('parent succeeded to open.') 

def workAround(): 
    """So, a dummy fork after seteuid is necessary?""" 
    os.seteuid(1000) 
    pid = os.fork() 
    if pid == 0: 
     exit(0) 
    else: 
     os.wait() 

    open('/etc/group-').close() 

## Run one of them. 

# stillRoot() 
# forkCase() 
# workAround() 

回答

6

在Unix系統上操作進程憑證非常棘手。 I 高度建議您深入瞭解Real,Effective和Saved-Set用戶ID如何相互關聯。搞砸「特權」很容易。

至於你的具體觀察......我想知道是否有一個簡單的原因,你可能忽略了。您的代碼正在執行不一致的測試,並且您忽略了在/etc/sudoers/etc/group-文件中指定確切的文件權限。如果/etc/sudoers擁有權限mode = 440,uid = root,gid = root(這是我係統上的默認權限)並且/etc/group-的mode = 400,那麼您的預期行爲可能與您描述的完全相同。

如果/etc/sudoers是組可讀的,那麼您不會修改該進程的GID,這可以解釋爲什麼它始終可讀。 fork()不會修改流程憑證。但是,它可能會出現在您的示例代碼中,因爲您正在檢查父代和子代中的不同文件。如果/etc/group-沒有組的組讀取權限,那將解釋明顯的問題。

如果你正在試圖做的一切都是「滴特權」,使用下面的代碼:

os.setgid(NEW_GID) 
os.setuid(NEW_UID) 

一般來說,你只需要操縱的有效用戶ID,如果你的程序需要切換它在進程的整個生命週期內都是根權限。如果您只需要使用root權限執行一些設置操作,但在完成這些設置操作後不再需要這些設置操作,只需使用上面的代碼不可撤銷地刪除它們即可。

呵呵,在Linux上進行過程憑證操作的一個有用的調試工具是打印/proc/self/status的輸出,該文件的Uid和Gid行顯示當前持有的真實,有效,保存集和文件ID過程(按此順序)。 Python API可用於檢索相同的信息,但您可以將此文件的內容視爲「真實數據」,並避免Python跨平臺API的任何潛在複雜情況。

+1

糟糕,這正是gid問題。愚蠢的我。 非常感謝Rakis,他們都指出了我的錯誤和詳細的解釋。 – 2011-06-03 08:35:44

相關問題