限制Linux应用程序的系统调用访问
假设一个Linux二进制限制Linux应用程序的系统调用访问,linux,security,linux-kernel,hook,system-calls,Linux,Security,Linux Kernel,Hook,System Calls,假设一个Linux二进制foobar,它有两种不同的操作模式: 模式A:一种性能良好的模式,其中使用系统调用A、b和c 模式B:一种出错模式,其中使用系统调用A、B、c和d 系统调用a、b和c是无害的,而系统调用d是潜在的危险,可能会导致机器不稳定 进一步假设应用程序运行的两种模式中的哪一种是随机的:应用程序以95%的概率在模式A中运行,以5%的概率在模式B中运行。应用程序没有源代码,因此无法修改,只能按原样运行 我想确保应用程序不能执行syscalld。执行syscalld时,结果应该是N
foobar
,它有两种不同的操作模式:
- 模式A:一种性能良好的模式,其中使用系统调用
、A
和b
c
- 模式B:一种出错模式,其中使用系统调用
、A
、B
和c
d
a
、b
和c
是无害的,而系统调用d
是潜在的危险,可能会导致机器不稳定
进一步假设应用程序运行的两种模式中的哪一种是随机的:应用程序以95%的概率在模式A中运行,以5%的概率在模式B中运行。应用程序没有源代码,因此无法修改,只能按原样运行
我想确保应用程序不能执行syscalld
。执行syscalld
时,结果应该是NOOP或立即终止应用程序
如何在Linux环境中实现这一点?这是一种可能的应用程序(特别是基于规则的执行)。一种流行的实现是
您必须确保与您希望允许流程执行的操作相对应。应用程序是否静态链接 如果没有,您可以覆盖某些符号,例如,让我们重新定义
套接字
:
int socket(int domain, int type, int protocol)
{
write(1,"Error\n",6);
return -1;
}
然后构建一个共享库:
gcc -fPIC -shared test.c -o libtest.so
让我们跑吧:
nc -l -p 6000
嗯
现在:
$ LD_PRELOAD=./libtest.so nc -l -p 6000
Error
Can't get socket
使用变量LD_PRELOAD=./libtest.so
运行时会发生什么?它使用libtest中定义的符号进行重写。因此,在C库中定义的符号之上。这似乎正是您所需要的。从:
应用程序只允许进行策略中指定的系统调用。如果应用程序试图执行未明确允许的系统调用,则会发出警报
这正是为什么。请参阅。如果您的问题中存在误解,您能否澄清一下“概率”的含义?帕斯卡:当然!用澄清后编辑。对于这个问题,“模式选择”是随机的。这当然是SELinux的用例。其他沙箱技术也可用。@stband我将您的评论合并到了一起。您可能对上一版本中的“声明”做出了部分反应……我这样说是因为听到一些人说SELinux在实践中不太实用,正是因为需要适当的政策。没有尝试过,我没有任何意见,所以从这个角度来看,新版本可能更好。这实际上不符合安全要求吗?很容易让代码在
eax
或任何CPU约定中加载适当的系统调用号,然后将控制权转移到“a”、“b”或“c”系统调用的末尾。更改每个进程的系统调用表和加载程序更改(如SELinux)是阻止用户空间损坏的唯一方法。例如,见。至少这个答案假设系统中有几件事情是无法妥协的。