Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何保护我加载的插件?_C_Security_Plugins_Shared Libraries - Fatal编程技术网

C 如何保护我加载的插件?

C 如何保护我加载的插件?,c,security,plugins,shared-libraries,C,Security,Plugins,Shared Libraries,假设我的一段代码扫描目录/plugins并加载.dlls/。因此s带有一个已知的符号(“此处的函数”),以扩展其功能性,如下所示: main.c #include <stdlib.h> #include <dirent.h> #include <string.h> #include <stdio.h> #include <dlfcn.h> int main(void) { DIR *dir; struct dirent

假设我的一段代码扫描目录
/plugins
并加载
.dll
s/
。因此
s带有一个已知的符号(“此处的函数”),以扩展其功能性,如下所示:

main.c

#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include <dlfcn.h>

int
main(void)
{
    DIR *dir;
    struct dirent *entry;
    dir = opendir("./plugins");
    if (dir == NULL)
        return -1;
    while ((entry = readdir(dir)) != NULL)
    {
        void *handle;
        char path[PATH_MAX];
        int (*function)(char *);
        if (strstr(entry->d_name, ".so") == NULL)
            continue;
        if (snprintf(path, sizeof(path), "./%s", entry->d_name) >= sizeof(path))
            continue;
        handle = dlopen(path, RTLD_LAZY);
        if (handle == NULL)
            continue; // Better: report the error with `dlerror()'
        function = (int (*)(char *)) dlsym(handle, "function");
        if (function != NULL)
            fprintf(stdout, "function: %d\n", function("example"));
        else
            fprintf(stderr, "symbol-not-found: %s\n", entry->d_name);
        dlclose(handle);
    }
    closedir(dir);
    return 0;
}
#包括
#包括
#包括
#包括
#包括
int
主(空)
{
DIR*DIR;
结构方向*条目;
dir=opendir(“./插件”);
if(dir==NULL)
返回-1;
while((entry=readdir(dir))!=NULL)
{
无效*手柄;
字符路径[path_MAX];
int(*函数)(字符*);
if(strstr(entry->d_name,“.so”)==NULL)
继续;
如果(snprintf(path,sizeof(path),“/%s”,entry->d_name)>=sizeof(path))
继续;
handle=dlopen(路径,RTLD_-LAZY);
if(handle==NULL)
继续;//更好:使用'dlerror()'报告错误
函数=(int(*)(char*)dlsym(句柄,“函数”);
if(函数!=NULL)
fprintf(标准输出,“函数:%d\n”,函数(“示例”);
其他的
fprintf(标准,“未找到符号:%s\n”,条目->数据单元名称);
dlclose(手柄);
}
closedir(dir);
返回0;
}
这可能会导致一个重大的安全问题:如果我的应用程序以root用户身份运行,或者具有管理员权限,这意味着任何未经授权的攻击者都可以通过生成一个包含名为已知符号的函数(此处为
函数
)的共享对象,以特权用户身份执行代码

如何保护我的
插件
文件夹?如何检查我加载的共享对象是否安全?


这是对的后续操作。

我相信在一般情况下您无法保护插件。恶意用户可以在其插件中执行任意操作(包括在运行时发出一些C代码,然后对其进行编译和
dlopen
-ing,在内存中JIT编译机器代码等等)。请记住,
dlopen
-ed(或
mmap
-ed)插件正在共享运行其加载程序的功能

编译器的Meta插件是这样做的:在运行时生成C++或C++代码,即时编译它,<代码> DLOpen<代码>。但这并不是恶意的

请注意,(as)正在运行任意初始化插件代码(在您执行任何
dlsym
从其
“函数”
名称检索函数之前)。了解

如果你非常雄心勃勃(多年的工作,值得一个博士…),你可能会生成插件的代码,同时做一些代码验证或声音

(因为你和我一样在法国巴黎附近,所以请查看Xavier Leroy-INRIA的作品,例如,Emmanuel Chailloux-LIP6-,Julia Lavall&-LIP6-;也可以阅读关于&;但要了解,;你可以给我发一封电子邮件,提及你问题的URL)

另请阅读有关的信息您的请求是或至少是

你可以考虑一些对偶方法:有一个可信的过程来“签名”或“戳”好插件(因此,系统管理员负责告诉这样和那样的插件是好的),并且只有代码> DLOPEN/CODE >一个插件,当它被“认证”或简单地“人类认可”的时候。可能只需在可信插件名称及其md5签名之间保持一个(可信且安全的)数据库或文本关联,然后计算校验和,然后在

dlopen
之前进行检查即可


当编程时,一个很好的启发是经常问自己:我是在试图解决停顿问题吗?有着有趣的见解……

我相信在一般情况下你无法保护你的插件。恶意用户可以在其插件中执行任意操作(包括在运行时发出一些C代码,然后对其进行编译和
dlopen
-ing,在内存中JIT编译机器代码等等)。请记住,
dlopen
-ed(或
mmap
-ed)插件正在共享运行其加载程序的功能

编译器的Meta插件是这样做的:在运行时生成C++或C++代码,即时编译它,<代码> DLOpen<代码>。但这并不是恶意的

请注意,(as)正在运行任意初始化插件代码(在您执行任何
dlsym
从其
“函数”
名称检索函数之前)。了解

如果你非常雄心勃勃(多年的工作,值得一个博士…),你可能会生成插件的代码,同时做一些代码验证或声音

(因为你和我一样在法国巴黎附近,所以请查看Xavier Leroy-INRIA的作品,例如,Emmanuel Chailloux-LIP6-,Julia Lavall&-LIP6-;也可以阅读关于&;但要了解,;你可以给我发一封电子邮件,提及你问题的URL)

另请阅读有关的信息您的请求是或至少是

你可以考虑一些对偶方法:有一个可信的过程来“签名”或“戳”好插件(因此,系统管理员负责告诉这样和那样的插件是好的),并且只有代码> DLOPEN/CODE >一个插件,当它被“认证”或简单地“人类认可”的时候。可能只需在可信插件名称及其md5签名之间保持一个(可信且安全的)数据库或文本关联,然后计算校验和,然后在

dlopen
之前进行检查即可


当编程时,一个很好的启发是经常问自己:我是在试图解决停顿问题吗?有有趣的见解……

在这种情况下,您唯一能做的就是只允许特权用户在插件目录中写入文件

对已丢失的未知文件调用
dlopen
。请注意,您甚至不需要从中调用函数,对
dlopen
的调用就足够了,因为共享对象可以具有将自动运行的构造函数