Preferences

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.

The 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.
I'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.

This item has no comments currently.

Keyboard Shortcuts

Story Lists

j
Next story
k
Previous story
Shift+j
Last story
Shift+k
First story
o Enter
Go to story URL
c
Go to comments
u
Go to author

Navigation

Shift+t
Go to top stories
Shift+n
Go to new stories
Shift+b
Go to best stories
Shift+a
Go to Ask HN
Shift+s
Go to Show HN

Miscellaneous

?
Show this modal