如何编译C文件但限制库的使用?

如何编译C文件但限制库的使用?,c,unix,gcc,compilation,C,Unix,Gcc,Compilation,我正在使用unix服务器 我从我的客户机那里得到一个c文件作为输入,我编译了它 c文件应该非常基本,并且只包含来自stdio、stdlib、math和string的函数 GCC编译器中是否有任何标志不允许使用任何其他库,并且在使用其他库时会抛出编译错误 如果有一个解决方案不涉及GCC,它可能也很好,但我不想检查该文件 谢谢。将选项-nodefaultlibs或-nostlib传递给gcc,以及仅包括允许的库的选项(如数学库的-lm)。有关这些选项的详细信息,请查看 -nodefaultlibs

我正在使用unix服务器

我从我的客户机那里得到一个c文件作为输入,我编译了它

c文件应该非常基本,并且只包含来自stdio、stdlib、math和string的函数

GCC编译器中是否有任何标志不允许使用任何其他库,并且在使用其他库时会抛出编译错误

如果有一个解决方案不涉及GCC,它可能也很好,但我不想检查该文件


谢谢。

将选项
-nodefaultlibs
-nostlib
传递给gcc,以及仅包括允许的库的选项(如数学库的
-lm
)。有关这些选项的详细信息,请查看

-nodefaultlibs

链接时不要使用标准系统库。只有 您指定的库将传递给链接器


将选项
-nodefaultlibs
-nostlib
传递给gcc,以及仅包括允许的库的选项(如数学库的
-lm
)。有关这些选项的详细信息,请查看

-nodefaultlibs

链接时不要使用标准系统库。只有 您指定的库将传递给链接器

限制库(编译时的头文件和链接时的库链接)并不能阻止不受信任的代码直接调用危险的(与安全相关的)内核系统调用。这可以通过不受信任的代码来实现,例如使用内联汇编或外壳代码/漏洞利用技术,例如故意覆盖堆栈上的返回地址以指向包含外壳代码的字符串

话虽如此,您可以使用
-nostlib-nodefaultlibs
链接器选项来防止链接到库。但是,这仍然只允许您拥有整个libc,或者不拥有任何libc。您不能有选择地仅链接到libc的一部分(例如,have
printf()
,而不是
system()

只允许某些include也不是很有效:代码可以从include文件复制声明,而不包括某些头,以绕过只允许特定的
#include
语句的限制。例如:

int system(const char *);
int main() {
    return system("uname -a");
}
如果必须确保安全,您可能应该在运行时对代码进行沙箱处理,而不是试图阻止编译不安全的代码。

限制库(编译时的头包括库,链接时的库链接)不会阻止不受信任的代码直接调用危险代码(如与安全相关的代码)内核系统调用。这可以通过不受信任的代码来实现,例如使用内联汇编或外壳代码/漏洞利用技术,例如故意覆盖堆栈上的返回地址以指向包含外壳代码的字符串

话虽如此,您可以使用
-nostlib-nodefaultlibs
链接器选项来防止链接到库。但是,这仍然只允许您拥有整个libc,或者不拥有任何libc。您不能有选择地仅链接到libc的一部分(例如,have
printf()
,而不是
system()

只允许某些include也不是很有效:代码可以从include文件复制声明,而不包括某些头,以绕过只允许特定的
#include
语句的限制。例如:

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

如果必须确保安全,您可能应该在运行时对代码进行沙箱处理,而不是试图阻止编译不安全的代码。

为了说明允许包含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;
}
#包括
int main(){
系统(`whichpython`-c\'print'helloword'\”);
//我不需要简单地打印hello world,而是可以打开一个套接字返回到
//攻击者的机器并开始读取二进制代码并执行它。
返回0;
}

为了说明允许包含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;
}
#包括
int main(){
系统(`whichpython`-c\'print'helloword'\”);
//我不需要简单地打印hello world,而是可以打开一个套接字返回到
//攻击者的机器并开始读取二进制代码并执行它。
返回0;
}

为什么不对文件进行预处理,拒绝任何包含include语句的文件,然后添加四个允许的include语句。你所做的听起来非常不安全。@Dunes-我知道这是不安全的,这就是为什么我想把客户限制在那些图书馆里。你想实现什么?是否要验证预处理器仅包含某些头文件
-MD
标志到gcc将为您提供相关的头,您可以验证只有允许的头存在。还是要验证编译的对象仅与libc和libm链接?您可以从目标文件中提取未定义的符号(
nm
objdump
,“U”符号),并验证它们是否都在libc.so或libm.so或其静态等效文件中找到。但您允许包含具有系统功能的stdlib.h。利用系统功能和一点创造力,攻击者可以在您的计算机上运行任意代码。您的客户端是否确实是学生提交作业?为什么不预处理该文件,拒绝包含语句的任何文件,然后添加四个允许的包含。你所做的听起来非常不安全。@Dunes-我知道这是不安全的,这就是为什么我想把客户限制在那些图书馆里。你想实现什么?是否要验证预处理器仅包含某些头文件
-MD
标志到gcc将为您提供相关的标题,您可以验证