Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions docs/_docs/user-guide/eldritch.md
Original file line number Diff line number Diff line change
Expand Up @@ -552,37 +552,32 @@ The <b>pivot.smb_exec</b> method is being proposed to allow users a way to move

### pivot.ssh_copy

`pivot.ssh_copy(target: str, port: int, src: str, dst: str, username: str, password: Optional<str>, key: Optional<str>, key_password: Optional<str>, timeout: Optional<int>) -> None`
`pivot.ssh_copy(target: str, port: int, src: str, dst: str, username: str, password: Optional<str>, key: Optional<str>, key_password: Optional<str>, timeout: Optional<int>) -> str`

The <b>pivot.ssh_copy</b> method copies a local file to a remote system. If no password or key is specified the function will error out with:
`Failed to run handle_ssh_exec: Failed to authenticate to host`
The <b>pivot.ssh_copy</b> method copies a local file to a remote system.
ssh_copy will return `"Sucess"` if successful and `"Failed to run handle_ssh_copy: ..."` on failure.
If the connection is successful but the copy writes a file error will be returned.

ssh_copy will first delete the remote file and then write to its location.
ssh_copy will overwrite the remote file if it exists.
The file directory the `dst` file exists in must exist in order for ssh_copy to work.


### pivot.ssh_exec

`pivot.ssh_exec(target: str, port: int, command: str, username: str, password: Optional<str>, key: Optional<str>, key_password: Optional<str>, timeout: Optional<int>) -> List<Dict>`

The <b>pivot.ssh_exec</b> method executes a command string on the remote host using the default shell. If no password or key is specified the function will error out with:
`Failed to run handle_ssh_exec: Failed to authenticate to host`
If the connection is successful but the command fails no output will be returned but the status code will be set.
Not returning stderr is a limitation of the way we're performing execution. Since it's not using the SSH shell directive we're limited on the return output we can capture.
The <b>pivot.ssh_exec</b> method executes a command string on the remote host using the default shell.
Stdout returns the string result from the command output.
Stderr will return any errors from the SSH connection but not the command being executed.
Status will be equal to the code returned by the command being run and -1 in the event that the ssh connection raises an error.

```json
{
"stdout": "uid=1000(kali) gid=1000(kali) groups=1000(kali),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),118(bluetooth),128(lpadmin),132(scanner),143(docker)\n",
"stderr":"",
"status": 0
}
```

### pivot.ssh_password_spray

`pivot.ssh_password_spray(targets: List<str>, port: int, credentials: List<str>, keys: List<str>, command: str, shell_path: str) -> List<str>`

The <b>pivot.ssh_password_spray</b> method is being proposed to allow users a way to test found credentials against neighboring targets. It will iterate over the targets list and try each credential set. Credentials will be a formatted list of usernames and passwords Eg. "username:password". The function will return a formatted list of "target:username:password". command and shell_path is intended to give more flexibility but may be adding complexity.

---

## Process
Expand Down
11 changes: 2 additions & 9 deletions implants/lib/eldritch/src/pivot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ mod reverse_shell_pty_impl;
mod smb_exec_impl;
mod ssh_copy_impl;
mod ssh_exec_impl;
mod ssh_password_spray_impl;

use anyhow::Result;
use async_trait::async_trait;
Expand Down Expand Up @@ -48,14 +47,8 @@ fn methods(builder: &mut MethodsBuilder) {
}

#[allow(unused_variables)]
fn ssh_copy<'v>(this: &PivotLibrary, target: String, port: i32, src: String, dst: String, username: String, password: Option<String>, key: Option<String>, key_password: Option<String>, timeout: Option<u32>) -> anyhow::Result<NoneType> {
ssh_copy_impl::ssh_copy(target, port, src, dst, username, password, key, key_password, timeout)?;
Ok(NoneType{})
}

#[allow(unused_variables)]
fn ssh_password_spray(this: &PivotLibrary, targets: UnpackList<String>, port: i32, credentials: UnpackList<String>, keys: UnpackList<String>, command: String, shell_path: String) -> anyhow::Result<String> {
ssh_password_spray_impl::ssh_password_spray(targets.items, port, credentials.items, keys.items, command, shell_path)
fn ssh_copy<'v>(this: &PivotLibrary, target: String, port: i32, src: String, dst: String, username: String, password: Option<String>, key: Option<String>, key_password: Option<String>, timeout: Option<u32>) -> anyhow::Result<String> {
ssh_copy_impl::ssh_copy(target, port, src, dst, username, password, key, key_password, timeout)
}

#[allow(unused_variables)]
Expand Down
9 changes: 3 additions & 6 deletions implants/lib/eldritch/src/pivot/ssh_copy_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub fn ssh_copy(
key: Option<String>,
key_password: Option<String>,
timeout: Option<u32>,
) -> Result<()> {
) -> Result<String> {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()?;
Expand All @@ -63,14 +63,11 @@ pub fn ssh_copy(
)) {
Ok(local_res) => local_res,
Err(local_err) => {
return Err(anyhow::anyhow!(
"Failed to run handle_ssh_exec: {}",
local_err.to_string()
))
return Ok(format!("Failed to run handle_ssh_copy: {}", local_err));
}
};

Ok(())
Ok("Sucess".to_string())
}

#[cfg(test)]
Expand Down
16 changes: 6 additions & 10 deletions implants/lib/eldritch/src/pivot/ssh_exec_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub fn ssh_exec(
let key_password_ref = key_password.as_deref();
let local_port: u16 = port.try_into()?;

let cmd_res = match runtime.block_on(handle_ssh_exec(
let (out, status, err) = match runtime.block_on(handle_ssh_exec(
target,
local_port,
command,
Expand All @@ -73,19 +73,15 @@ pub fn ssh_exec(
key_password_ref,
timeout,
)) {
Ok(local_res) => local_res,
Err(local_err) => {
return Err(anyhow::anyhow!(
"Failed to run handle_ssh_exec: {}",
local_err.to_string()
))
}
Ok(local_res) => (local_res.stdout, local_res.status, String::from("")),
Err(local_err) => (String::from(""), -1, local_err.to_string()),
};

let res = SmallMap::new();
let mut dict_res = Dict::new(res);
insert_dict_kv!(dict_res, starlark_heap, "stdout", &cmd_res.stdout, String);
insert_dict_kv!(dict_res, starlark_heap, "status", cmd_res.status, i32);
insert_dict_kv!(dict_res, starlark_heap, "stdout", &out, String);
insert_dict_kv!(dict_res, starlark_heap, "stderr", &err, String);
insert_dict_kv!(dict_res, starlark_heap, "status", status, i32);

Ok(dict_res)
}
Expand Down
12 changes: 0 additions & 12 deletions implants/lib/eldritch/src/pivot/ssh_password_spray_impl.rs

This file was deleted.

2 changes: 1 addition & 1 deletion implants/lib/eldritch/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ mod tests {
parameters: HashMap::new(),
file_names: Vec::new(),
},
want_text: format!("{}\n", r#"["arp_scan", "bind_proxy", "ncat", "port_forward", "port_scan", "reverse_shell_pty", "smb_exec", "ssh_copy", "ssh_exec", "ssh_password_spray"]"#),
want_text: format!("{}\n", r#"["arp_scan", "bind_proxy", "ncat", "port_forward", "port_scan", "reverse_shell_pty", "smb_exec", "ssh_copy", "ssh_exec"]"#),
want_error: None,
},
assets_bindings: TestCase {
Expand Down
Loading