Skip to content

Commit

Permalink
Add: NASL builtin function for open privileged sockets with udp and tcp
Browse files Browse the repository at this point in the history
  • Loading branch information
Kraemii committed Nov 25, 2024
1 parent d7e85c8 commit 285ea44
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@

## SYNOPSIS

*any* **open_priv_sock_tcp**(dport: *int*, sport: *int*);
*any* **open_priv_sock_tcp**(dport: *int*, sport: *int*, timeout: *int*);

**open_priv_sock_tcp** takes two named integer arguments:
**open_priv_sock_tcp** takes three named integer arguments:
- dport is the destination port
- sport is the source port, which may be inferior to 1024.
- sport is the source port, which may be inferior to 1024. This argument is optional.
If it is not set, the function will try to open a socket on any port from 1 to 1023.
- timeout: An integer with the timeout value in seconds. The default timeout is controlled by a global value.

## DESCRIPTION

Expand Down
39 changes: 26 additions & 13 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ license = "GPL-2.0-or-later"

[dependencies]
aes = "0.8.2"
aes-gcm = { version = "0.10.1"}
aes-gcm = { version = "0.10.1" }
anyhow = "1.0.75"
async-trait = "0.1.68"
base64 = "0.21.2"
cbc = { version = "0.1.2", features = ["alloc"]}
cbc = { version = "0.1.2", features = ["alloc"] }
ccm = "0.5.0"
chacha20 = "0.9.1"
chrono = { version = "0.4.23", default-features = false, features = ["clock"]}
chrono = { version = "0.4.23", default-features = false, features = ["clock"] }
clap = { version = "4.3.0", features = ["derive", "env"] }
cmac = "0.7.2"
configparser = "3"
Expand Down Expand Up @@ -57,11 +57,14 @@ rustls = "0.23.5"
rustls-pemfile = "2.1.2"
rustls-pemfile-old = { version = "1.0.2", package = "rustls-pemfile" }
sequoia-ipc = "0.30.1"
sequoia-openpgp = { version ="1.16.1", default-features = false, features = ["crypto-openssl"] }
serde = { version = "1.0", features = ["derive"]}
sequoia-openpgp = { version = "1.16.1", default-features = false, features = [
"crypto-openssl",
] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.96"
sha1 = "0.10.5"
sha2 = "0.10.7"
socket2 = "0.5.7"
sysinfo = "0.30.5"
thiserror = "1.0.62"
time = { version = "0", features = ["parsing"] }
Expand All @@ -78,11 +81,13 @@ rayon = { version = "1.8.0", optional = true }
pcap = { version = "1.0.0", optional = true }
pnet_base = { version = "0.33.0", optional = true }
pnet = { version = "0.33.0", optional = true }
socket2 = {version = "0.5.2", features = ["all"], optional = true}
pnet_macros = { version = "0.33.0", optional = true }
pnet_macros_support = { version = "0.33.0", optional = true }

libssh-rs = {version = "~0.2", features = ["vendored-openssl", "vendored"], optional = true}
libssh-rs = { version = "~0.2", features = [
"vendored-openssl",
"vendored",
], optional = true }

nasl-function-proc-macro = { path = "crates/nasl-function-proc-macro" }
nasl-c-lib = { path = "crates/nasl-c-lib", optional = true }
Expand All @@ -92,10 +97,7 @@ rc4 = "0.1.0"

[workspace]
resolver = "2"
members = [
"crates/smoketest",
"crates/nasl-function-proc-macro",
]
members = ["crates/smoketest", "crates/nasl-function-proc-macro"]

[dev-dependencies]
tracing-test = "0.2.5"
Expand All @@ -105,9 +107,20 @@ criterion = "0"
dep-graph-parallel = ["rayon", "crossbeam-channel"]
openvas_serde_support = []
serde_support = []
default = ["dep-graph-parallel", "openvas_serde_support", "enforce-no-trailing-arguments", "serde_support"]
default = [
"dep-graph-parallel",
"openvas_serde_support",
"enforce-no-trailing-arguments",
"serde_support",
]

nasl-builtin-raw-ip = ["pcap", "pnet_base", "pnet", "socket2", "pnet_macros", "pnet_macros_support",]
nasl-builtin-raw-ip = [
"pcap",
"pnet_base",
"pnet",
"pnet_macros",
"pnet_macros_support",
]
nasl-builtin-ssh = ["libssh-rs"]
experimental = ["nasl-builtin-raw-ip", "nasl-builtin-ssh", "nasl-c-lib"]

Expand Down
17 changes: 17 additions & 0 deletions rust/examples/socket/tcp_priv.nasl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: 2024 Greenbone AG
#
# SPDX-License-Identifier: GPL-2.0-or-later WITH x11vnc-openssl-exception

display("Start");
display("is function defined: ", defined_func("open_priv_sock_tcp"));
sock = open_priv_sock_tcp(dport: 34254);
display("was socket created: ", !isnull(sock));
display("fd: ", sock);
ret = send(socket: sock, data: 'foobar');
display("num bytes sent: ", ret);
rec = recv(socket: sock, length: 10, min: 3);
display("received: ", rec);
port = get_source_port(sock);
display("source port: ", port);
close(sock);
display("end");
15 changes: 15 additions & 0 deletions rust/examples/socket/udp_priv.nasl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2024 Greenbone AG
#
# SPDX-License-Identifier: GPL-2.0-or-later WITH x11vnc-openssl-exception

display("Start");
display("is function defined: ", defined_func("open_priv_sock_udp"));
sock = open_priv_sock_udp(dport: 34254);
display("was socket created: ", !isnull(sock));
display("fd: ", sock);
ret = send(socket: sock, data: '123');
display("num bytes sent: ", ret);
rec = recv(socket: sock, length: 10);
display(rec);
close(sock);
display("end");
4 changes: 2 additions & 2 deletions rust/src/nasl/builtin/network/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
## Implements
- open_sock_kdc
- open_sock_tcp
- open_priv_sock_tcp
- open_sock_udp
- open_priv_sock_udp
- close
- send
- recv
Expand All @@ -26,8 +28,6 @@
- get_udp_port_state
- join_multicast_group
- leave_multicast_group
- open_priv_sock_tcp
- open_priv_sock_udp
- scanner_get_port
- start_denial
- end_denial
Expand Down
4 changes: 3 additions & 1 deletion rust/src/nasl/builtin/network/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ fn this_host(context: &Context) -> Result<String, FunctionErrorKind> {

let port: u16 = DEFAULT_PORT;

get_source_ip(dst, port).map(|ip| ip.to_string())
get_source_ip(dst, port)
.map(|ip| ip.to_string())
.map_err(|_| FunctionErrorKind::Diagnostic("No route to destination".to_string(), None))
}

/// Get the host name of the current (attacking) machine
Expand Down
10 changes: 3 additions & 7 deletions rust/src/nasl/builtin/network/network_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,12 @@ pub fn bind_local_socket(dst: &SocketAddr) -> io::Result<UdpSocket> {
}

/// Return the source IP address given the destination IP address
pub fn get_source_ip(dst: IpAddr, port: u16) -> Result<IpAddr, FunctionErrorKind> {
pub fn get_source_ip(dst: IpAddr, port: u16) -> io::Result<IpAddr> {
let socket = SocketAddr::new(dst, port);
let sd = format!("{}:{}", dst, port);
let local_socket = bind_local_socket(&socket)?;
local_socket
.connect(sd)
.ok()
.and_then(|_| local_socket.local_addr().ok())
.and_then(|l_addr| IpAddr::from_str(&l_addr.ip().to_string()).ok())
.ok_or_else(|| FunctionErrorKind::Diagnostic("No route to destination".to_string(), None))
local_socket.connect(sd)?;
Ok(local_socket.local_addr()?.ip())
}

/// Tests whether a packet sent to IP is LIKELY to route through the
Expand Down
107 changes: 100 additions & 7 deletions rust/src/nasl/builtin/network/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,16 @@ impl NaslSockets {
NaslSocket::Tcp(conn) => {
self.wait_before_next_probe();

if !conn.is_tls() {
if let Some(flags) = option {
conn.set_flags(flags as i32);
if let Some(flags) = option {
if flags < 0 || flags > i32::MAX as i64 {
return Err(FunctionErrorKind::WrongArgument(
"the given flags value is out of range".to_string(),
));
}
Ok(conn.send_with_flags(data, flags as i32)?)
} else {
Ok(conn.write(data)?)
}

Ok(conn.write(data)?)
}
NaslSocket::Udp(conn) => {
if let Some(flags) = option {
Expand Down Expand Up @@ -510,6 +513,96 @@ impl NaslSockets {
Ok(NaslValue::Number(fd as i64))
}

/// Open a privileged socket to the target host.
/// It takes three named integer arguments:
/// - dport is the destination port
/// - sport is the source port, which may be inferior to 1024. This argument is optional.
/// If it is not set, the function will try to open a socket on any port from 1 to 1023.
/// - timeout: An integer with the timeout value in seconds. The default timeout is controlled by a global value.
#[nasl_function(named(dport, sport))]
fn open_priv_sock_tcp(
&self,
context: &Context,
dport: i64,
sport: Option<i64>,
) -> Result<NaslValue, FunctionErrorKind> {
let dport = verify_port(dport)?;

let addr = ipstr2ipaddr(context.target())?;

// TODO: set timeout to global recv timeout when available
let timeout = Duration::from_secs(10);

if let Some(sport) = sport {
let sport = verify_port(sport)?;
self.wait_before_next_probe();
let tcp = TcpConnection::connect_priv(addr, sport, dport, timeout)?;

let fd = self.add(NaslSocket::Tcp(Box::new(tcp)));
return Ok(NaslValue::Number(fd as i64));
}

let mut sport = 1023;

while sport > 0 {
self.wait_before_next_probe();
if let Ok(tcp) = TcpConnection::connect_priv(addr, sport, dport, timeout) {
let fd = self.add(NaslSocket::Tcp(Box::new(tcp)));
return Ok(NaslValue::Number(fd as i64));
}
sport -= 1;
}
Err(FunctionErrorKind::Diagnostic(
format!(
"Unable to open priv socket to {} on any socket from 1-1023",
addr
),
None,
))
}

/// Open a privileged UDP socket to the target host.
/// It takes three named integer arguments:
/// - dport is the destination port
/// - sport is the source port, which may be inferior to 1024. This argument is optional.
/// If it is not set, the function will try to open a socket on any port from 1 to 1023.
#[nasl_function(named(dport, sport))]
fn open_priv_sock_udp(
&self,
context: &Context,
dport: i64,
sport: Option<i64>,
) -> Result<NaslValue, FunctionErrorKind> {
let dport = verify_port(dport)?;

let addr = ipstr2ipaddr(context.target())?;

if let Some(sport) = sport {
let sport = verify_port(sport)?;
let udp = UdpConnection::new_priv(addr, sport, dport)?;

let fd = self.add(NaslSocket::Udp(udp));
return Ok(NaslValue::Number(fd as i64));
}

let mut sport = 1023;

while sport > 0 {
if let Ok(udp) = UdpConnection::new_priv(addr, sport, dport) {
let fd = self.add(NaslSocket::Udp(udp));
return Ok(NaslValue::Number(fd as i64));
}
sport -= 1;
}
Err(FunctionErrorKind::Diagnostic(
format!(
"Unable to open priv socket to {} on any socket from 1-1023",
addr
),
None,
))
}

/// Get the source port of a open socket
#[nasl_function]
fn get_source_port(&self, socket: usize) -> Result<NaslValue, FunctionErrorKind> {
Expand Down Expand Up @@ -573,8 +666,6 @@ impl NaslSockets {
}
}

/// *any* **ftp_log_in**(user: *string*, pass: *string*, socket: *int*);
/// **ftp_log_in** takes three named arguments:
/// - user: is the user name (it has no default value like “anonymous” or “ftp”)
/// - pass: is the password (again, no default value like the user e-mail address)
Expand Down Expand Up @@ -620,7 +711,9 @@ function_set! {
(
(NaslSockets::open_sock_kdc, "open_sock_kdc"),
(NaslSockets::open_sock_tcp, "open_sock_tcp"),
(NaslSockets::open_priv_sock_tcp, "open_priv_sock_tcp"),
(NaslSockets::open_sock_udp, "open_sock_udp"),
(NaslSockets::open_priv_sock_udp, "open_priv_sock_udp"),
(NaslSockets::close, "close"),
(NaslSockets::send, "send"),
(NaslSockets::recv, "recv"),
Expand Down
Loading

0 comments on commit 285ea44

Please sign in to comment.