-
Notifications
You must be signed in to change notification settings - Fork 1.7k
dcerpc: mimic gap behavior for invalid data #14805
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -762,21 +762,20 @@ impl DCERPCState { | |
| } | ||
| } | ||
|
|
||
| pub fn handle_input_data(&mut self, stream_slice: StreamSlice, direction: Direction) -> AppLayerResult { | ||
| let retval; | ||
| let mut cur_i = stream_slice.as_slice(); | ||
| let mut consumed = 0u32; | ||
| let mut rem = cur_i.len() as u32; | ||
| fn handle_gap (&mut self, i: &[u8], direction: Direction, mimic: bool) -> (u32, i8) { | ||
| let mut consumed; | ||
|
|
||
| if !mimic && ((!self.ts_gap && !self.tc_gap) || ((self.ts_gap && direction == Direction::ToClient) || (self.tc_gap && direction == Direction::ToServer))) { | ||
| return (0, 0); | ||
| } | ||
| // Skip the record since this means that its in the middle of a known length record | ||
| if (self.ts_gap && direction == Direction::ToServer) || (self.tc_gap && direction == Direction::ToClient) { | ||
| SCLogDebug!("Trying to catch up after GAP (input {})", cur_i.len()); | ||
| match self.search_dcerpc_record(cur_i) { | ||
| Ok((_, pg)) => { | ||
| SCLogDebug!("DCERPC record found"); | ||
| let offset = cur_i.len() - pg.len(); | ||
| cur_i = &cur_i[offset..]; | ||
| consumed = offset as u32; | ||
| SCLogDebug!("Trying to catch up after GAP (input {})", i.len()); | ||
| match self.search_dcerpc_record(i) { | ||
| Ok((_, pg)) => { | ||
| SCLogDebug!("DCERPC record found"); | ||
| let offset = i.len() - pg.len(); | ||
| consumed = offset as u32; | ||
| if !mimic { | ||
| match direction { | ||
| Direction::ToServer => { | ||
| self.ts_gap = false; | ||
|
|
@@ -785,20 +784,36 @@ impl DCERPCState { | |
| self.tc_gap = false; | ||
| } | ||
| } | ||
| }, | ||
| _ => { | ||
| consumed = cur_i.len() as u32; | ||
| // At least 2 bytes are required to know if a new record is beginning | ||
| if consumed < 2 { | ||
| consumed = 0; | ||
| } else { | ||
| consumed -= 1; | ||
| } | ||
| SCLogDebug!("DCERPC record NOT found"); | ||
| return AppLayerResult::incomplete(consumed, 2); | ||
| }, | ||
| } | ||
| } | ||
| }, | ||
| _ => { | ||
| consumed = i.len() as u32; | ||
| // At least 2 bytes are required to know if a new record is beginning | ||
| if consumed < 2 { | ||
| consumed = 0; | ||
| } else { | ||
| consumed -= 1; | ||
| } | ||
| SCLogDebug!("DCERPC record NOT found"); | ||
| return (consumed, -1); | ||
| }, | ||
| } | ||
|
|
||
| (consumed, 0) | ||
| } | ||
|
|
||
| pub fn handle_input_data(&mut self, stream_slice: StreamSlice, direction: Direction) -> AppLayerResult { | ||
| let retval; | ||
| let mut cur_i = stream_slice.as_slice(); | ||
| let mut rem = cur_i.len() as u32; | ||
|
|
||
| SCLogDebug!("ts_gap: {:?}; direction: {:?}; tc_gap: {:?}", self.ts_gap, direction, self.tc_gap); | ||
| let (nb, ret) = self.handle_gap(cur_i, direction, false /* handling the actual gap */); | ||
| let mut consumed = nb; | ||
| if ret == -1 { | ||
| return AppLayerResult::incomplete(consumed, 2); | ||
| } | ||
| cur_i = &cur_i[consumed as usize..]; | ||
| rem -= consumed; | ||
|
|
||
| let mut flow = std::ptr::null_mut(); | ||
|
|
@@ -817,7 +832,11 @@ impl DCERPCState { | |
| header.rpc_vers, | ||
| header.rpc_vers_minor | ||
| ); | ||
| return AppLayerResult::err(); | ||
| SCLogDebug!("mimicing gap for invalid header"); | ||
| let (nb, _ret) = self.handle_gap(cur_i, direction, true /* mimicing a gap */); | ||
| consumed += nb; | ||
| /* no need to update rem/cur_i as it won't be used anymore */ | ||
| return AppLayerResult::incomplete(consumed, rem - consumed); | ||
| } | ||
| header | ||
| } | ||
|
|
@@ -859,10 +878,10 @@ impl DCERPCState { | |
|
|
||
| let hdrtype = hdr.hdrtype; | ||
|
|
||
| let _hdr = Frame::new(flow, &stream_slice, &cur_i[consumed as usize..], DCERPC_HDR_LEN as i64, DCERPCFrameType::Hdr as u8, None); | ||
| let _pdu = Frame::new(flow, &stream_slice, &cur_i[consumed as usize..], fraglen as i64, DCERPCFrameType::Pdu as u8, None); | ||
| let _hdr = Frame::new(flow, &stream_slice, cur_i, DCERPC_HDR_LEN as i64, DCERPCFrameType::Hdr as u8, None); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you reverting fc9da1c which was incorrect as found by oss-fuzz
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No, I'm not reverting it. I'm creating the slice in the beginning now so it'll be wrong to index here at
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was already done at line 716
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you're right. I'm surprised fuzzers didn't catch that. Behavior in this PR looks correct to me. wdyt? Edit: I think I misunderstood what you are saying in this thread. Are you referring to fuzzers finding the crash in #14766 and that being fixed here? Then, yes. I did not realize that the crash found by the fuzzers was not because of the new code. |
||
| let _pdu = Frame::new(flow, &stream_slice, cur_i, fraglen as i64, DCERPCFrameType::Pdu as u8, None); | ||
| if fraglen >= DCERPC_HDR_LEN && rem > DCERPC_HDR_LEN as u32 { | ||
| let _data = Frame::new(flow, &stream_slice, &cur_i[(consumed + DCERPC_HDR_LEN as u32) as usize..], (fraglen - DCERPC_HDR_LEN) as i64, DCERPCFrameType::Data as u8, None); | ||
| let _data = Frame::new(flow, &stream_slice, &cur_i[DCERPC_HDR_LEN as usize..], (fraglen - DCERPC_HDR_LEN) as i64, DCERPCFrameType::Data as u8, None); | ||
| } | ||
| let current_call_id = hdr.call_id; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.