在 Mac OS X 上编译不受库重定向影响的二进制文件
Compiling a binary immune to library redirection on Mac OS X
我注意到在 Mac OS X 上(目前我在 运行ning Yosemite,但我在早期版本的 OS X) 每当我使用 -static 选项调用 g++(甚至 gcc)时,二进制文件的链接失败——总是由于某个库或另一个库没有被成功找到。因此,我只能生成使用共享库的二进制文件。
这是个问题,因为我有一种情况,如果不编写使用 Setuid Root 权限安装的程序,我将无法解决。我需要编写的这个程序将检查环境变量以确保它们没有任何恶意(并且它会以安全而不是抱歉的态度这样做)然后它将它的用户 ID 降级为普通用户 before 使用 exec() 的形式调用另一个程序。
这些环境安全检查将确保 other 程序可以 运行 在保证关键环境变量(例如 DYLD_LIBRARY_PATH) 没有损坏。但是这个程序 本身 可以 不 运行 在任何这样的保证下 - 因为它是 执行的工作的一部分这个检查在第一个地方。
那么我该如何保护这个 C++ 程序免受这样的安全漏洞的影响呢?我的第一个想法是用 -static 选项编译它 --- 但由于这在 OS X 上不起作用,有没有人有 other想法?
谢谢。
编辑:只要可执行文件是 setuid,加载器就会杀死所有 DYLD_* 环境变量。来自 the source code for dyld.cpp:
// For security, setuid programs ignore DYLD_* environment variables.
// Additionally, the DYLD_* enviroment variables are removed
// from the environment, so that any child processes don't see them.
[原始答案:] 根据 this post by Sam Marshall,您可以通过向名为“__RESTRICT”的二进制 header 添加新部分来实现,其中一个部分名为“__restrict”。您可以通过将此添加到 "Other Linker Flags":
在 Xcode 中执行此操作
-Wl,-sectcreate,__RESTRICT,__restrict,/dev/null
忽略 DYLD_LIBRARY_PATH 的其他可能方法是将可执行文件设置为 setuid 或 setgid,或者使用授权进行签名。来自 the source code for dyld.cpp:
dyld::log("dyld: DYLD_ environment variables being ignored because ");
switch (sRestrictedReason) {
case restrictedNot:
break;
case restrictedBySetGUid:
dyld::log("main executable (%s) is setuid or setgid\n", sExecPath);
break;
case restrictedBySegment:
dyld::log("main executable (%s) has __RESTRICT/__restrict section\n", sExecPath);
break;
case restrictedByEntitlements:
dyld::log("main executable (%s) is code signed with entitlements\n", sExecPath);
break;
}
我注意到在 Mac OS X 上(目前我在 运行ning Yosemite,但我在早期版本的 OS X) 每当我使用 -static 选项调用 g++(甚至 gcc)时,二进制文件的链接失败——总是由于某个库或另一个库没有被成功找到。因此,我只能生成使用共享库的二进制文件。
这是个问题,因为我有一种情况,如果不编写使用 Setuid Root 权限安装的程序,我将无法解决。我需要编写的这个程序将检查环境变量以确保它们没有任何恶意(并且它会以安全而不是抱歉的态度这样做)然后它将它的用户 ID 降级为普通用户 before 使用 exec() 的形式调用另一个程序。
这些环境安全检查将确保 other 程序可以 运行 在保证关键环境变量(例如 DYLD_LIBRARY_PATH) 没有损坏。但是这个程序 本身 可以 不 运行 在任何这样的保证下 - 因为它是 执行的工作的一部分这个检查在第一个地方。
那么我该如何保护这个 C++ 程序免受这样的安全漏洞的影响呢?我的第一个想法是用 -static 选项编译它 --- 但由于这在 OS X 上不起作用,有没有人有 other想法?
谢谢。
编辑:只要可执行文件是 setuid,加载器就会杀死所有 DYLD_* 环境变量。来自 the source code for dyld.cpp:
// For security, setuid programs ignore DYLD_* environment variables.
// Additionally, the DYLD_* enviroment variables are removed
// from the environment, so that any child processes don't see them.
[原始答案:] 根据 this post by Sam Marshall,您可以通过向名为“__RESTRICT”的二进制 header 添加新部分来实现,其中一个部分名为“__restrict”。您可以通过将此添加到 "Other Linker Flags":
在 Xcode 中执行此操作-Wl,-sectcreate,__RESTRICT,__restrict,/dev/null
忽略 DYLD_LIBRARY_PATH 的其他可能方法是将可执行文件设置为 setuid 或 setgid,或者使用授权进行签名。来自 the source code for dyld.cpp:
dyld::log("dyld: DYLD_ environment variables being ignored because ");
switch (sRestrictedReason) {
case restrictedNot:
break;
case restrictedBySetGUid:
dyld::log("main executable (%s) is setuid or setgid\n", sExecPath);
break;
case restrictedBySegment:
dyld::log("main executable (%s) has __RESTRICT/__restrict section\n", sExecPath);
break;
case restrictedByEntitlements:
dyld::log("main executable (%s) is code signed with entitlements\n", sExecPath);
break;
}