CVE-2019-5715: Reflected SQL Injection through Form and DataObject
- Critical (?)
- CVE-2019-5715 (SS-2018-021)
- Versions Affected:
- All versions of SilverStripe 3 prior to 3.6.7, 3.7.3, all versions of SilverStripe 4 prior to 4.0.7, 4.1.5, 4.2.4, 4.3.1
- Versions Fixed:
- 3.6.7, 3.7.3, 4.0.7, 4.1.5, 4.2.4, 4.3.1
- Release Date:
A vulnerability has been identified where specifically crafted user input is executed as SQL SELECT statements in the process of writing this input to a database record. It requires a specific SilverStripe implementation to accept user input for this purpose (e.g. through a contact form which stores messages). It further requires that this record is exposed to the user again (e.g. emailing a copy of the contact form submission). In these situations, data stored in other database tables can be viewed (e.g. draft content). This only affects properties on the database record which are intended to be written through this user input (e.g. a contact form message, but not it’s database identifier).
There are no known exploits for this vulnerability which allow changing database state outside of the intended use (writing input to a specific database record). User input accepted by the CMS is not affected, since those endpoints require authentication. In certain situations, this vulnerability allows exposing of user credentials. These credentials are secured by strong one way cryptography (bcrypt hashed with individual salts), which makes it impractical to gain access by offline attacks against the user’s password.
Both direct assignment on DataObject (update(), setters via method calls, setters via magic methods) and indirect assignment (e.g. Form->saveInto()) are affected.
The vulnerability is related to the DBField classes underpinning the DataObject logic. Most DBField types in SilverStripe 3 are affected. Only the DBYear field type is confirmed to be affected in SilverStripe 4, limiting the impact in our current release line to a relatively uncommon use case.
Projects and modules which have implemented their own custom DBField classes may need to adjust them to override the DBField::scalarValueOnly() and DBField::prepValueForDB() methods if they want to accept non-scalar values. A common example of this are CompositeField implementations. Usually, there is no need to adjust custom code apart from upgrading to the latest releases. Subclasses of the DBCompositeField in 4.x are safe by default.
Our thanks to James Turner (plastyk studios) who responsibly disclosed the issue to us.