Issue metadata
Sign in to add a comment
|
Security: buffer overrun in ReplaceSubstringsAfterOffset |
||||||||||||||||||||||
Issue description
Found by inspection.
On some inputs, DoReplaceSubstringsAfterOffset (which powers
base::ReplaceSubstringsAfterOffset) never terminates, and writes past
the bounds of its buffer. For example:
ReplaceSubstringsAfterOffset(std::string("aaabaa"), 0, "aa", "ccc");
The root cause of this is an algorithmic bug, where it was assumed that
string::rfind and string::find would return the same matches in reversed order.
The fix should be to not call rfind(), and instead only scan forward using
find().
EXPLOITABILITY
On triggering the bug, the code appears never to terminate, and will keep searching/
memmoving for string matches until it hits an invalid memory region. This might
make it hard to use in an exploit.
Three conditions are necessary to trigger the overrun in practice, and most
non-test calls to ReplaceSubstringAfterOffset seem to not satisfy (1) or (2):
1. |find_this| must be a string that overlaps with itself (it has a prefix
that is also a suffix). E.g. 'aa'.
2. |replace_with| must be longer than |find_this|.
3. |str| must have overlapping occurences of |find_this| that are not
adjacent to the last match, in string.
I see only one case where there might be potential for abusing this: https://cs.chromium.org/chromium/src/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc?type=cs&sq=package:chromium&l=44
Possible fix: https://codereview.chromium.org/2979393002
,
Jul 26 2017
,
Jul 26 2017
(Security Sheriff Triage) Nick -- assigning to you since you have already figured out the rootcause and have a fix and the right reviewers.
,
Jul 26 2017
,
Jul 27 2017
,
Jul 28 2017
,
Aug 2 2017
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/09d9682b0039e3b1dd16e5be60f5ebe4f698021f commit 09d9682b0039e3b1dd16e5be60f5ebe4f698021f Author: nick <nick@chromium.org> Date: Wed Aug 02 00:31:16 2017 [string_util] fix bug in ReplaceSubstringsAfterOffset() The problem with DoReplaceSubstringsAfterOffset was that the following search would not terminate: ReplaceSubstringsAfterOffset(std::string("aaabaa"), 0, "aa", "ccc"); The root cause of this is an algorithmic bug, where it was assumed that string::rfind and string::find would return the same matches in reversed order. The fix is to only scan forward using find(). For the length-expansion case, if capacity is insufficient, we swap with a temporary and build the result into new memory. If existing capacity suffices, we'll shift the tail of the string down to the new size, and then use left-to-right memmove loop of the length- contraction case, with the shifted tail as the src. BUG= 749228 Review-Url: https://codereview.chromium.org/2979393002 Cr-Commit-Position: refs/heads/master@{#491170} [modify] https://crrev.com/09d9682b0039e3b1dd16e5be60f5ebe4f698021f/base/strings/string_util.cc [modify] https://crrev.com/09d9682b0039e3b1dd16e5be60f5ebe4f698021f/base/strings/string_util_unittest.cc
,
Aug 29 2017
,
Aug 30 2017
,
Oct 17 2017
,
Dec 6 2017
This bug has been closed for more than 14 weeks. Removing security view restrictions. For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot |
|||||||||||||||||||||||
►
Sign in to add a comment |
|||||||||||||||||||||||
Comment 1 by nick@chromium.org
, Jul 26 2017