Python script for SSH through PuTTY

后端 未结 3 1074
隐瞒了意图╮
隐瞒了意图╮ 2021-01-07 10:46

I am able to give the following command in the command-line

C:\\>cd \"C:\\Program Files\\ExtraPuTTY\\Bin\"

C:\\P         


        
相关标签:
3条回答
  • 2021-01-07 10:55

    I know it' a bit beside the question, but that the most closed topic I found (I'd like to found that code a week ago on that post)

    I was looking for a code to massively check if a password is active, and change it if possible

    Putty have several cli tool like plink and pscp whch are useful for a lot of stuff.

    Here is python 3 function to connect to a ssh server and accept ssh key. using pscp allow a auto accept key... can be useful for first time

    def TestSSHConnection(IP_Addr,User,Password,verbosity=0, force_plink=False):
    #Some infos about returned code
    # 0 = Error Or crash
    # 1 = Connection ok
    # 2 = No connect Password Error
    # 3 = SSH key trouble (shit append)
    # 4 = Timeout
    # 5 = Host Unreachable
    # 6 = Connection Crash
    
    out=""
    err=""
    try:
        if force_plink:
            print("echo y | plink -l "+str(User)+" -pw "+str(Password)+" -batch "+str(IP_Addr)+" exit",)
            ssh=subprocess.Popen("echo y | plink -l "+str(User)+" -pw "+str(Password)+" -batch "+str(IP_Addr)+" exit",shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,encoding='utf8')#,stdin=subprocess.PIPE)
        else:
            print("echo y | pscp -l "+str(User)+" -pw "+str(Password)+" -ls "+str(IP_Addr)+":/",)
            ssh=subprocess.Popen("echo y | pscp -l "+str(User)+" -pw "+str(Password)+" -ls "+str(IP_Addr)+":/",shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    
        out,err = ssh.communicate()
        try:
            out = out.decode('utf-8')
        except AttributeError as inst:
            pass
        except Exception as inst:
            if verbosity>1:
                print("While decoding stdout: "+str(type(inst)))
        try:
            err = err.decode('utf-8')
        except AttributeError as inst:
            pass
        except Exception as inst:
           print("While decoding stderr: "+str(type(inst)))
        ssh.kill()
        del ssh
    except Exception as inst:
        print("Crash"+str(inst))
        return 0
    
    if len(err)>0:
        if 'Unable to open connection' in err or 'Host does not exist' in err:
            if verbosity>0: print("Unreachable")
            result = 5
            if verbosity>1:
                print()
                print("-"*30)
                print(err)
                print("-"*30)
    
        elif 'Connection timed out' in err:
            result = 4
    
        elif 'The server\'s host key is not cached in the registry' in err:
            result = 3
            if verbosity>1:
                print()
                print("SSH key Err".center(30,"-"))
                print(err)
                print("-"*30)
    
        elif 'Access denied' in err:
            result = 2
            if verbosity>2:
                print()
                print("Denied".center(30,"-"))
                print(err)
                print("-"*30)
        else:
            result = 6
            if verbosity>0: print("ConnCrash")
            print("Oups".center(30,"-"))
            print(err)
            print("-"*30)
    else:
        if verbosity>0: print("Conn ok")
        result = 1
    
    del out,err
    return result
    

    Of cource, this juste Check connection (and accept ssh key)

    So here is a code to run a script on the host (precisely a password change). To do so, you can't use one line syntax (even it must work, it won't, i tried) You have to pass through a script file and push it with plink.

    def ChangeMyPassword(IP_Addr,User,Old_Password,New_Password,verbosity=0):
    #Some infos about returned code
    # 0 = Error Or crash
    # 1 = Change Ok
    # 2 = Old Password Error
    # 3 = SSH key trouble (shit append)
    # 4 = Timeout
    # 5 = Host Unreachable
    # 6 = Connection Crash
    
    out=""
    err=""
    
    try:
        path_script = "."+os.sep+"Script_chmdp_"+str(IP_Addr)+".sh"
        if os.path.exists(path_script):os.remove(path_script)
        fic_script = codecs.open(path_script,'w', encoding='utf8')
        fic_script.write('echo -e \"'+str(Old_Password)+'\\n'+str(New_Password)+'\\n'+str(New_Password)+'\" | passwd')
        fic_script.flush()
        fic_script.close()
    
        cmd = "plink -l "+str(User)+" -pw "+str(Old_Password)+" -batch "+str(IP_Addr)+ " "
        cmd += "-m "+path_script
    
        print(str(cmd))
    
        ssh=subprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,encoding='utf8')#,stdin=subprocess.PIPE)
    
        out,err = ssh.communicate()
        try:
            out = out.decode('utf-8')
        except AttributeError as inst:
            pass
        except Exception as inst:
            if verbosity>1:
                print("While decoding stdout: "+str(type(inst)))
        try:
            err = err.decode('utf-8')
        except AttributeError as inst:
            pass
        except Exception as inst:
           print("While decoding stderr: "+str(type(inst)))
        ssh.kill()
        del ssh
    except Exception as inst:
        print("Crash"+str(inst))
        return 0
    
    if 'all authentication tokens updated successfully' in out:
        if verbosity>0: print("Conn ok")
        result = 1
    else:
        if verbosity>0: print("Something goes wrong, hope we do not crash your server :)")
        result = 0
    del out,err
    return result
    

    So now you have two function to massively change password on your systems.

    Bonus: a function to get /etc/passwd and /etc/shadow. Why? for educationnal use on your IT admin like 'hey you f*** up and use the same password everywhere, and now all this account can be Bruteforced. So clean up your mess

    def GetPass(IP_Addr,User,Password,verbosity=0, force_plink=False):
    #Some infos about returned code
    # 0 = Error Or crash
    # 1 = Connection ok
    # 2 = No connect Password Error
    # 3 = SSH key trouble (shit append)
    # 4 = Timeout
    # 5 = Host Unreachable
    # 6 = Connection Crash
    
    out=""
    err=""
    try:
    
        ssh=subprocess.Popen("echo "+str(Password)+" | plink -l "+str(User)+" -pw "+str(Password)+" -batch "+str(IP_Addr)+" sudo cat /etc/passwd;sudo cat /etc/shadow",shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,encoding='utf8')#,stdin=subprocess.PIPE)
    
        out,err = ssh.communicate()
        try:
            out = out.decode('utf-8')
        except AttributeError as inst:
            pass
        except Exception as inst:
            if verbosity>1:
                print("While decoding stdout: "+str(type(inst)))
        try:
            err = err.decode('utf-8')
        except AttributeError as inst:
            pass
        except Exception as inst:
           print("While decoding stderr: "+str(type(inst)))
        ssh.kill()
        del ssh
    except Exception as inst:
        print("Crash"+str(inst))
        return 0
    
    if len(err)>0:
        if 'Unable to open connection' in err or 'Host does not exist' in err:
            if verbosity>0: print("Unreachable")
            result = 5
            if verbosity>1:
                print()
                print("-"*30)
                print(err)
                print("-"*30)
    
        elif 'Connection timed out' in err:
            result = 4
    
        elif 'The server\'s host key is not cached in the registry' in err:
            result = 3
            if verbosity>1:
                print()
                print("SSH key Err".center(30,"-"))
                print(err)
                print("-"*30)
    
        elif 'Access denied' in err:
            result = 2
            if verbosity>2:
                print()
                print("Denied".center(30,"-"))
                print(err)
                print("-"*30)
        else:
            result = 6
            if verbosity>0: print("ConnCrash")
            print("Oups".center(30,"-"))
            print(err)
            print("-"*30)
    else:
        if verbosity>0: print("Conn ok")
        result = out
    
    del out,err
    return result
    

    Some more notes:

    if you don't use shell=True, you don't get the output, and it does not work, I don't know why.

    I also tried a asynchronous communication to send comand line by line, it does not work.

    I also tried the ssh command (yes it now exist on windows \o/) but it does not work for my purpose.

    Hope this help someone one day, it would have helped me a lot a week ago :)

    0 讨论(0)
  • 2021-01-07 10:58

    In the putty download page, download and install plink, and make sure its in the windows path ($PATH variable)

    Then, this python snippet should work:

    import subprocess
    cmd='plink -ssh {}@{} -pw {}'.format(user,server,password)
    sp = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True)
    sp.stdin.write(stdin)
    sp.stdin.close()
    stdout= sp.stdout.read()
    stderr=sp.stderr.read()
    sp.wait()
    

    stdin is the commands typed by the user in the terminal, stdout and stderr are the server output.

    Fill in your credentials in the user="root", server="172.20.0.102 22" and maybe password for the ssh connection

    0 讨论(0)
  • 2021-01-07 11:13

    You have to pass the cwd as the cwd parameter of the Popen:

    Popen(['putty.exe -ssh'...], shell=True, stdout=f, stderr=f, cwd=cwd)
    

    And you should use Plink, not PuTTY, for automating the remote command execution. The Plink accepts the command on its command-line (PuTTY does not):

    Popen(['plink.exe -ssh root@172.20.0.102 ls'], shell=True, stdout=f, stderr=f, cwd=cwd)
    
    0 讨论(0)
提交回复
热议问题