Skip to content

Commit

Permalink
Add: Extend nasl_ssh_shell_read() (#964)
Browse files Browse the repository at this point in the history
The function receives now a new parameter timeout.
If a timeout is given, enables the blocking ssh read until it gives the timeout or there is no bytes left to read.
Otherwise, it does a non-blocking ssh read as before.

To test, run the following script (it should be a debian based OS, with dpkg cmd)

`time sudo openvas-nasl -X -B -d -i /home/jjnicola/install/var/lib/openvas/plugins -t 192.168.0.1 ssh_shell_gather_package_list_ssh_read_timeout.nasl
`

```
if(description)
{
  script_oid("1.3.6.1.4.1.25623.1.0.ssh1");
  script_version("2020-11-12T09:50:32+0000");
  script_tag(name:"last_modification", value:"2021-11-17 11:25:00 +0000 (Mon, 17 May 2021)");
  script_tag(name:"creation_date", value:"2021-11-17 11:25:00 +0000 (Mon, 17 May 2021)");
  script_tag(name:"cvss_base", value:"0.0");
  script_tag(name:"cvss_base_vector", value:"AV:N/AC:L/Au:N/C:N/I:N/A:N");
  script_name("SSH shell 1");
  script_category(ACT_GATHER_INFO);
  script_copyright("Copyright (C) 2007-2012 Greenbone Networks GmbH");
  script_family("General");

  script_tag(name:"summary", value:"This script tries to login with provided credentials.

  If the login was successful, it marks this port as available for any authenticated tests.");

  script_tag(name:"qod_type", value:"remote_banner");

  exit(0);
}

include("ssh_func.inc");
include("misc_func.inc");

port = 22;
user = 'USER';
pass = 'PASS';
priv_user = 'root';
priv_pass = 'ROOT_PASS';

function clean_buffer(sess) {
  while( TRUE ) {
    c = ssh_shell_read(sess);
    if( strlen( c ) <= 0 ) break;
  }
};

soc = open_sock_tcp( port );
if( ! soc ) exit( 0 );
display (soc);

display("Open connection");
sess = ssh_connect( socket:soc );
display("User Auth");
prompt = ssh_userauth(sess, login:user, password:pass);

display("Open shell");
sess = ssh_shell_open (sess, pty:1);
clean_buffer (sess);

cmd1 = "whoami" + '\n';
sh_wr = ssh_shell_write(sess, cmd:cmd1);
ret = "";
ret = ssh_shell_read(sess, timeout: 1000);
display("Return whoami before priv login: ", ret);

display("Changing to root");
cmd1 = 'su - ' + priv_user  + '\n';
sh_wr = ssh_shell_write(sess, cmd:cmd1);

ret = "";
ret = ssh_shell_read(sess, timeout: 1000);
   display(ret);

if (strstr(ret, "Password")){
   cmd1 = priv_pass + '\n';
   sh_wr = ssh_shell_write(sess, cmd:cmd1);
   clean_buffer(sess);
}

cmd1 = 'dpkg -l' + '\n';
sh_wr = ssh_shell_write(sess, cmd:cmd1);

ret = ssh_shell_read(sess, timeout: 1000);
display("Return whoami after priv login: ", ret);

ssh_shell_close(sess);
ssh_disconnect(sess);
display("Finished, close, disconnect script 1");
```

(cherry picked from commit be5a0af)
  • Loading branch information
jjnicola authored and mergify-bot committed Dec 6, 2021
1 parent 5e95e3a commit 0272c14
Showing 1 changed file with 66 additions and 2 deletions.
68 changes: 66 additions & 2 deletions nasl/nasl_ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -1743,6 +1743,53 @@ nasl_ssh_shell_open (lex_ctxt *lexic)
return retc;
}

/**
* @brief read from an ssh channel until timeouts or there is no bytes left to
* read.
*
* @param[in] channel SSH Channel.
* @param[out] response Buffer to store response in.
* @param[in] timeout Timeout in milliseconds.
*
* @return 0 if success, -1 if error.
*/
static int
read_ssh_blocking (ssh_channel channel, GString *response, int timeout)
{
int rc;
char buffer[4096];

/* Read stderr */
do
{
if ((rc = ssh_channel_read_timeout (channel, buffer, sizeof (buffer), 1,
timeout))
> 0)
g_string_append_len (response, buffer, rc);

else if (rc == SSH_ERROR)
goto exec_err;
}
while (rc > 0 || rc == SSH_AGAIN);

/* Read stdout */
do
{
if ((rc = ssh_channel_read_timeout (channel, buffer, sizeof (buffer), 0,
timeout))
> 0)
g_string_append_len (response, buffer, rc);

else if (rc == SSH_ERROR)
goto exec_err;
}
while (rc > 0 || rc == SSH_AGAIN);
rc = SSH_OK;

exec_err:
return rc;
}

/**
* @brief read from an ssh channel without blocking.
*
Expand Down Expand Up @@ -1781,6 +1828,11 @@ read_ssh_nonblocking (ssh_channel channel, GString *response)
*
* - An SSH session id.
*
* @naslparam timeout
*
* - Enable the blocking ssh read until it gives the timeout or there is no
* bytes left to read.
*
* @naslret A string on success or NULL on error.
*
* @param[in] lexic Lexical context of NASL interpreter.
Expand All @@ -1794,15 +1846,27 @@ nasl_ssh_shell_read (lex_ctxt *lexic)
ssh_channel channel;
tree_cell *retc;
GString *response;
int timeout;

session_id = get_int_var_by_num (lexic, 0, -1);
if (!verify_session_id (session_id, "ssh_shell_read", &tbl_slot, lexic))
return NULL;
channel = session_table[tbl_slot].channel;

response = g_string_new (NULL);
if (read_ssh_nonblocking (channel, response))
return NULL;

timeout = get_int_var_by_name (lexic, "timeout", 0);

if (timeout > 0)
{
if (read_ssh_blocking (channel, response, timeout))
return NULL;
}
else
{
if (read_ssh_nonblocking (channel, response))
return NULL;
}
retc = alloc_typed_cell (CONST_DATA);
retc->size = response->len;
retc->x.str_val = g_string_free (response, FALSE);
Expand Down

0 comments on commit 0272c14

Please sign in to comment.