-
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
protodetect: improve DCERPC UDP probing parser and simplify app-layer-detect-proto.c code #11541
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 |
---|---|---|
|
@@ -1401,7 +1401,6 @@ AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx, Flow *f | |
(flags & STREAM_TOSERVER) ? "toserver" : "toclient"); | ||
|
||
AppProto alproto = ALPROTO_UNKNOWN; | ||
AppProto pm_alproto = ALPROTO_UNKNOWN; | ||
|
||
if (!FLOW_IS_PM_DONE(f, flags)) { | ||
AppProto pm_results[ALPROTO_MAX]; | ||
|
@@ -1419,38 +1418,24 @@ AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx, Flow *f | |
FLOW_RESET_PP_DONE(f, reverse_dir); | ||
} | ||
} | ||
|
||
/* HACK: if detected protocol is dcerpc/udp, we run PP as well | ||
* to avoid misdetecting DNS as DCERPC. */ | ||
if (!(ipproto == IPPROTO_UDP && alproto == ALPROTO_DCERPC)) | ||
goto end; | ||
|
||
pm_alproto = alproto; | ||
|
||
/* fall through */ | ||
SCReturnUInt(alproto); | ||
} | ||
} | ||
|
||
if (!FLOW_IS_PP_DONE(f, flags)) { | ||
bool rflow = false; | ||
alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto, flags, &rflow); | ||
*reverse_flow = false; /* to be safe if it was changed by PM */ | ||
alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto, flags, reverse_flow); | ||
if (AppProtoIsValid(alproto)) { | ||
if (rflow) { | ||
*reverse_flow = true; | ||
} | ||
goto end; | ||
SCReturnUInt(alproto); | ||
} | ||
} | ||
|
||
/* Look if flow can be found in expectation list */ | ||
if (!FLOW_IS_PE_DONE(f, flags)) { | ||
*reverse_flow = false; /* to be safe if it was changed by PP */ | ||
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. Not sure about this safety check... not sure it is needed... 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'll inspect if the reversed flag is never set by the previous kind of the proto detection in the case of an unknown/failed result 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've made an inspection of the corresponding code. Direction may be reported reversed only in a case of valid protocol returned. So the "to be safe" lines are not necessary. Now i believe even debug validation is not necessary. At the same time i found a case when incorrect direction may be technically reported by the PM. The PM technically detects a set of protos but only first one is used. Let's see at app-layer-detect-proto.c from line 1407 DEBUG_VALIDATE_BUG_ON exists but the whole part of code looks confusing. Why do we use an array of matches when only first is expected? And i believe without debug a combination of patterns is possible when more than one is returned and some of the following damaged the 'reverse_flow'. It looks a bit confusing why PMGetProtoInspect tries to traverse all patterns (from line 294 of app-layer-detect-proto.c) while its client expects the one and only. And it has even DEBUG_VALIDATE_BUG_ON check. 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. Thanks for the investigation
It may be useful in the future, if some new code tries to break this assertion
Because we use some generic code for multi-pattern matching. The debug validation is here so that fuzzing can find if there is one way to find mutliple protocols with patterns... which would lead likely to bad things... 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 see. Regarding the array of matches - I still don't quite understand why we do not break from the loop started at app-layer-detect-proto.c:294 when the pattern is found. 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.
That is the important point indeed... |
||
alproto = AppLayerProtoDetectPEGetProto(f, flags); | ||
} | ||
|
||
end: | ||
if (!AppProtoIsValid(alproto)) | ||
alproto = pm_alproto; | ||
|
||
SCReturnUInt(alproto); | ||
} | ||
|
||
|
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.
Why this condition
leftover_bytes.len() >= hdr.fraglen as usize
?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.
Please see the conventional parser code at rust/src/dcerpc/dcerpc_udp.rs:207
The probe must do at least the same since the DCERPC PM is extremely short.
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 indeed, we are on UDP here :-)