Making Expect scripts for SSH Authentication and Privilege Elevation

Expect can help you to automate interactive console applications. For example, expect script can go to some Linux host via SSH with password authentication, make additional authentication procedures (su, sudo) to elevate privileges and execute some commands. Like Vulnerability and Compliance management products do during the active Linux scanning, right? 🙂 For example you can get the list of installed packages and make Vulnerability Assessment without Vulnerability Scanner.

Expect SSH exec

Actually, the tool is pretty old. It was presented more than 20 years ago! And perhaps now it makes more sense to use python scripts, for example paramiko with paramiko-expect. Or even use some software provisioning tool, like Ansible. But my fun was in creating (generating?) a small old-school scripts that could be sent to any remote host (with expect installed) to gather information from the accessible hosts.

So, the installation is trivial:

# yum install expect

Expect scripting language is an extension to the Tcl. In this language you can set the variables, commands that you want to ran, the lines that you expect from the server response and the commands that will be sent back. I will not show it here, but you can set the timeouts flexibly and initialize the variables from command line (e.g. argv[1]).

Here is a sample ssh_exec.exp script for password-based and authentication and privilege elevation using sudo:

#!/usr/bin/expect

## Parameters

set user "username"
set host "server.corporation.com"
set password "Password123"
set command "cat /etc/shadow"

## Commands

spawn ssh -o StrictHostKeyChecking=no $user@$host
expect "password:" {send "$password\r"}
expect "\$ " {send "sudo su\r"}
expect "password" {send "$password\r"}
expect "\# " {send "$command >temp_file 2>temp_file_error; chown $user temp_file; chown $user temp_file_error;\r"} 
expect "\# " {send "exit;\r"}
expect "\$ " {send "exit;\r"}

Here I want to connect to server.corporation.comusing credentials username/Password123. When the scripts connects to server, server asks for password. The script expects the line with “password:” and sends the password value. Note the option “-o StrictHostKeyChecking=no” that helps to avoid checking host key against known_hosts file and related questions.

On the host I want to read /etc/shadowfile. But I can’t do it with the rights of a normal user, root access is required. So, in the same manner script expects the line with “$ “, sends “sudo su” and repeats the password to elevate privileges.

Then the script expects the line with “” and executes the necessary command. The output of the  “cat /etc/shadow” will be saved in “temp_file” and the possible errors will be saved in “temp_file_error“. It is also necessary to change permissions on the files, so it will be easier to get them from the server.

Output:

$ expect ssh_exec.exp 
spawn ssh -o StrictHostKeyChecking=no username@server.corporation.com
username@server.corporation.com's password: 
Last login: Fri Sep  9 19:40:23 2018 from desktop12.corporation.com
[username@server.corporation.com ~]$ sudo su
[sudo] password for username: 
[root@server.corporation.com username]# cat /etc/passwd >temp_file 2>temp_file_error; chown username temp_file; chown username temp_file_error;
[root@server.corporation.com username]# exit;
exit

Here is a script for retrieving files from the server with password authentication. It works similar, but with scp tool:

#!/usr/bin/expect

## Parameters

set user "username"
set host "server.corporation.com"
set password "Password123"
set remotefilepath "~/temp_file"
set localfilepath "temp_file"

## Commands

spawn scp -o StrictHostKeyChecking=no $user@$host:$remotefilepath $localfilepath
expect "password:" {send "$password\r"}
expect "\$ " {send "sudo su\r"}

Output:

$ expect scp_get_file.exp 
spawn scp -o StrictHostKeyChecking=no username@server.corporation.com:~/temp_file temp_file
username@server.corporation.com's password: 
temp_file                                            100% 2390   203.9KB/s   00:00    

In the same manner you can get the temp_file_error file.

2 thoughts on “Making Expect scripts for SSH Authentication and Privilege Elevation

  1. Sakib Mesalic

    Hi Alexander,
    thank you very much for your help with except. It’s really helping.
    I am working on a scrip and I like to ask you for an advice related to ssh login. The script should be used to log on a Linux server which may and may not require RSA token.
    If a Linux server does not requires RSA token the script works fine.
    spawn ssh [lindex $argv 1]@[lindex $argv 0]

    expect “yes/no” {
    send “yes\r”
    expect “*?assword” { send “[lindex $argv 2]\r”}
    } “*?assword” { send “[lindex $argv 2]\r” }

    expect “$ ” { send “hostname -i\r” }
    expect “$ ” { send “sudo passwd -S my_usr_id\r” }
    expect “$ ” { send “echo \r” }
    exit

    But If requires RSA I would like to enter it using key board and proceed with the rest of the commands.
    Can you please help?

    I really appreciate your time and help.
    Thank you,
    Sakib Mesalic

    Reply
  2. Pingback: Linux Expect Ssh? The 6 Detailed Answer - Ar.taphoamini.com

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.