Skip to content
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

[5.8] Correctly escape single quotes in json paths #28160

Merged
merged 3 commits into from Apr 10, 2019
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.
+25 −0
Diff settings

Always

Just for now

@@ -1119,6 +1119,8 @@ protected function wrapJsonFieldAndPath($column)
*/
protected function wrapJsonPath($value, $delimiter = '->')
{
$value = preg_replace("/([\\\\]+)?\\'/", "\\'", $value);

This comment has been minimized.

Copy link
@staudenmeir

staudenmeir Apr 10, 2019

Contributor

With preg_replace("/(\\\\)*'/", ...), the tests still pass. Is there a difference?

This comment has been minimized.

Copy link
@brendt

brendt Apr 10, 2019

Author Contributor

You sure? Because it won't match \', this would cause only the ' to be escaped. Resulting in \\' as the end result, which in turn allows for the attack.

This comment has been minimized.

Copy link
@staudenmeir

staudenmeir Apr 10, 2019

Contributor

Don't the tests check this?

This comment has been minimized.

Copy link
@vlakoff

vlakoff Apr 13, 2019

Contributor

Same thoughts as staudenmeir, preg_replace("/\\\\*'/", ...) appears to be a strictly equivalent code. But simpler thus less error-prone.

I guess you got a bit confused between PHP and regex escaping ;)

This comment has been minimized.

Copy link
@vlakoff

vlakoff Apr 13, 2019

Contributor

Describing the code:

  • replace: quote preceded by 0 or more backslashes
  • with: quote preceded by one backslash
return '\'$."'.str_replace($delimiter, '"."', $value).'"\'';
}
@@ -2252,6 +2252,29 @@ public function testMySqlWrappingJsonWithBooleanAndIntegerThatLooksLikeOne()
$this->assertEquals('select * from `users` where json_extract(`items`, \'$."available"\') = true and json_extract(`items`, \'$."active"\') = false and json_unquote(json_extract(`items`, \'$."number_available"\')) = ?', $builder->toSql());
}
public function testJsonPathEscaping()
{
$expectedWithJsonEscaped = <<<SQL
select json_unquote(json_extract(`json`, '$."\'))#"'))
SQL;
$builder = $this->getMySqlBuilder();
$builder->select("json->'))#");
$this->assertEquals($expectedWithJsonEscaped, $builder->toSql());
$builder = $this->getMySqlBuilder();
$builder->select("json->\'))#");
$this->assertEquals($expectedWithJsonEscaped, $builder->toSql());
$builder = $this->getMySqlBuilder();
$builder->select("json->\\'))#");
$this->assertEquals($expectedWithJsonEscaped, $builder->toSql());
$builder = $this->getMySqlBuilder();
$builder->select("json->\\\'))#");
$this->assertEquals($expectedWithJsonEscaped, $builder->toSql());
}
public function testMySqlWrappingJson()
{
$builder = $this->getMySqlBuilder();
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.