answer OPTIONS with 404

This commit is contained in:
serxoz 2022-12-05 17:29:58 +01:00
commit 76e73b4058
9 changed files with 606 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

316
Cargo.lock generated Normal file
View File

@ -0,0 +1,316 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bytes"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "libc"
version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "lock_api"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "mio"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys",
]
[[package]]
name = "num_cpus"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
]
[[package]]
name = "pin-project-lite"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "proc-macro2"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
[[package]]
name = "sip-tarpit"
version = "0.1.0"
dependencies = [
"tokio",
]
[[package]]
name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "socket2"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "syn"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tokio"
version = "1.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3"
dependencies = [
"autocfg",
"bytes",
"libc",
"memchr",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"winapi",
]
[[package]]
name = "tokio-macros"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "sip-tarpit"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1", features = ["full"] }

10
README.md Normal file
View File

@ -0,0 +1,10 @@
# SIP tarpit
The idea is that a SIP attacker lost more time while trying to crack this "SIP service".
Could be defined as a slow honeypot...
Initially will be designed against a sipvicious attacker.
## Answer to OPTIONS
This way will be mapped in the network

26
doc/sip-packets.txt Normal file
View File

@ -0,0 +1,26 @@
OPTIONS sip:100@127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.1.1:5061;branch=z9hG4bK-487618168;rport
Max-Forwards: 70
To: "sipvicious"<sip:100@1.1.1.1>
From: "sipvicious"<sip:100@1.1.1.1>;tag=37663030303030313133633401393537303038303638
User-Agent: friendly-scanner
Call-ID: 447615548427934163033914
Contact: sip:100@127.0.1.1:5061
CSeq: 1 OPTIONS
Accept: application/sdp
Content-Length: 0
SIP/2.0 404 Not Found
Via: SIP/2.0/UDP 127.0.1.1:5060;rport=65476;received=185.179.142.180;branch=z9hG4bK-3692480612
Call-ID: 953932568039675157936807
From: "sipvicious" <sip:100@1.1.1.1>;tag=6239623338663563313363370134323538333932373936
To: "sipvicious" <sip:100@1.1.1.1>;tag=z9hG4bK-3692480612
CSeq: 1 OPTIONS
Accept: application/xpidf+xml, application/cpim-pidf+xml, application/dialog-info+xml, application/simple-message-summary, application/pidf+xml, application/pidf+xml, application/dialog-info+xml, application/s
ple-message-summary, application/sdp, message/sipfrag;version=2.0
Allow: OPTIONS, REGISTER, SUBSCRIBE, NOTIFY, PUBLISH, INVITE, ACK, BYE, CANCEL, UPDATE, PRACK, MESSAGE, REFER
Supported: 100rel, timer, replaces, norefersub
Accept-Encoding: identity
Accept-Language: en
Server: Asterisk PBX 18.9.0
Content-Length: 0

96
src/main.rs Normal file
View File

@ -0,0 +1,96 @@
/*
* SIP-tarpit
* Listens on 5060 udp by default
*
*/
pub mod sip;
use std::error::Error;
use std::net::SocketAddr;
use std::{env, io};
use tokio::net::UdpSocket;
use tokio::time::{sleep, Duration};
use crate::sip::options::*;
use crate::sip::not_found::*;
struct Server {
socket: UdpSocket,
buf: Vec<u8>,
to_send: Option<(usize, SocketAddr)>,
}
impl Server {
async fn run(self) -> Result<(), io::Error> {
let Server {
socket,
mut buf,
mut to_send,
} = self;
loop {
// First we check to see if there's a message we need to answer.
// If so then we try to send it back to the original source, waiting
// until it's writable and we're able to do so.
if let Some((size, peer)) = to_send {
// let amt = socket.send_to(&buf[..size], &peer).await?;
// println!("Echoed {}/{} bytes to {}", amt, size, peer);
//
// test type of message received
let msg = String::from_utf8(buf[..size].to_vec()).unwrap();
match msg {
msg if msg.contains("OPTIONS") => {
// esperar - tarpit!
sleep(Duration::from_secs(5)).await;
let options = Options::parse(&msg);
// respondemos con un 404 not found
// o campo via non é como vai... pero ñapa
let not_found = NotFoundPacket {
command: "SIP/2.0 404 Not Found".to_string(),
via: options.via,
call_id: options.call_id,
from: options.from,
to: options.to,
cseq: options.cseq,
accept: Some("application/sdp".to_string()),
allow: Some("OPTIONS, REGISTER, SUBSCRIBE, NOTIFY, PUBLISH, INVITE, ACK, BYE, CANCEL, UPDATE, PRACK, MESSAGE, REFER".to_string()),
supported: Some("100rel, timer, replaces, norefersub".to_string()),
accept_encoding: Some("itentity".to_string()),
accept_language: Some("en".to_string()),
server: Some("Asterisk PBX 18.9.0".to_string()),
content_length: Some(0)
};
let amt = socket.send_to(&not_found.serialize(), &peer).await?;
println!("Sent {}/{} bytes to {}", amt, &not_found.serialize().len(), peer);
},
_ => println!("Packet don't known, yet...")
}
}
// If we're here then `to_send` is `None`, so we take a look for the
// next message we're going to answer.
to_send = Some(socket.recv_from(&mut buf).await?);
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let addr = env::args()
.nth(1)
.unwrap_or_else(|| "127.0.0.1:5063".to_string());
let socket = UdpSocket::bind(&addr).await?;
println!("Listening on: {}", socket.local_addr()?);
let server = Server {
socket,
buf: vec![0; 1024],
to_send: None,
};
// This starts the server task.
server.run().await?;
Ok(())
}

2
src/sip/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod options;
pub mod not_found;

79
src/sip/not_found.rs Normal file
View File

@ -0,0 +1,79 @@
/*
SIP/2.0 404 Not Found
Via: SIP/2.0/UDP 127.0.1.1:5060;rport=65476;received=185.179.142.180;branch=z9hG4bK-3692480612
Call-ID: 953932568039675157936807
From: "sipvicious" <sip:100@1.1.1.1>;tag=6239623338663563313363370134323538333932373936
To: "sipvicious" <sip:100@1.1.1.1>;tag=z9hG4bK-3692480612
CSeq: 1 OPTIONS
Accept: application/xpidf+xml, application/cpim-pidf+xml, application/dialog-info+xml, application/simple-message-summary, application/pidf+xml, application/pidf+xml, application/dialog-info+xml, application/s
ple-message-summary, application/sdp, message/sipfrag;version=2.0
Allow: OPTIONS, REGISTER, SUBSCRIBE, NOTIFY, PUBLISH, INVITE, ACK, BYE, CANCEL, UPDATE, PRACK, MESSAGE, REFER
Supported: 100rel, timer, replaces, norefersub
Accept-Encoding: identity
Accept-Language: en
Server: Asterisk PBX 18.9.0
Content-Length: 0
*/
#[derive(Debug)]
pub struct NotFoundPacket {
pub command: String, // SIP/2.0 404 Not Found
pub via: String, // SIP/2.0/UDP 127.0.1.1:5061;branch=z9hG4bK-487618168;rport
pub call_id: Option<String>, // Call-ID: 447615548427934163033914
pub from: String, // "sipvicious"<sip:100@1.1.1.1>;tag=37663030303030313133633401393537303038303638
pub to: String, // "sipvicious"<sip:100@1.1.1.1>
pub cseq: String, // 1 OPTIONS
pub accept: Option<String>, // application/sdp
pub allow: Option<String>, // OPTIONS, REGISTER, SUBSCRIBE, NOTIFY, PUBLISH, INVITE...
pub supported: Option<String>, // 100rel, timer, replaces, norefersub
pub accept_encoding: Option<String>, // identity
pub accept_language: Option<String>, // en
pub server: Option<String>, // Asterisk PBX 18.9.0
pub content_length: Option<i32> // 0
}
impl NotFoundPacket {
pub fn serialize(&self) -> Vec<u8> {
let mut preout = String::new();
preout.push_str(&self.command);
preout.push_str("\n");
preout.push_str("Via: ");
preout.push_str(&self.via);
preout.push_str("\n");
preout.push_str("Call-ID: ");
preout.push_str(&self.call_id.as_ref().unwrap());
preout.push_str("\n");
preout.push_str("From: ");
preout.push_str(&self.from);
preout.push_str("\n");
preout.push_str("To: ");
preout.push_str(&self.to);
preout.push_str("\n");
preout.push_str("CSeq: ");
preout.push_str(&self.cseq);
preout.push_str("\n");
preout.push_str("Accept: ");
preout.push_str(&self.accept.as_ref().unwrap());
preout.push_str("\n");
preout.push_str("Allow: ");
preout.push_str(&self.allow.as_ref().unwrap());
preout.push_str("\n");
preout.push_str("Supported: ");
preout.push_str(&self.supported.as_ref().unwrap());
preout.push_str("\n");
preout.push_str("Accept-Encoding: ");
preout.push_str(&self.accept_encoding.as_ref().unwrap());
preout.push_str("\n");
preout.push_str("Accept-Language: ");
preout.push_str(&self.accept_language.as_ref().unwrap());
preout.push_str("\n");
preout.push_str("Server: ");
preout.push_str(&self.server.as_ref().unwrap());
preout.push_str("\n");
preout.push_str("Content-Length: ");
preout.push_str(&self.content_length.unwrap().to_string());
preout.push_str("\n");
preout.push_str("\n");
// println!("{}", preout);
preout.as_bytes().to_vec()
}
}

67
src/sip/options.rs Normal file
View File

@ -0,0 +1,67 @@
// Mandatory: To, From, CSeq, Call-ID, Max-Forwards, and Via;
//
#[derive(Debug)]
pub struct Options {
pub command: String, // OPTIONS sip:100@127.0.0.1 SIP/2.0
pub via: String, // SIP/2.0/UDP 127.0.1.1:5061;branch=z9hG4bK-487618168;rport
pub max_forwards: i32, // 70
pub to: String, // "sipvicious"<sip:100@1.1.1.1>
pub from: String, // "sipvicious"<sip:100@1.1.1.1>;tag=37663030303030313133633401393537303038303638
pub user_agent: Option<String>, // friendly-scanner
pub call_id: Option<String>, // Call-ID: 447615548427934163033914
pub contact: Option<String>, // sip:100@127.0.1.1:5061
pub cseq: String, // 1 OPTIONS
pub accept: Option<String>, // application/sdp
pub content_length: Option<i32> // 0
}
impl Options {
pub fn new() -> Options {
Options {
command: "OPTIONS".to_string(),
via: String::new(),
max_forwards: 0,
to: String::new(),
from: String::new(),
user_agent: Some(String::new()),
call_id: Some(String::new()),
contact: Some(String::new()),
cseq: String::new(),
accept: Some(String::new()),
content_length: Some(0,)
}
}
pub fn parse(msg: &String) -> Options {
let mut packet = Options::new();
for line in msg.lines() {
if line.len() > 0 {
// split polos dous puntos e comprobar
// si a parte 0 conten via asignar a via e así
let parts = line.split(":").collect::<Vec<&str>>();
let header = parts[0].trim();
let mut content = "".to_owned();
for p in &parts[1..]{
content.push_str(p.trim())
}
match header {
"OPTIONS sip" => packet.command = format!("{}{}", header, content),
"Via" => packet.via = content.to_string(),
"Max-Forwards" => packet.max_forwards = content.parse::<i32>().unwrap(),
"To" => packet.to = content.to_string(),
"From" => packet.from = content.to_string(),
"User-Agent" => packet.user_agent = Some(content.to_string()),
"Call-ID" => packet.call_id = Some(content.to_string()),
"Contact" => packet.contact = Some(content.to_string()),
"CSeq" => packet.cseq = content.to_string(),
"Accept" => packet.accept = Some(content.to_string()),
"Content-Length" => packet.content_length = Some(content.parse::<i32>().unwrap()),
_ => println!("---> {:?} no contemplada!", header),
}
}
}
// println!("{:?}",packet);
packet
}
}