2012-04-21 35 views
1

我正在使用unix服務器。如何編譯C文件但限制庫的使用?

我得到一個c文件作爲我的客戶端,我編譯的輸入。

c文件應該是非常基本的,並且只包含來自stdio,stdlib,數學,字符串的函數。

GCC編譯器中是否有任何標誌不允許使用任何其他庫,並在使用其他庫時會拋出編譯錯誤?

如果有一個不涉及GCC的解決方案,它可能也不錯,但我不想檢查該文件。

謝謝。

+4

爲什麼不預處理文件,用include語句拒絕任何文件,然後添加四個允許的包含。你所做的事聽起來很不安全,但。 – Dunes 2012-04-21 19:50:37

+0

@Dunes - 我知道那是不安全的,這就是爲什麼我想限制客戶端到那些庫 – RanZilber 2012-04-21 19:53:32

+0

你想實現什麼?你想驗證預處理器只包含某些頭文件嗎? '-MD'標誌gcc會給你相關的標題,你可以驗證只有允許的標題在那裏。還是你想驗證編譯的對象只與libc和libm鏈接?您可以從目標文件('nm'或'objdump','U'符號)中提取未定義的符號,並驗證它們是否都在libc.so或libm.so中或它們的靜態等價物中找到。 – 2012-04-21 19:57:51

回答

1

將選項-nodefaultlibs-nostdlib傳遞給gcc,以及僅包含允許的庫(如數學庫的-lm)的選項。有關這些選項的更多信息,請查閱gcc manual

-nodefaultlibs
鏈接時不要使用標準系統庫。只有您指定的 庫將傳遞給鏈接器。

+0

+1我認爲這是做到這一點的正確方法。 – dirtybit 2012-04-21 20:04:53

6

限制庫(包括編譯時的頭文件和鏈接時的庫鏈接)不會阻止不可信的代碼直接調用危險的(如安全相關的)內核系統調用。這可以通過不可信代碼來完成,例如通過使用內聯彙編或shellcode/exploit技術,例如通過故意覆蓋堆棧上的返回地址來指向包含shellcode的字符串。

話雖如此,您可以使用-nostdlib -nodefaultlibs鏈接器選項來防止鏈接到庫。但是,這仍然只允許你擁有整個libc,或者不是。你不能有選擇地鏈接到libc的一部分(比如說,有printf()但不是system())。

只允許某些包含並不是非常有效:代碼可以從包含文件中複製聲明,而不是包含某些頭文件來解決限制,只允許特定的#include語句。例如:

int system(const char *); 
int main() { 
    return system("uname -a"); 
} 

如果它是安全的,你應該考慮在運行時沙盒的代碼,而不是試圖阻止不安全的代碼進行編譯。

+1

如果目標是對沙盒編譯代碼進行編譯,使用'-nostdlib'或'-nodefaultlibs'限制庫不會有幫助:用戶可以直接編寫內聯彙編,直接執行系統調用,而無需使用任何標準庫。運行時沙盒真的是唯一的出路。 – davidg 2012-04-22 02:20:46

1

只是爲了說明允許包含stdlib.h的不安全性,我會寫一個可以在您的機器上運行任意代碼的小程序。

#include <stdlib.h> 

int main() { 
    system("`which python` -c \"print 'hello word'\""); 
    // instead of simply printing hello world i could open a socket back to the 
    // attacker's machine and start reading in abitrary code and executing it. 
    return 0; 
}