我的应用程序需要以非root用户身份运行,但需要切换到其他用户才能执行某些命令。
我试图:
编写一个JNI,
JNIEXPORT void JNICALL Java_SetUIDJNI_setuid(JNIEnv *env, jobject thisObj,jstring uname) {
const char *name = jstringTostring(env,uname);
int pid;
struct passwd *p;
show_ids();
if ((p = getpwnam(name)) == NULL) {
perror(name);
exit(EXIT_FAILURE);
}
pid = (int) p->pw_uid;
printf("pid=%d\n",pid);
if (seteuid (pid) < 0) {
perror ("setuid");
exit (EXIT_FAILURE);
}
show_ids();
}
以 root 和 chmod u + s
构建-rwsr-xr-x 1 root root 76155 Aug 7 16:56 libsetuid.so*
在Java中调用
api = new SetUIDJNI(); // invoke the native method
api.setuid("slurm");
但是如果以非根用户身份运行,它将无法正常工作
/opt/jdk1.8/jre/bin/java -Djava.library.path=../jni HelloJNI
The real user ID is: 1000
The effective user ID is :1000 <= which expected is 0
setuid: Operation not permitted
但是如果runner是root,它会起作用
The real user ID is: 0
The effective user ID is :0
pid=1002The real user ID is: 0
The effective user ID is :1002
这里有什么问题吗?
更新
将JNI部分修改为可执行文件
void show_ids (void)
{
printf ("The real user ID is: %d\n", getuid());
printf ("The effective user ID is :%d\n", geteuid());
}
int main(void)
{
show_ids();
if (seteuid (1002) < 0) {
perror ("setuid");
exit (EXIT_FAILURE);
}
show_ids();
return (0);
}
以 root 身份构建并运行 chmod u + s
-rwsr-xr-x 1 root root 8814 Aug 9 11:44 a.out*
以普通用户身份运行并正常运行
./a.out
The real user ID is: 1000
The effective user ID is :0
The real user ID is: 1000
The effective user ID is :1002
答案 0 :(得分:0)
seteuid
对JNI不起作用的原因是,JVM进程的有效用户标识不是0(root)。
您显然正在尝试通过将本机库中的“ setuid”位设置为有效的用户ID。那行不通。同样,将JAR文件(或类文件)设置为setuid也不起作用。 setuid位仅在可执行文件上有意义。即 OS本身知道如何执行的文件。
那么我们如何为Java程序实现“ setuid根行为”?
从理论上讲,您可以将/usr/bin/java
标记为root的setuid。 请勿这样做!。如果这样做,您运行的每个Java程序都将以root用户身份运行。那就不好了。
从理论上讲,您可以编写一个Shell脚本来启动您的应用程序。例如
#!/bin/sh
java some.pkg.Main "$@"
并将脚本标记为root的setuid。 请勿这样做! Setuid shell脚本存在安全风险。 (在某些版本的Linux / UNIX上,shell脚本始终不尊重setuid位。)
解决方案是使用本机代码编写自定义JVM启动器,进行编译和链接,并使启动器可执行setuid。请注意,必须非常仔细地编写启动器,以防他人破坏它。例如:
它应该忽略CLASSPATH环境变量,并且不允许以其他任何方式提供类路径。
不应将用户提供的JAR文件作为参数。
应注意,用户不能通过干扰JAR文件的路径来诱使它运行错误的Java代码。
还有其他我没想到的事情!
实际上,以特权用户身份运行Java应用程序可能更安全……完全不依赖“ setuid root”。