-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
app-layer: websockets protocol support
Ticket: 2695
- Loading branch information
1 parent
704e34f
commit 1b1fc8b
Showing
25 changed files
with
1,296 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
WebSocket Keywords | ||
================== | ||
|
||
websocket.payload | ||
----------------- | ||
|
||
A sticky buffer on the unmasked payload, | ||
limited by suricata.yaml config value ``websocket.max-payload-size``. | ||
|
||
Examples:: | ||
|
||
websocket.payload; pcre:"/^123[0-9]*/"; | ||
websocket.payload content:"swordfish"; | ||
|
||
``websocket.payload`` is a 'sticky buffer' and can be used as ``fast_pattern``. | ||
|
||
websocket.flags | ||
--------------- | ||
|
||
Matches on the websocket flags. | ||
It uses a 8-bit unsigned integer as value. | ||
Only the four upper bits are used. | ||
|
||
The value can also be a list of strings (comma-separated), | ||
where each string is the name of a specific bit like `fin` and `comp`, | ||
and can be prefixed by `!` for negation. | ||
|
||
Examples:: | ||
|
||
websocket.flags:128; | ||
websocket.flags:&0x40=0x40; | ||
websocket.flags:fin,!comp; | ||
|
||
websocket.mask | ||
-------------- | ||
|
||
Matches on the websocket mask if any. | ||
It uses a 32-bit unsigned integer as value (big-endian). | ||
|
||
Examples:: | ||
|
||
websocket.mask:123456; | ||
websocket.mask:>0; | ||
|
||
websocket.opcode | ||
---------------- | ||
|
||
Matches on the websocket opcode. | ||
It uses a 8-bit unsigned integer as value. | ||
Only 16 values are relevant. | ||
It can also be specified by text from the enumeration | ||
|
||
Examples:: | ||
|
||
websocket.opcode:1; | ||
websocket.opcode:>8; | ||
websocket.opcode:ping; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# WebSocket app-layer event rules. | ||
# | ||
# These SIDs fall in the 2235000+ range. See: | ||
# http://doc.emergingthreats.net/bin/view/Main/SidAllocation and | ||
# https://redmine.openinfosecfoundation.org/projects/suricata/wiki/AppLayer | ||
|
||
alert websocket any any -> any any (msg:"SURICATA Websocket skipped end of payload"; app-layer-event:websocket.skip_end_of_payload; classtype:protocol-command-decode; sid:2235000; rev:1;) | ||
alert websocket any any -> any any (msg:"SURICATA Websocket reassembly limit reached"; app-layer-event:websocket.reassembly_limit_reached; classtype:protocol-command-decode; sid:2235001; rev:1;) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
/* Copyright (C) 2023 Open Information Security Foundation | ||
* | ||
* You can copy, redistribute or modify this Program under the terms of | ||
* the GNU General Public License version 2 as published by the Free | ||
* Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* version 2 along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
* 02110-1301, USA. | ||
*/ | ||
|
||
use super::websocket::WebSocketTransaction; | ||
use crate::detect::uint::{detect_parse_uint, detect_parse_uint_enum, DetectUintData, DetectUintMode}; | ||
use crate::websocket::parser::WebSocketOpcode; | ||
|
||
use nom7::branch::alt; | ||
use nom7::bytes::complete::{is_a, tag}; | ||
use nom7::combinator::{opt, value}; | ||
use nom7::multi::many1; | ||
use nom7::IResult; | ||
|
||
use std::ffi::CStr; | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn SCWebSocketGetOpcode(tx: &mut WebSocketTransaction) -> u8 { | ||
return tx.pdu.opcode; | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn SCWebSocketGetFlags(tx: &mut WebSocketTransaction) -> u8 { | ||
return tx.pdu.flags; | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn SCWebSocketGetPayload( | ||
tx: &WebSocketTransaction, buffer: *mut *const u8, buffer_len: *mut u32, | ||
) -> bool { | ||
*buffer = tx.pdu.payload.as_ptr(); | ||
*buffer_len = tx.pdu.payload.len() as u32; | ||
return true; | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn SCWebSocketGetMask( | ||
tx: &mut WebSocketTransaction, value: *mut u32, | ||
) -> bool { | ||
if let Some(xorkey) = tx.pdu.mask { | ||
*value = xorkey; | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn SCWebSocketParseOpcode( | ||
ustr: *const std::os::raw::c_char, | ||
) -> *mut DetectUintData<u8> { | ||
let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe | ||
if let Ok(s) = ft_name.to_str() { | ||
if let Some(ctx) = detect_parse_uint_enum::<u8, WebSocketOpcode>(s) { | ||
let boxed = Box::new(ctx); | ||
return Box::into_raw(boxed) as *mut _; | ||
} | ||
} | ||
return std::ptr::null_mut(); | ||
} | ||
|
||
struct WebSocketFlag { | ||
neg: bool, | ||
value: u8, | ||
} | ||
|
||
fn parse_flag_list_item(s: &str) -> IResult<&str, WebSocketFlag> { | ||
let (s, _) = opt(is_a(" "))(s)?; | ||
let (s, neg) = opt(tag("!"))(s)?; | ||
let neg = neg.is_some(); | ||
let (s, value) = alt((value(0x80, tag("fin")), value(0x40, tag("comp"))))(s)?; | ||
let (s, _) = opt(is_a(" ,"))(s)?; | ||
Ok((s, WebSocketFlag { neg, value })) | ||
} | ||
|
||
fn parse_flag_list(s: &str) -> IResult<&str, Vec<WebSocketFlag>> { | ||
return many1(parse_flag_list_item)(s); | ||
} | ||
|
||
fn parse_flags(s: &str) -> Option<DetectUintData<u8>> { | ||
// try first numerical value | ||
if let Ok((_, ctx)) = detect_parse_uint::<u8>(s) { | ||
return Some(ctx); | ||
} | ||
// otherwise, try strings for bitmask | ||
if let Ok((_, l)) = parse_flag_list(s) { | ||
let mut arg1 = 0; | ||
let mut arg2 = 0; | ||
for elem in l.iter() { | ||
if elem.value & arg1 != 0 { | ||
SCLogWarning!("Repeated bitflag for websocket.flags"); | ||
return None; | ||
} | ||
arg1 |= elem.value; | ||
if !elem.neg { | ||
arg2 |= elem.value; | ||
} | ||
} | ||
let ctx = DetectUintData::<u8> { | ||
arg1, | ||
arg2, | ||
mode: DetectUintMode::DetectUintModeBitmask, | ||
}; | ||
return Some(ctx); | ||
} | ||
return None; | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn SCWebSocketParseFlags( | ||
ustr: *const std::os::raw::c_char, | ||
) -> *mut DetectUintData<u8> { | ||
let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe | ||
if let Ok(s) = ft_name.to_str() { | ||
if let Some(ctx) = parse_flags(s) { | ||
let boxed = Box::new(ctx); | ||
return Box::into_raw(boxed) as *mut _; | ||
} | ||
} | ||
return std::ptr::null_mut(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* Copyright (C) 2023 Open Information Security Foundation | ||
* | ||
* You can copy, redistribute or modify this Program under the terms of | ||
* the GNU General Public License version 2 as published by the Free | ||
* Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* version 2 along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
* 02110-1301, USA. | ||
*/ | ||
|
||
use super::parser::WebSocketOpcode; | ||
use super::websocket::WebSocketTransaction; | ||
use crate::detect::Enum; | ||
use crate::jsonbuilder::{JsonBuilder, JsonError}; | ||
use std; | ||
|
||
fn log_websocket(tx: &WebSocketTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> { | ||
js.open_object("websocket")?; | ||
js.set_bool("fin", tx.pdu.fin)?; | ||
if let Some(xorkey) = tx.pdu.mask { | ||
js.set_uint("mask", xorkey.into())?; | ||
} | ||
if let Some(opcode) = WebSocketOpcode::from_u(tx.pdu.opcode) { | ||
js.set_string("opcode", opcode.to_str())?; | ||
} else { | ||
js.set_string("opcode", &format!("unknown-{}", tx.pdu.opcode))?; | ||
} | ||
js.close()?; | ||
Ok(()) | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn rs_websocket_logger_log( | ||
tx: *mut std::os::raw::c_void, js: &mut JsonBuilder, | ||
) -> bool { | ||
let tx = cast_pointer!(tx, WebSocketTransaction); | ||
log_websocket(tx, js).is_ok() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* Copyright (C) 2023 Open Information Security Foundation | ||
* | ||
* You can copy, redistribute or modify this Program under the terms of | ||
* the GNU General Public License version 2 as published by the Free | ||
* Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* version 2 along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
* 02110-1301, USA. | ||
*/ | ||
|
||
//! Application layer websocket parser and logger module. | ||
|
||
pub mod detect; | ||
pub mod logger; | ||
mod parser; | ||
pub mod websocket; |
Oops, something went wrong.