-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MySQL protocol parser v1 #11800
MySQL protocol parser v1 #11800
Conversation
@glongo I think you mentioned you had some WIP code as well. Care to have a look at this? |
NOTE: This PR may contain new authors. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #11800 +/- ##
=========================================
Coverage ? 78.80%
=========================================
Files ? 923
Lines ? 251982
Branches ? 0
=========================================
Hits ? 198566
Misses ? 53416
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the TBD list ;)
- update etc/schema.json
- update commit messages to contain Ticket number in the commit body (
Task #3446
) - update your git author to follow the format
FirstName LastName
:P
nit: in the commit messages, you can remove the rust/
portion
Yes sure. |
ea503dd
to
da79f32
Compare
5083bc9
to
3fe510b
Compare
I have fixed, please check again, thx. |
3fe510b
to
becd843
Compare
src/output-json-mysql.c
Outdated
return TM_ECODE_FAILED; | ||
} | ||
|
||
if (!rs_mysql_logger(txptr, thread->mysqllog_ctx->flags, jb)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should not need this file now
rs_mysql_logger
(which should rather be named SCMysqlLogger
) cf EveJsonSimpleTxLogFunc
in output.c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, please check again.Why keep simple logger only?
Are you planning on adding keywords as well ? |
rust/src/mysql/logger.rs
Outdated
|
||
fn log_mysql(tx: &MysqlTransaction, _flags: u32, js: &mut JsonBuilder) -> Result<(), JsonError> { | ||
js.open_object("mysql")?; | ||
js.set_uint("tx_id", tx.tx_id)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it meaningful to log the tx id ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, all of fields are based on my project, if you have any idea in logger, please comment, thx.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, please check again.
rust/src/mysql/logger.rs
Outdated
js.set_bool("tls", false)?; | ||
} | ||
|
||
if tx.command.is_some() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if let Some(c) = tx.command
;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, please check again.
rust/src/mysql/logger.rs
Outdated
Ok(()) | ||
} | ||
|
||
fn log_mysql_alert( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is different with log_mysql
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for my project's demand.I will remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, please check again.
|
||
client_flags: u32, | ||
version: Option<String>, | ||
tls: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you handle protocol change ? (like STARTTLS
does in SMTP)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rust/src/mysql/mysql.rs
Outdated
|
||
/// Probe for a valid mysql message | ||
pub fn probe(input: &[u8]) -> bool { | ||
if parse_packet_header(input).is_ok() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can not it say "not enough data to know" ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like parse_packet_header
accepts pretty much everything
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Probe for a valid mysql message
pub fn probe(i: &[u8]) -> IResult<&[u8], ()> {
let (i, _) = parse_packet_header(i)?;
Ok((i, ()))
}
Did you mean this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I mean that the probing parser is likely not strict enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have another probe function rs_mysql_probing_tc
and rs_mysql_probing_ts
for real probing
rust/src/mysql/mysql.rs
Outdated
|
||
/// Get the mysql query | ||
#[no_mangle] | ||
pub unsafe extern "C" fn SCMysqlTxGetCommandName( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unused now...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, please check again.
get_state_data: rs_mysql_get_state_data, | ||
apply_tx_config: None, | ||
flags: APP_LAYER_PARSER_OPT_ACCEPT_GAPS, | ||
get_frame_id_by_name: None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you planning on adding frames support ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this work already.
I left some comments and questions to get deeper
} | ||
} | ||
|
||
pub fn parse_request(&mut self, flow: *const Flow, i: &[u8]) -> AppLayerResult { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is a corner case to handle here: if a payload length is set to ff ff ff
, it means that it is fragmented and the payload should be reassembled before of being parsed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, i will fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When i implement this, i found some problems in rust lifetime that i can't reassemble, do you have any advice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have implemented a low performance version, please check.
) -> IResult<&[u8], MysqlRequest> { | ||
let (i, header) = parse_packet_header(i)?; | ||
let (i, command_code) = be_u8(i)?; | ||
match command_code { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be rewritten as:
let (i, req) = match command_code {
0x01 => (i, MysqlRequest {
command_code,
command: MysqlCommand::Quit,
})
...
}
Ok((i, req))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, please check again.
let (i, _tag) = verify(be_u8, |&x| x == 0xfe)(i)?; | ||
let (i, warnings) = le_u16(i)?; | ||
let (i, status_flags) = le_u16(i)?; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warnings
and status_flags
can be parsed only if the following condition is true:
if capabilities & CLIENT_PROTOCOL_41 != 0
The flags parsed during the handshake phase should be passed here as a parameter to check this condition.
Reference: https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_eof_packet.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When i parse handshake response, i have checked this.
rust/src/mysql/parser.rs
Outdated
)) | ||
} | ||
|
||
fn parse_response_ok(i: &[u8], length: u32) -> IResult<&[u8], MysqlResponse> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned above, some fields depend on flags, and certain conditions should be checked before parsing them.
Reference: https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_ok_packet.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When i parse ok response, i just take the fields what I need.
As mentioned before, when i parse handshake response, i have checked capabilities should contain CLIENT_PROTOCOL_41.
let (i, error_code) = le_u16(i)?; | ||
let (i, _) = take(6_u32)(i)?; | ||
// sql state maker & sql state | ||
let (i, _) = take(6_u32)(i)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sql state marker and state are available only if capabilities & CLIENT_PROTOCOL_41
is true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When i parse handshake response, i have checked this.
84f0700
to
512c197
Compare
No, all of fields are based on my project, if you have any idea in logger, please comment, thx. |
512c197
to
93124a1
Compare
The keywords are for making detection easier and more efficient, not for the logging part. Thanks for incorporating feedback :) I'll mark this PR as a draft, as there are still a lot of moving parts. Once you consider you've reached something more stable, do submit another PR version, with SV tests, as those work well not only for our CI checks testing but also for showcasing the EVE output. |
Ok, I will move my project's detection keywords here, and do more tests. |
Continued in #11842 if I am not mistaken |
Make sure these boxes are signed before submitting your Pull Request -- thank you.
https://docs.suricata.io/en/latest/devguide/contributing/contribution-process.html
https://suricata.io/about/contribution-agreement/ (note: this is only required once)
Link to ticket: https://redmine.openinfosecfoundation.org/issues/3446
Describe changes:
This is a WIP patchset that implements an application layer for MySQL protocol, many features are not supported.
TBD:
Support Protocol:Handshake V9
Support Mysql Protocol 32
Support Protocol:AuthSwitchRequest
Support Protocol:AuthSwitchResponse
Support Protocol:AuthMoreData
Support Protocol:AuthNextFactor
Support Compression
Add documentation
Add SV tests
Fix CI