简体   繁体   English

如何在 Java 程序中拦截 SSH 密码请求

[英]How to intercept SSH Password request in a Java Program

I am need to spawn a SSH connection from a JAVA program using ProcessBuilder and a USERID/PASSWORD combination.我需要使用 ProcessBuilder 和 USERID/PASSWORD 组合从 JAVA 程序生成 SSH 连接。

I have already successfully implemented SSH connections using Ganymed, JSch, a combination of JAVA Processbuilder and Expect scripting (Expect4J also), JAVA ProcessBuilder and SSHPASS script and SSH Shared Key.我已经使用 Ganymed、JSch、JAVA Processbuilder 和 Expect 脚本(也包括 Expect4J)、JAVA ProcessBuilder 和 SSHPASS 脚本以及 SSH 共享密钥的组合成功实现了 SSH 连接。

Security is NOT a concern at this point in time and all I am after is to be able to support programmatically all kinds of combinations for SSH connection.目前安全性不是问题,我所追求的只是能够以编程方式支持 SSH 连接的各种组合。

My problem is the Password prompt that SSH throws somewhere that is not on STDIN/STDOUT (on a tty I believe).我的问题是 SSH 抛出的密码提示不在 STDIN/STDOUT 上(我相信是在 tty 上)。 This is my last hurdle to overcome.这是我要克服的最后一道障碍。

My question is there a way to intercept SSH password request and provide it from my JAVA code?我的问题是有没有办法拦截 SSH 密码请求并从我的 JAVA 代码中提供它?

Please, note this is a very narrow question (and all the above information was to guarantee the answer would not be too broad).请注意,这是一个非常狭窄的问题(以上所有信息都是为​​了保证答案不会太宽泛)。

Here is a sample code of what I am trying:这是我正在尝试的示例代码:

import  java.io.*;
import  java.util.*;

public class ProcessBuilderTest {
    public  static void main(String[] args) throws IOException, Exception {

        ProcessBuilder pb = new ProcessBuilder(
                                "/usr/bin/ssh",
                                "nyuser@myserver.com",
                                "export NOME='Jennifer Lawrence'; echo $NOME"
                                );


        pb.redirectErrorStream(); //redirect stderr to stdout
        Process process = pb.start();
        InputStream inputStream = process.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line = null;
        while((line = reader.readLine())!= null) {
            System.out.println(line);
        }
        process.waitFor();
     }
}

But, when I run it I got this:但是,当我运行它时,我得到了这个:

[memphis BuilderTest]# java ProcessBuilderTest

myuser@myserver's password: 

and after I type the password, I got the rest of the output:输入密码后,我得到了其余的输出:

Jennifer Lawrence

[memphis BuilderTest]# 

Again, the specific question is: Is there a way to spawn an external ssh client (OpenSSH, Tectia SSH, SecureCRT, etc) using PasswordAuthentication method (no other method can be used) process using JAVA ProcessBuilder interface (no other language can be used), intercept/capture the password prompt and respond/interact providing that password from my JAVA code (so the user does not need to type it)?同样,具体问题是:有没有办法使用 JAVA ProcessBuilder 接口(不能使用其他语言)使用 PasswordAuthentication 方法(不能使用其他方法)生成外部 ssh 客户端(OpenSSH、Tectia SSH、SecureCRT 等) ),拦截/捕获密码提示并响应/交互从我的 JAVA 代码中提供该密码(因此用户不需要键入它)?

You need to learn about pseudo-ttys, assuming that you are operating on Linux.假设您在 Linux 上操作,您需要了解伪 ttys。 The password prompt is on the tty device.密码提示在 tty 设备上。 You will need to build a separate process running against a pseudo-tty instead of just inheriting your tty device, and then you can intercept the password prompt.您将需要构建一个针对伪 tty 运行的单独进程,而不仅仅是继承您的 tty 设备,然后您可以拦截密码提示。

This is a moderately complex process.这是一个中等复杂的过程。

There is a library that supports some of this: http://www.ganymed.ethz.ch/ssh2/FAQ.html .有一个库支持其中的一些: http : //www.ganymed.ethz.ch/ssh2/FAQ.html You might find reading its source illuminating if it is available.如果它可用,您可能会发现阅读其来源很有启发性。

While it has been suggested that a pseudo-tty (pty) is required to simulate a terminal, the accepted answer doesn't provide a working solution - there are also lots of similar questions with no working answers.虽然有人建议需要伪 tty (pty) 来模拟终端,但接受的答案并没有提供有效的解决方案 - 还有很多类似的问题没有有效的答案。

Here are two solutions that allow you to capture the "Password:" prompt in SSH and enter the password in an automated way without using SSH_ASKPASS or Expect.这里有两种解决方案,允许您在 SSH 中捕获“密码:”提示并以自动方式输入密码,而无需使用 SSH_ASKPASS 或 Expect。

Why use one programming language when you can use two - the first option isn't ideal, but it demonstrates the solution:当您可以使用两种编程语言时,为什么要使用一种编程语言 - 第一个选项并不理想,但它演示了解决方案:

ProcessBuilder pb = new ProcessBuilder("/usr/bin/python", "-c", "import pty; pty.spawn(['/usr/bin/ssh', '<hostname>'])");

The above example makes use of the Python pty module to wrap SSH into a PTY.上面的示例使用 Python pty模块将 SSH 包装到 PTY 中。 Although it is simple, it doesn't provide any flexibility to allow you to modify any terminal properties like the passed window size.尽管它很简单,但它没有提供任何灵活性来允许您修改任何终端属性,例如传递的窗口大小。

The other more lightweight option is to use a PTY wrapper in C - the pty tool from the "Advanced Programming in the UNIX® Environment" book is just this - the source can be found at https://github.com/abligh/pty .另一个更轻量级的选择是在 C 中使用 PTY 包装器——“UNIX® 环境中的高级编程”一书中的pty工具就是这个——源代码可以在https://github.com/abligh/pty找到.

You will then use it in a similar way, but referencing the pty tool instead of Python:然后您将以类似的方式使用它,但引用pty工具而不是 Python:

ProcessBuilder pb = new ProcessBuilder("/usr/local/bin/pty", "/usr/bin/ssh", "<hostname>");

This is the same approach that Expect uses to simulate a PTY, which is why you are able to intercept it using Expect.这与 Expect 用于模拟 PTY 的方法相同,这就是您能够使用 Expect 拦截它的原因。 It goes without saying that tunneled clear text passwords are insecure and public key authentication should always be the preferred way of doing this.不用说,隧道明文密码是不安全的,公钥认证应该始终是这样做的首选方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM