Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

James Turner
James Turner

Posted on • Edited on • Originally published atturnerj.com

     

The anatomy of a critical vulnerability

Note: This was responsibly disclosed to SilverStripe immediately when it was discovered. It has now beenpublicly disclosed by SilverStripe (CVE-2019-5715 / SS-2018-021) as of the 18th of February with patches for all supported versions released.

Where I have workedfor the last 7 years, we have primarily built sites in PHP, specificallySilverStripe. As a final little surprise for my colleagues before I left, I discovered an SQL injection vulnerability.

Before going into detail of what the security vulnerability is, I need to explain a little about SilverStripe.

SilverStripe

SilverStripe is an open source PHP content management system. At its core, you have aDataObject class that basically everything that writes to the database uses. That is from yourHomePage class to yourImageSlide class to yourMember class.

A typicalDataObject might look something like this (namespacing removed for brevity):

classMyCustomObjectextendsDataObject{private$db=['MyProperty'=>'Varchar'];private$has_many=['Slides'=>ImageSlide::class];}
Enter fullscreen modeExit fullscreen mode

When you have an instance of one of these objects, you can read/writeMyProperty through magic methods:

$myPropertyVal=$myCustomObject->MyProperty;$slides=$myCustomObject->Slides();$myCustomObject->MyProperty='Hello world!';$myCustomObject->write();
Enter fullscreen modeExit fullscreen mode

This is the main way you will deal with getting and setting values. There are other helper methods which can bulk set these values from arrays etc.

That's all you need to know to get the gist of the issue that is to come.

Discovery

While I did discover the issue, there are two important things to mention in the discovery process:

  • A site of ours was having a security audit through one of those automatic vulnerability testing systems. An error from a specific attempt pointed me in the right direction.
  • When I disclosed the issue to SilverStripe, they discovered further issues which expanded on this vulnerability.

The error triggered by the automated security audit was with a SilverStripe module calledSwipeStripe however it wasn't a bug with the module, just in this case initially exposed through the module.

There is anOrderForm class with a specificupdate method which is where the problems start:

publicfunctionupdate(SS_HTTPRequest$request){if($request->isPOST()){$member=Customer::currentUser()?Customer::currentUser():singleton('Customer');$order=Cart::get_current_order();//Update the Order$order->update($request->postVars());$order->updateModifications($request->postVars())->write();$form=OrderForm::create($this->controller,'OrderForm')->disableSecurityToken();// $form->validate();return$form->renderWith('OrderFormCart');}}
Enter fullscreen modeExit fullscreen mode

It is$order->update($request->postVars()); that is a problem. Theupdate function call on the$order object is a built-in SilverStripe function where you pass an array of fields and it will set them for you. The passing of POST variables straight into it is a Very Bad Idea™ (you should be checking your fields properly) but I digress.

SilverStripe would normally safely prepare queries so SQL injection can't happen but there was an edge case where it didn't work.

It turns out that if your POST request looks less likeSomeProperty=1 and more likeSomeProperty[MySneakySQLStatement]=1, things start going weird, skipping how the prepared statements work and ending up in the raw query.

This issue presents itself here becausepostVars returnsSomeProperty[MySneakySQLStatement]=1 to something a little like this:

{"SomeProperty":{"MySneakySQLStatement":1}}
Enter fullscreen modeExit fullscreen mode

If internally it looked more like the following, it likely would have not been an issue:

{"SomeProperty[MySneakySQLStatement]":1}
Enter fullscreen modeExit fullscreen mode

Now to actually have a working exploit, it is a little more complex than just sticking an SQL query in a field name but you get the idea.

I gave everything I knew to SilverStripe and they took it from there, finding that it is a bit bigger of an issue than it seemed.

The actual issue

In terms of a method to exploit this issue, I wasn't wrong but it wasn't the only method. It turns out that theupdate function I mentioned earlier isn't the problem, it is the code that it depended on which backs basically all writing to the database.

InSilverStripe's blog post about the issue, they state:

Both direct assignment on DataObject (update(), setters via method calls, setters via magic methods) and indirect assignment (e.g. Form->saveInto()) are affected.

So not just theupdate method that I originally noticed but basically every method of writing was affected! This bug just turned from a "bad but unlikely to affect many" to a "oh this might affect everyone".

Their blog post goes onto say:

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.

While still a critical vulnerability, it is great that through other fixes and improvements that the latest major version of SilverStripe (Version 4) is less impacted.

The fix

The fix is actually fairly small, split across 5 files (for SilverStripe 4) which you can seehere.

It really amount to double checking that field assignments are not arrays.

For example, in part of theDataObject class:

// Make sure none of our field assignment are arraysforeach($manipulationas$tableManipulation){if(!isset($tableManipulation['fields'])){continue;}foreach($tableManipulation['fields']as$fieldValue){if(is_array($fieldValue)){user_error('DataObject::writeManipulation: parameterised field assignments are disallowed',E_USER_ERROR);}}}
Enter fullscreen modeExit fullscreen mode

Conclusion

Always, always, ALWAYS responsibly disclose security issues. Thanks to Matt, Maxime, Ingo and everyone else at SilverStripe who worked on testing and resolving this vulnerability! 🙂

For SilverStripe users, you can view all security releaseshere or view the security release processeshere.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Director of Turner Software | Creator of BrandVantage
  • Location
    Adelaide, Australia
  • Education
    Bachelor of Information Technology
  • Work
    Director at Turner Software
  • Joined

Trending onDEV CommunityHot

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp