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

SQL injection possible with limit() on MySQL #1463

Closed
mpetrovich opened this issue Feb 14, 2018 · 9 comments
Closed

SQL injection possible with limit() on MySQL #1463

mpetrovich opened this issue Feb 14, 2018 · 9 comments

Comments

@mpetrovich
Copy link
Contributor

mpetrovich commented Feb 14, 2018

The limit() query method is susceptible to catastrophic SQL injection with MySQL.

For example, given a model User for a table users:

UserQuery::create()->limit('1;DROP TABLE users')->find();

This will drop the users table!

The cause appears to be a lack of integer casting of the limit input in either Propel\Runtime\ActiveQuery\Criteria::setLimit() or in Propel\Runtime\Adapter\Pdo\MysqlAdapter::applyLimit(). The code comments there seem to imply that casting was avoided due to overflow issues with 32-bit integers.

This is surprising behavior since one of the primary purposes of an ORM is to prevent basic SQL injection.

This affects all versions of Propel: 1.x, 2.x, and 3.

Related:

@marcj
Copy link
Member

marcj commented Feb 14, 2018

Care to provide a PR?

@mpetrovich
Copy link
Contributor Author

Happy to! Coming soon.

@halfer
Copy link

halfer commented Feb 16, 2018

@mpetrovich: good spot. However, food for thought - it is usual practice to notify a project of security problems privately, rather than making it public in the first instance.

@mpetrovich
Copy link
Contributor Author

mpetrovich commented Feb 16, 2018

Good point, pardon my rush to post it here. Maintainers: Please delete these issues in the meantime if you’d like—I’m working on a pull request tonight to address this issue.

mpetrovich added a commit to mpetrovich/Propel2 that referenced this issue Feb 16, 2018
When constructing a MySQL LIMIT clause, values for the offset and limit are coerced to integers. This prevents arbitrary SQL from being injected via the limit parameter. Example:

    UserQuery::create()->limit('1;DROP TABLE users')->find();

Previously, this would have injected `DROP TABLE users` into the generated SQL. Now, the limit value would be coerced to the integer `1`.

Fixes propelorm#1463
mpetrovich added a commit to mpetrovich/Propel2 that referenced this issue Feb 16, 2018
When constructing a MySQL LIMIT clause, values for the offset and limit are coerced to integers. This prevents arbitrary SQL from being injected via a query limit. Example:

    UserQuery::create()->limit('1;DROP TABLE users')->find();

Previously, this would have injected `DROP TABLE users` into the generated SQL. Now, the limit value would be coerced to the integer `1`.

Fixes propelorm#1463
@mpetrovich
Copy link
Contributor Author

PR with a fix: #1464

mpetrovich added a commit to mpetrovich/Propel2 that referenced this issue Feb 16, 2018
When constructing a MySQL LIMIT clause, values for the offset and limit are coerced to integers. This prevents arbitrary SQL from being injected via a query limit. Example:

    UserQuery::create()->limit('1;DROP TABLE users')->find();

Previously, this would have injected `DROP TABLE users` into the generated SQL. Now, the limit value would be coerced to the integer `1`.

Fixes propelorm#1463
mpetrovich added a commit to mpetrovich/Propel2 that referenced this issue Feb 16, 2018
When constructing a MySQL LIMIT clause, values for the offset and limit are coerced to integers. This prevents arbitrary SQL from being injected via a query limit. Example:

    UserQuery::create()->limit('1;DROP TABLE users')->find();

Previously, this would have injected `DROP TABLE users` into the generated SQL. Now, the limit value would be coerced to the integer `1`.

Fixes propelorm#1463
@halfer
Copy link

halfer commented Feb 16, 2018

@marcj: I think this should this get an alert for the relevant versions on the Symfony security checker. Do you agree that all prior versions were vulnerable? I suspect the PR to that service needs to specify what versions are affected, and thus it needs to be accurate.

Does this need a CVE reference? I don't know how to go about getting that assigned.

marcj pushed a commit that referenced this issue Feb 16, 2018
)

When constructing a MySQL LIMIT clause, values for the offset and limit are coerced to integers. This prevents arbitrary SQL from being injected via a query limit. Example:

    UserQuery::create()->limit('1;DROP TABLE users')->find();

Previously, this would have injected `DROP TABLE users` into the generated SQL. Now, the limit value would be coerced to the integer `1`.

Fixes #1463
@halfer
Copy link

halfer commented Feb 17, 2018

@mpetrovich:

Partly to answer my own question, I see you have a bug report for each of the major versions. Thanks.

I have prepared a suggested change and will submit that as a PR to the sec database tomorrow (Sunday 18th Feb). If you are around and are able to double-check the contents, that'd be great.

In particular, I don't know if >=2 is considered in Composer terms to include all the alpha releases in this project. Unfortunately I cannot test this until the changes are merged to the FriendsOfSymfony repo. Comments on this are most welcome.

Presently for Propel1 I have marked everything including the current release as vulnerable. If a new release is made, ping me and I will push a new change.

@mpetrovich
Copy link
Contributor Author

@halfer:

In particular, I don't know if >=2 is considered in Composer terms to include all the alpha releases in this project.

I believe so. According to the Composer docs, any alpha version like 2.x-alpha-y is strictly before 2.0, but both are still in the 2.x range and should be satisfied by any rule like ~2 or >=2.

Presently for Propel1 I have marked everything including the current release as vulnerable. If a new release is made, ping me and I will push a new change.

I've made pull requests [1] [2] to fix the same vulnerabilities in Propel v1 and v3, so you should be able to restrict the vulnerability version range to everything up to the current releases.
[1] propelorm/Propel#1054
[2] propelorm/Propel3#74

@halfer
Copy link

halfer commented Feb 18, 2018

Marvellous, thanks @mpetrovich. I've set the Propel1 constraints to <=1.7.1, so if a new release is made, I am assuming it will contain your fix.

I'll raise a PR just now and will liaise with maintainers to get this merged into the advisories db. Once that is done I'll build a demo Propel1 and Propel2 project to make sure the warnings come up on the latest releases. That will double-check the alpha thing too.

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

No branches or pull requests

3 participants