Short summary:
In products that use the same real-time collaboration system as Google Docs, an attacker could take over other user’s “real-time sessions”. This means that the attacker could chat, move the cursor, and perform other collaboration-related actions in the name of any victim.
POC Video:
https://youtu.be/q34AZ3I4gK8 - 2:37
Core Issue:
The real-time collaboration system uses a custom 16 char long session ID to authenticate users. When a user opens e.g. a Docs document, the page starts polling the /bind endpoint, which returns as soon as a new event occurs on the document.
The core issue is that the events received by this endpoint almost always contain the session ID of the event initiator. For example, if a new user joins the document, everyone who already has the document open will receive a user object with the new user’s name, profile picture, and among others, with the new user’s session ID.
The obtained session ID then can be used to perform real-time actions in the name of that user.
Steps to reproduce:
This is a written version of the attack performed in the POC video.
- Install Burp Suite
- Create 3 new users,
Attacker,Victim, andObserver - Only start proxying
Attacker’s traffic with Burp - With
Victim, Create a new Document, and inviteAttackerandObserverasEditors - Open the document in all 3 browser windows
- Refresh
Victim’s page to generate a new join event on the/bindendpoint - In Burp, look for new
/bindresponses, and find the one that includesVictim’s user object - Note the
Victim’ssidfrom the user object, andAttacker’ssidfrom the/bindrequest’ssidparameter - Go to
Proxy->Options->Match and Replaceand clickAdd - Set the type to
Request first line, setMatchtoAttacker’ssid, setReplacetoVictim’ssid, and clickOK - With
Attacker, send a new chat message - With
Observer, open the chat pane, and see that the message was sent byVictim - With
Attacker, start typing and/or selecting text - With
Observer, see that it looks likeVictimis selecting/editing the document
Extra Attacks:
- Other actions can also be performed when the attacker has the victim’s session ID. For example, using the
/leaveendpoint, the victim can be “kicked off” from the document, making her invisible for the other users (but can still edit). Any other endpoint that authenticates with that session ID is probably vulnerable, like/active. - Moving the cursor requires
EditororCommenterprivileges, so a normalViewercan’t move the cursors ofEditors, since the permission is checked on a Google session level. But, endpoints like/chatand/leavecan be used byViewers as well. I was able to chat in the name of any editor with an anonymous (not logged in) account when the document was link-shared with theViewerpermissions. That is interesting, since by design onlyEditors andCommenters should be able to chat, other roles can’t even see the chat pane. - Changing the
sid(fromAttacker’s toVictim’s) in thebundlesobject when making an edit withAttackerwill crashVictim’s page, with the messageUnable to load file - Try to load it again or send an error report.. OtherViewers will not crash, and if they have theLive editsaccessibility pane enabled, they will see that the edit was made byVictim. The edit initiator (Attacker) will be correctly shown in theVersion history.
Limitations:
- Changing the
sidin theRequest first lineonly changes the user of theselectioncommands. So, it looks likeAttackeris typing in the name ofVictim, but actually,Attackeris only moving the cursor in the name ofVictim, and editing using her own account. So, checkingVersion historywill correctly show that the edits were made byAttacker. - In my research, I wasn’t able to trick the
Version historyusing these session IDs, as it is most likely checking the user’s full Google session.
[Disclosure Warning]:
This is a new system I am experimenting with:
This issue is subject to a 90 day disclosure deadline. On 2021-04-20 this issue with all additional comments will be publicly disclosed. Sensitive details from the report/comments such as names/email addresses will be redacted. If you would like to redact additional information or if for some reason the issue can’t be fixed until the deadline, let me know in a comment.
Thank you!