Java应用程序有没有办法获得root权限?

Posted

技术标签:

【中文标题】Java应用程序有没有办法获得root权限?【英文标题】:Is there a way for a Java app to gain root permissions? 【发布时间】:2016-08-18 02:29:51 【问题描述】:

当以非特权用户身份运行Files.walk(Paths.get("/var/")).count() 时,执行可能会引发异常,因为/var/ 中存在需要root 权限才能遍历的文件夹。

不是正在寻找一种以 root 身份执行 bash 命令的方法(例如 sudo find /var),使用 Process 等。

我只是想确保Files.walk(Paths.get("/var/")).count() 不会抛出AccessDeniedException

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0
    at sun.reflect.NativeMethodAccessorImpl.invoke
    at sun.reflect.DelegatingMethodAccessorImpl.invoke
    at java.lang.reflect.Method.invoke
    at org.springframework.boot.devtools.restart.RestartLauncher.run
Caused by: java.io.UncheckedIOException: java.nio.file.AccessDeniedException: /var/cache/httpd
    at java.nio.file.FileTreeIterator.fetchNextIfNeeded
    at java.nio.file.FileTreeIterator.hasNext
    at java.util.Iterator.forEachRemaining
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining
    at java.util.stream.AbstractPipeline.copyInto
    at java.util.stream.AbstractPipeline.wrapAndCopyInto
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential
    at java.util.stream.AbstractPipeline.evaluate
    at java.util.stream.LongPipeline.reduce
    at java.util.stream.LongPipeline.sum
    at java.util.stream.ReferencePipeline.count
    at com.example.DemoApplication.main
    ... 5 more
Caused by: java.nio.file.AccessDeniedException: /var/cache/httpd
    at sun.nio.fs.UnixException.translateToIOException
    at sun.nio.fs.UnixException.rethrowAsIOException
    at sun.nio.fs.UnixException.rethrowAsIOException
    at sun.nio.fs.UnixFileSystemProvider.newDirectoryStream
    at java.nio.file.Files.newDirectoryStream
    at java.nio.file.FileTreeWalker.visit
    at java.nio.file.FileTreeWalker.next
    at java.nio.file.FileTreeIterator.fetchNextIfNeeded

这只是一个例子。使用filter(...) 可以解决该异常。但是这个例子也可以扩展到其他用例。

简而言之,对于 CLI、JavaFX 等应用程序,通过java -jar app.jar 等方法从命令行执行后,这是否可能获得 root 权限?

【问题讨论】:

如果可能的话,这将是一个重大的安全问题......想象一下,该应用程序获得了 root 访问权限并执行了rm -rf /。哎呀。 应用可以弹出一个对话框,要求用户输入sudo/root密码。许多本机应用程序已经具有此功能。例如。 Gnome 软件、磁盘工具等。OOPS。 ;-) 正确的问题是“我如何忽略我无法访问的位置”。 诚实并要求对您的应用进行 sudo 执行。所有 linux 用户都会喜欢这种方法 相关:***.com/questions/2483755/… 【参考方案1】:

如果你想要的实际上是跳过你无法访问的路径,你有两种方法:

In the answer to this question解释了如何获取可以访问的子树的所有文件的流。

但这个例子也可以扩展到其他用例。

文件访问者

使用FileVisitor 会添加大量代码,但在遍历目录树时会赋予您更大的灵活性。要解决同样的问题,您可以将Files.walk() 替换为:

Files.walkFileTree(Path start, FileVisitor<? super Path> visitor);

扩展 SimpleFileVisitor(对文件进行计数)并覆盖一些方法。

你可以:

    重写visitFileFailed方法,处理因某些原因无法访问文件的情况; (Lukasz_Plawny 的建议) (可选)覆盖preVisitDirectory方法,在访问目录之前检查权限:如果你不能访问它,你可以简单地跳过它的子树(记住你可能可以访问一个目录,但是不是所有文件);

例如1

@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) 
    // you can log the exception 'exc'
    return FileVisitResult.SKIP_SUBTREE;

例如2

@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) 

    if(!Files.isReadable(dir))
        return FileVisitResult.SKIP_SUBTREE;

    return FileVisitResult.CONTINUE;


FileVisitor docs

FileVisitor tutorial

希望对你有帮助。

【讨论】:

我的建议是从FileVisitor 实现visitFileFailed 方法,当无法访问文件时调用该方法。当你在这个方法中添加return FileVisitResult.SKIP_SUBTREE; 时,就不会抛出AccessDeniedException。【参考方案2】:

只是一些完全未经测试的想法:

1) 首先使用 root 权限运行您的应用:

sudo java -jar myapp.jar

2) 让您的应用启动一个请求 root 权限的启动器类,然后继续运行应用的其余部分:

java -jar myapp.jar

这反过来确实执行了一个shell命令,但只是一个提示输入root密码的xterm,然后继续以root权限运行一个java程序:

xterm -e "sudo sh -c 'java -jar /tmp/myrootapp.jar'"

或者也许使用 gksudo 使用更好看的东西。注意'"

也许myapp.jar 将自己提取到temporary directory 中。 myapp.jar 包含 myrootapp.jar,因此它可以如上所述启动它。 /tmp 当然应该从 java 中检索,最好是一个随机名称的目录,只有运行 myapp.jar 的用户才能访问,以防止 myrootapp.jar 注入。

跨平台

您自己提到了/var/,所以我假设您使用的是某种 Linux。如果这应该跨平台工作,例如在 Macintosh 或 Microsoft Windows 上,您也需要先进行某种系统识别。然后你可以在代码中应用StrategyPattern来处理让myrootapp.jar获得root或管理员权限的各种方式。

【讨论】:

但是,根据您的应用程序,请记住,以 root 权限运行您的应用程序可能会引入更多有害漏洞。例如,当您使用 Rhino 引擎时,存在注入漏洞,允许攻击者通过引擎注入任意 Java 代码。在这种情况下,这个注入的代码当然是以 root 权限运行的。【参考方案3】:

没有简单的方法可以更改权限。 Java 不擅长这些任务。只有一些技巧,例如在启动时检查权限并尝试通过 su/sudo 更改权限,然后重新启动应用程序或使用 Java-gnome。请在此处阅读更多内容:Java: Ask root privileges on Ubuntu

【讨论】:

以上是关于Java应用程序有没有办法获得root权限?的主要内容,如果未能解决你的问题,请参考以下文章

小米MIX 3获得ROOT权限的步骤

如何获得MIUI10系统的root超级权限

如何以编程方式获得 root 权限?

小米手机怎么获得root权限

Android如何获得系统(system)权限

如何获得小米手机4c的Root超级权限