Skip to content
This repository has been archived by the owner on Nov 6, 2022. It is now read-only.

http_parser: revert memchr() optimization #469

Closed
wants to merge 3 commits into from

Conversation

indutny
Copy link
Member

@indutny indutny commented Apr 5, 2019

An optimization was introduced in c6097e1 and 0097de5. The crux of
optimization was to skip all characters in header value until either
of CR or LF. Unfortunately, this optimization comes at cost of
inconsistency in header value validation, which might lead to security
issue due to violated expectations in the user code.

Partially revert the optimization, and add additional check to make
general header value parsing consistent.

Fix: #468

An optimization was introduced in c6097e1 and 0097de5. The crux of
optimization was to skip all characters in header value until either
of CR or LF. Unfortunately, this optimization comes at cost of
inconsistency in header value validation, which might lead to security
issue due to violated expectations in the user code.

Partially revert the optimization, and add additional check to make
general header value parsing consistent.

Fix: nodejs#468
@indutny
Copy link
Member Author

indutny commented Apr 5, 2019

cc @nodejs/http .

I do not believe that there is any security risk for Node.js applications. However, since this is causing a public security issue for envoyproxy, I'd suggest we act promptly on this.

Thank you!

Copy link
Contributor

@sam-github sam-github left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an expert here, but this looks like it works to me.

Copy link

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! A few minor comments.

@@ -4316,6 +4316,9 @@ main (void)
test_simple("GET / HTTP/11.1\r\n\r\n", HPE_INVALID_VERSION);
test_simple("GET / HTTP/1.01\r\n\r\n", HPE_INVALID_VERSION);

test_simple("GET / HTTP/1.0\r\nHello: w\1rld\r\n\r\n", HPE_INVALID_HEADER_TOKEN);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you could also test with explicit \0 I think it would be great, since NULs are particularly tricky when it comes to C strings as a special case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that there's point to checking \0 too. However, this works without further changes to the code, because strlen() still returns correct value. Perhaps, we should address it in a separate follow-up change?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine too.

http_parser.c Outdated Show resolved Hide resolved
http_parser.c Outdated
for (; p != data + len; p++) {
ch = *p;
if (ch == CR || ch == LF) {
--p;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you remove this, can you then skip the if below?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a revert of the change. I'd rather keep it closer to the original code, unless there are other reasons for improving it here?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that's fine.

http_parser.c Outdated Show resolved Hide resolved
Copy link

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quick fix. Can you advise on the best way to report security vulnerabilities related to http-parser in the future?

indutny added a commit that referenced this pull request Apr 9, 2019
An optimization was introduced in c6097e1 and 0097de5. The crux of
optimization was to skip all characters in header value until either
of CR or LF. Unfortunately, this optimization comes at cost of
inconsistency in header value validation, which might lead to security
issue due to violated expectations in the user code.

Partially revert the optimization, and add additional check to make
general header value parsing consistent.

Fix: #468
PR-URL: #469
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Harvey Tuch <htuch@google.com>
@indutny
Copy link
Member Author

indutny commented Apr 9, 2019

Landed in 2a0d106. Thank you everyone!

@htuch I'd use Node.js security channels for this. https://nodejs.org/en/security/ Thanks again for reporting it!

@indutny indutny closed this Apr 9, 2019
@indutny indutny deleted the fix/gh-468 branch April 9, 2019 00:38
@indutny indutny mentioned this pull request Apr 9, 2019
ploxiln pushed a commit to ploxiln/http-parser that referenced this pull request Apr 9, 2019
An optimization was introduced in c6097e1 and 0097de5. The crux of
optimization was to skip all characters in header value until either
of CR or LF. Unfortunately, this optimization comes at cost of
inconsistency in header value validation, which might lead to security
issue due to violated expectations in the user code.

Partially revert the optimization, and add additional check to make
general header value parsing consistent.

Fix: nodejs#468
PR-URL: nodejs#469
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Harvey Tuch <htuch@google.com>
@sam-github
Copy link
Contributor

@indutny @nodejs/http Can anyone confirm that this does not affect Node.js? #469 (comment) --- why would it not affect Node.js?

Because it looks like it could affect Node.js, in which case we'd need a CVE for it and to backport the fix to LTS branches.

@indutny
Copy link
Member Author

indutny commented Nov 18, 2019

I believe it would not affect Node.js due to the way the header values are converted to V8 strings in Node. We use OneByteString(env->isolate(), str_, size_) and thus \0 have no special effects on our operation.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

http-parser does not correct sanitize NUL characters in header values
5 participants