Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Security@Scale: Invariant Detector

Security@Scale: Invariant Detector

A Facebook London project with Chad Parry, Ben Matthews, Ioannis Papagiannis and Marjori Pomarole.

Video: https://www.youtube.com/watch?v=a-GyrDBWppU

Marjori Pomarole

November 12, 2015
Tweet

Other Decks in Technology

Transcript

  1. Endpoints everywhere, bugs will appear eventually Facebook App POST requests

    facebook.com/update/cover_photo m.facebook.com/update/page_preference facebook.com/graphql/photos .... Mobile Apps (Android, iPhone, etc) facebook.com m.facebook.com
  2. Malicious actors taking advantage of bugs Exploiting endpoints POST requests

    facebook.com/update/cover_photo m.facebook.com/update/page_preference facebook.com/graphql/photos .... Mobile Apps (Android, iPhone, etc) facebook.com m.facebook.com
  3. Building tools and frameworks so developers don't have to think

    about security Security Infrastructure POST requests facebook.com/update/cover_photo m.facebook.com/update/page_preference facebook.com/graphql/photos .... Mobile Apps (Android, iPhone, etc) facebook.com m.facebook.com
  4. What a typical request looks like Good Request and Good

    Code endpoint facebook.com/update/cover_photo uri params ?user_id=1234&photo_id=4321 Logger in user: 1234 class UpdateCoverPhotoController { ... public async genResponse( ): Awaitable<xhp> { $request = $this->getRequest(); $user_id = $request->getInt('user_id'); $photo_id = $request->getInt('photo_id'); $actor = $request->getUserID(); $can_edit = Photos::checkPermission($actor, $photo_id); // code to update cover photo for $user_id } }
  5. Malicious actor can use Curl to fabricate a request Evil

    request and Good code endpoint facebook.com/update/cover_photo uri params ?user_id=9876&photo_id=2345 Logger in user: 1234 class UpdateCoverPhotoController { ... public async genResponse( ): Awaitable<xhp> { $request = $this->getRequest(); $user_id = $request->getInt('user_id'); $photo_id = $request->getInt('photo_id'); $actor = $request->getUserID(); $can_edit = Photos::checkPermission($actor, $photo_id); // cannot edit, so fail the request } }
  6. This is where we fail Evil Request and Bad code

    class UpdateCoverPhotoController { ... public async genResponse( ): Awaitable<xhp> { $request = $this->getRequest(); $user_id = $request->getInt('user_id'); $photo_id = $request->getInt('photo_id'); // code to update cover photo for $user_id } } endpoint facebook.com/update/cover_photo uri params ?user_id=9876&photo_id=2345 Logger in user: 1234
  7. Adding a layer of security before product code access objects

    in data store Privacy Framework Privacy Rules AllowIfOwner DenyIfNotCreator AllowIfViewerCanSeePageRule .... Product Code Data Store
  8. We still have to have all the correct policies in

    place Privacy Framework Privacy Rules AllowIfOwner DenyIfNotCreator AllowIfViewerCanSeePageRule .... Product Code Data Store
  9. Tons of legacy code though, hard to migrate everything over

    night Privacy Framework Product Code Data Store Privacy Rules AllowIfOwner DenyIfNotCreator AllowIfViewerCanSeePageRule ....
  10. The automatic approach, this is what you are all here

    for System that automatically finds and blocks anomalies in write requests before we update our data stores. Invariant Detector
  11. 1. log sample 2. data pipeline creates rules 3. evaluate

    rules 6. enforce rules 7. Block Set of Invariants 5. data pipeline ratifies rules 4. log evaluation results Hive actor uri equivalent fields 1234 /photo/save photo.owner_id === actor 2432 /user/update user.id == actor
  12. 1. log sample Hive actor uri equivalent fields 1234 /photo/save

    photo.owner_id === actor 2432 /user/update user.id == actor
  13. 1. log sample 2. data pipeline creates rules Set of

    Invariants Hive actor uri equivalent fields 1234 /photo/save photo.owner_id === actor 2432 /user/update user.id == actor
  14. 1. log sample 2. data pipeline creates rules Set of

    Invariants Hive actor uri equivalent fields 1234 /photo/save photo.owner_id === actor 2432 /user/update user.id == actor 3. evaluate rules
  15. 1. log sample 2. data pipeline creates rules 3. evaluate

    rules Set of Invariants 4. log evaluation results Hive actor uri equivalent fields 1234 /photo/save photo.owner_id === actor 2432 /user/update user.id == actor
  16. 1. log sample 2. data pipeline creates rules 3. evaluate

    rules Set of Invariants 5. data pipeline ratifies rules 4. log evaluation results Hive actor uri equivalent fields 1234 /photo/save photo.owner_id === actor 2432 /user/update user.id == actor
  17. 1. log sample 2. data pipeline creates rules 3. evaluate

    rules Set of Invariants 5. data pipeline ratifies rules 4. log evaluation results Hive actor uri equivalent fields 1234 /photo/save photo.owner_id === actor 2432 /user/update user.id == actor 6. enforce rules
  18. 1. log sample 2. data pipeline creates rules 3. evaluate

    rules 6. enforce rules 7. Block Set of Invariants 5. data pipeline ratifies rules 4. log evaluation results Hive actor uri equivalent fields 1234 /photo/save photo.owner_id === actor 2432 /user/update user.id == actor
  19. What exactly are we logging here? Equivalent Fields { "11111111111111":[["id1","owner_id"],["actors","[]"]],

    "22222222222222":[["id1","owner_id"],["id1","oid"]], "19283912830192":[["id1","time_updated"],["id2","time_updated"]], }
  20. Read-optimised graph data store built at Facebook TAO Bronson, Nathan,

    et al. "TAO: Facebook's Distributed Data Store for the Social Graph." USENIX Annual Technical Conference. 2013. User Privacy Settings Photo User like (asymmetric) liked by (asymmetric) privacy (unique) friends (symmetric)
  21. How it looks before it is saved to TAO Example

    request PHOTO USER USER_TO_COVER_PHOTO { "22222222222222":[["id1","id"],["id2","owner_id"]], "19283912830192":[["id1","time_updated"],["id2","time_updated"]], } id owner_id size type ... id name dob username ... id1 id2
  22. We can look at the environment as well Example request

    PHOTO USER USER_TO_COVER_PHOTO { "11111111111111":[["actors","[]"], ["id2","owner_id"]], "22222222222222":[["id1","id"],["id2","owner_id"]], "19283912830192":[["id1","time_updated"],["id2","time_updated"]], } id owner_id size type ... id name dob username ... id1 id2 logged in user (actors) actor's friends pages the actor admins groups the actor has membership groups the actor admins
  23. Reading logs in Hive and creating rules Data pipeline Logs

    Logs Logs Logs DATE DATE-1 DATE-N ... Data Pipeline HiveQL Set of invariants PHOTO -> COVER_PHOTO_TO_USER -> USER 1. logged in user always needs to be equal to the owner_id of the photo 2. field owner_id always needs to be equal to id of user FBOBj.
  24. With negligible overhead in 100% of the requests Evaluate the

    rules Set of invariants PHOTO -> COVER_PHOTO_TO_USER -> USER 1. logged in user always needs to be equal to the owner_id of the photo 2. field owner_id always needs to be equal to id of user FBOBj. /update/cover_photo
  25. Updating these rules on web servers Distribution Set of invariants

    PHOTO -> COVER_PHOTO_TO_USER -> USER 1. logged in user always needs to be equal to the owner_id of the photo 2. field owner_id always needs to be equal to id of user FBOBj.
  26. Configerator Tang, Chunqiang, et al. "Holistic configuration management at Facebook."

    Proceedings of the 25th Symposium on Operating Systems Principles. ACM, 2015.
  27. Configerator can take care of it Distribution Set of invariants

    Configerator PHOTO -> COVER_PHOTO_TO_USER -> USER 1. logged in user always needs to be equal to the owner_id of the photo 2. field owner_id always needs to be equal to id of user FBOBj.
  28. Configerator is immediate though, block disaster can occur Distribution Set

    of invariants PHOTO -> COVER_PHOTO_TO_USER -> USER 1. field size in photo is equal to 10x10 Configerator
  29. Investigating what code has the vulnerability Violations violations actor uri

    stack_trace post_data event_time 1234 /photo/ save .... photo_id.... 1231239122 blocked request Product teams to investigate
  30. Reducing impact of false positives Whitelist read whitelist before blocking

    Whitelist (in Configerator) PHOTO -> COVER_PHOTO_TO_USER -> USER logged in user always needs to be equal to the owner_id of the photo
  31. Whitelist Whitelist PHOTO -> COVER_PHOTO_TO_USER -> USER logged in user

    always needs to be equal to the owner_id of the photo Whitelist (in Configerator) PHOTO -> COVER_PHOTO_TO_USER -> USER logged in user always needs to be equal to the owner_id of the photo
  32. And blocked from exploiting people's data • A request that

    was trying to upload pending photos to any album in an specific endpoint in mobile • Whitehat trying to exploit scheduling of draft posts in pages in our graphql api • Requests that were allowing personal photos of a page admin to be used on the page. Leaked the identity of the admin • Endpoint to update location preferences of page was not checking that the person logged in was admin of the page Cool stuff it found
  33. What can we do to make the system even more

    powerful • False Positives • Better tools for investigation • Better graph relationships support What's next
  34. With Facebook scale and negligible overhead we can use dynamic

    code analysis on our live production traffic to automatically infer invariants to find and block malicious actors from manipulating people's data. Invariant Detector Questions? Come find me afterwards or email me at [email protected] A Facebook London project with Chad Parry, Ioannis Papagiannis, Marjori Pomarole and SecInfra team.