Skip to content

Commit fbb5559

Browse files
authored
Merge pull request #68 from kkrypt0nn/main
feat: Add IRC server password authentication
2 parents 8d736ba + c3ed849 commit fbb5559

File tree

8 files changed

+131
-1
lines changed

8 files changed

+131
-1
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ default = [
109109
"smtp",
110110
"pop3",
111111
"imap",
112+
"irc",
112113
"telnet",
113114
"ldap",
114115
"kerberos",
@@ -135,6 +136,7 @@ ftp = ["dep:async_ftp"]
135136
smtp = ["dep:async-smtp"]
136137
pop3 = ["dep:async-pop"]
137138
imap = ["dep:async-imap"]
139+
irc = []
138140
telnet = ["dep:mini-telnet"]
139141
ldap = ["dep:ldap3"]
140142
kerberos = [

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ For the building instructions, usage and the complete list of options [check the
2222

2323
## Supported Protocols/Features:
2424

25-
AMQP (ActiveMQ, RabbitMQ, Qpid, JORAM and Solace), Cassandra/ScyllaDB, DNS subdomain enumeration, FTP, HTTP (basic authentication, NTLMv1, NTLMv2, multipart form, custom requests with CSRF support, files/folders enumeration, virtual host enumeration), IMAP, Kerberos pre-authentication and user enumeration, LDAP, MongoDB, MQTT, Microsoft SQL, MySQL, Oracle, PostgreSQL, POP3, RDP, Redis, Samba, SSH / SFTP, SMTP, Socks5, STOMP (ActiveMQ, RabbitMQ, HornetQ and OpenMQ), TCP and UDP port scanning with banner grabbing, Telnet, VNC.
25+
AMQP (ActiveMQ, RabbitMQ, Qpid, JORAM and Solace), Cassandra/ScyllaDB, DNS subdomain enumeration, FTP, HTTP (basic authentication, NTLMv1, NTLMv2, multipart form, custom requests with CSRF support, files/folders enumeration, virtual host enumeration), IMAP, IRC, Kerberos pre-authentication and user enumeration, LDAP, MongoDB, MQTT, Microsoft SQL, MySQL, Oracle, PostgreSQL, POP3, RDP, Redis, Samba, SSH / SFTP, SMTP, Socks5, STOMP (ActiveMQ, RabbitMQ, HornetQ and OpenMQ), TCP and UDP port scanning with banner grabbing, Telnet, VNC.
2626

2727
## Benchmark
2828

src/options.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,7 @@ pub(crate) struct Options {
149149
#[cfg(feature = "port_scanner")]
150150
#[clap(flatten, next_help_heading = "PORT SCANNER")]
151151
pub port_scanner: crate::plugins::port_scanner::options::Options,
152+
#[cfg(feature = "irc")]
153+
#[clap(flatten, next_help_heading = "IRC")]
154+
pub irc: crate::plugins::irc::options::Options,
152155
}

src/plugins/irc/mod.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use rand::Rng;
2+
use std::time::Duration;
3+
use tokio::io::{AsyncReadExt, AsyncWriteExt};
4+
5+
use async_trait::async_trait;
6+
7+
use crate::session::{Error, Loot};
8+
use crate::utils;
9+
use crate::Options;
10+
use crate::Plugin;
11+
12+
pub(crate) mod options;
13+
14+
use crate::creds::Credentials;
15+
16+
super::manager::register_plugin! {
17+
"irc" => IRC::new()
18+
}
19+
20+
#[derive(Clone)]
21+
pub(crate) struct IRC {
22+
tls: bool,
23+
}
24+
25+
impl IRC {
26+
pub fn new() -> Self {
27+
IRC { tls: false }
28+
}
29+
30+
fn generate_random_username() -> String {
31+
let mut rng = rand::thread_rng();
32+
let length = rng.gen_range(5..=9);
33+
(0..length)
34+
.map(|_| {
35+
let range = if rng.gen_bool(0.5) {
36+
b'a'..=b'z'
37+
} else {
38+
b'A'..=b'Z'
39+
};
40+
rng.gen_range(range) as char
41+
})
42+
.collect()
43+
}
44+
}
45+
46+
#[async_trait]
47+
impl Plugin for IRC {
48+
fn description(&self) -> &'static str {
49+
"IRC server password authentication."
50+
}
51+
52+
fn setup(&mut self, opts: &Options) -> Result<(), Error> {
53+
self.tls = opts.irc.irc_tls;
54+
Ok(())
55+
}
56+
57+
async fn attempt(
58+
&self,
59+
creds: &Credentials,
60+
timeout: Duration,
61+
) -> Result<Option<Vec<Loot>>, Error> {
62+
let address =
63+
utils::parse_target_address(&creds.target, if self.tls { 6697 } else { 6667 })?;
64+
65+
let mut stream = crate::utils::net::async_tcp_stream(&address, timeout, self.tls).await?;
66+
67+
let username = IRC::generate_random_username();
68+
stream
69+
.write_all(
70+
format!(
71+
"NICK {}\r\nUSER {} 0 * :{}\r\nPASS {}\r\n",
72+
username, username, username, creds.password
73+
)
74+
.as_bytes(),
75+
)
76+
.await
77+
.map_err(|e| e.to_string())?;
78+
79+
let mut buffer = vec![0; 1024];
80+
let mut accumulated_data = Vec::new();
81+
loop {
82+
let bytes_read = stream.read(&mut buffer).await.map_err(|e| e.to_string())?;
83+
if bytes_read == 0 {
84+
return Ok(None);
85+
}
86+
accumulated_data.extend_from_slice(&buffer[..bytes_read]);
87+
let response = String::from_utf8_lossy(&accumulated_data);
88+
if response.contains(" 001 ") && response.contains("Welcome") {
89+
return Ok(Some(vec![Loot::new(
90+
"irc",
91+
&address,
92+
[("password".to_owned(), creds.password.to_owned())],
93+
)]));
94+
}
95+
}
96+
}
97+
}

src/plugins/irc/options.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use clap::Parser;
2+
use serde::{Deserialize, Serialize};
3+
4+
#[derive(Parser, Debug, Serialize, Deserialize, Clone, Default)]
5+
#[group(skip)]
6+
pub(crate) struct Options {
7+
#[clap(long, default_value_t = false)]
8+
/// Use TLS for IRC.
9+
pub irc_tls: bool,
10+
}

src/plugins/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ plug! {
3636
pub(crate) http;
3737
#[cfg(feature = "imap")]
3838
imap;
39+
#[cfg(feature = "irc")]
40+
pub(crate) irc;
3941
#[cfg(feature = "kerberos")]
4042
pub(crate) kerberos;
4143
#[cfg(feature = "ldap")]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<connect allow="*" password="test12345">
2+
3+
<bind address="*" port="6667" type="clients">
4+
<bind address="*" port="6697" type="clients" ssl="ssl">
5+
6+
<module name="ssl_gnutls">
7+
<sslprofile name="ssl"
8+
provider="gnutls"
9+
certfile="/inspircd/conf/cert.pem"
10+
keyfile="/inspircd/conf/key.pem"
11+
dhfile="/inspircd/conf/dhparams.pem"
12+
priority="NORMAL:-MD5">

test-servers/irc.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
docker run -p 6667:6667 \
2+
-p 6697:6697 \
3+
-v ./inspircd.config:/inspircd/conf/ \
4+
inspircd/inspircd-docker

0 commit comments

Comments
 (0)