5 ms·
The meaning of ^ and $ in perl regexes can be altered by modifiers at the end of the regex. A 'multi-line' regex, with a /m at the end, makes them match the sta
by joosters 3y ago
The meaning of ^ and $ in perl regexes can be altered by modifiers at the end of the regex. A 'multi-line' regex, with a /m at the end, makes them match the start and end of any line.
- jwilk 3y agoThe code doesn't use /m. So indeed the problem is that $ will match before \n at the end of the string the Perl interpreter is working with, which is not the whole thing containing the payload.
- jodrellblank 3y agoI've just worked through it to understand it; it's a more subtle exploit than I thought. My above comment about $ being end-of-line is wrong, the above comment saying you need the /m modifier for that to happen is correct. In case anyone cares, the bug matches <backslash> <newline> <quote> then the regex in question matches <backslash> <newline> and the code logic is that one backslash must be escaping the next character from the input, but instead of adding on the next character it always adds a quote - after searching for a quote the next character must be a quote, right? But it wasn't, it was a newline, which was missed because of $ behaviour with newline at the end of a string. That acts to shift the quote one to the left <backslash> <quote> <newline> and now that makes an escaped quote which won't break eval() and the loop carries on and reads in the exploit text up to the real end quote. ---- Details: the Perl code takes this pattern in the input (the quotes are part of the input, in the file data): "a\ "" six characters, describing a quoted string of four characters: <a> <backslash> <newline> <quote> The Perl code finds the string starting quote and moves past it, and sets $tok empty to hold the quoted string content. Then it searches for the next quote (not the last, the next): last Tok unless $$dataPt =~ /"/sg; This will match at the quote after the newline. Then it substrings from the saved opening quote position to 1 before the found quote. So the substring includes the newline char: # the closing quote position. (not including the quote). $tok .= substr($$dataPt, $pos, pos($$dataPt)-1-$pos); That gets <a> <backslash> <newline> and not the following <quote> <quote> Then it does the odd-number-of-backslashes test on the substring <a> <backslash> <newline>: last unless $tok =~ /(\\+)$/ and length($1) & 0x01; And the regex matches for <backslash> <newline> instead of the intended <backslash> ENDOFSTRING so the code thinks there is an escaped character. It doesn't add the next character from the string into the token, it assumes the escaped character must be a quote and always adds a quote to $tok. $tok .= '"'; # quote is part of the string Effectively shifting the input quote to the other side of the newline, from: "a\ "" to "a\" " and in the exploit case: "a\ "exploit code" to "a\" exploit code" Then the inner loop runs again and finds the <exploit code to closing quote> text and adds that on to $tok. Now there's a string with an escaped quote and some exploit code.