Skip to content

Commit

Permalink
new: tcp.ports will now get tls certificate information
Browse files Browse the repository at this point in the history
  • Loading branch information
evilsocket committed Jul 22, 2024
1 parent 79eb244 commit 92eee9f
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 13 deletions.
121 changes: 116 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ uuid = "1.10.0"
nix = { version = "0.29.0", features = ["signal"] }
strip-ansi-escapes = "0.2.0"
actix-cors = "0.7.0"
x509-parser = "0.16.0"

[dev-dependencies]
tempfile = "3.8.0"
Expand Down
51 changes: 47 additions & 4 deletions src/plugins/tcp_ports/grabbers/http.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use std::time::Duration;

use crate::{plugins::tcp_ports::options, utils::net::StreamLike};
use crate::{
plugins::tcp_ports::options,
utils::net::{upgrade_tcp_stream_to_tls, StreamLike},
};
use lazy_static::lazy_static;
use regex::Regex;
use x509_parser::prelude::{FromDer, X509Certificate};

use super::Banner;

Expand Down Expand Up @@ -63,7 +67,48 @@ pub(crate) async fn http_grabber(
port
);

drop(stream); // close original connection
// if ssl, upgrade stream to get certificate information
if ssl {
if let Ok(tls) = upgrade_tcp_stream_to_tls(stream, timeout).await {
if let Ok(Some(cert)) = tls.peer_certificate() {
if let Ok(der) = cert.to_der() {
if let Ok((_, cert)) = X509Certificate::from_der(&der) {
banner.insert("certificate.serial".to_owned(), cert.raw_serial_as_string());
banner.insert("certificate.subject".to_owned(), cert.subject().to_string());
banner.insert("certificate.issuer".to_owned(), cert.issuer().to_string());

let validity = cert.validity();
banner.insert(
"certificate.validity.from".to_owned(),
validity.not_before.to_string(),
);
banner.insert(
"certificate.validity.to".to_owned(),
validity.not_after.to_string(),
);

if let Ok(Some(alt_names)) = cert.subject_alternative_name() {
banner.insert(
"certificate.names".to_owned(),
alt_names
.value
.general_names
.iter()
.map(|n| n.to_string())
.collect::<Vec<String>>()
.join(", "),
);
}
}
}
}

// close original connection
drop(tls);
}
} else {
drop(stream); // close original connection
}

log::debug!("grabbing http banner for {} ...", &url);

Expand Down Expand Up @@ -91,8 +136,6 @@ pub(crate) async fn http_grabber(
.await;

if let Ok(resp) = resp {
// TODO: find a way to collect certificate information if ssl

let headers_of_interest: Vec<&str> = opts
.tcp_ports_http_headers
.split(',')
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/tcp_ports/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ impl Plugin for TcpPortScanner {
for (key, val) in banner {
if key == "proto" || key == "protocol" {
data.push(("protocol".to_owned(), val));
} else if key.starts_with("certificate.") {
data.push((key, val));
} else {
data.push((format!("banner.{}", key), val));
}
Expand Down
17 changes: 13 additions & 4 deletions src/utils/net.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::time::Duration;

use async_native_tls::TlsStream;

use crate::session::Error;

pub(crate) trait StreamLike:
Expand All @@ -12,18 +14,25 @@ impl StreamLike for tokio::net::TcpStream {}
impl StreamLike for async_native_tls::TlsStream<tokio::net::TcpStream> {}
impl StreamLike for async_native_tls::TlsStream<Box<dyn StreamLike>> {}

pub(crate) async fn upgrade_tcp_stream_to_ssl(
pub(crate) async fn upgrade_tcp_stream_to_tls(
tcp_stream: Box<dyn StreamLike>,
timeout: Duration,
) -> Result<Box<dyn StreamLike>, Error> {
) -> Result<TlsStream<Box<dyn StreamLike>>, Error> {
let tls = async_native_tls::TlsConnector::new()
.danger_accept_invalid_certs(true)
.danger_accept_invalid_hostnames(true);

let tls_stream = tokio::time::timeout(timeout, tls.connect("", tcp_stream))
tokio::time::timeout(timeout, tls.connect("", tcp_stream))
.await
.map_err(|e| e.to_string())?
.map_err(|e| e.to_string())?;
.map_err(|e| e.to_string())
}

pub(crate) async fn upgrade_tcp_stream_to_ssl(
tcp_stream: Box<dyn StreamLike>,
timeout: Duration,
) -> Result<Box<dyn StreamLike>, Error> {
let tls_stream = upgrade_tcp_stream_to_tls(tcp_stream, timeout).await?;

Ok(Box::new(tls_stream))
}
Expand Down

0 comments on commit 92eee9f

Please sign in to comment.