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.
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,
- Only start proxying
Attacker’s traffic with Burp
Victim, Create a new Document, and invite
- Open the document in all 3 browser windows
Victim’s page to generate a new join event on the
- In Burp, look for new
/bindresponses, and find the one that includes
Victim’s user object
- Note the
sidfrom the user object, and
- Go to
Match and Replaceand click
- Set the type to
Request first line, set
sid, and click
Attacker, send a new chat message
Observer, open the chat pane, and see that the message was sent by
Attacker, start typing and/or selecting text
Observer, see that it looks like
Victimis selecting/editing the document
- 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
- Moving the cursor requires
Commenterprivileges, so a normal
Viewercan’t move the cursors of
Editors, since the permission is checked on a Google session level. But, endpoints like
/leavecan be used by
Viewers 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 the
Viewerpermissions. That is interesting, since by design only
Commenters should be able to chat, other roles can’t even see the chat pane.
- Changing the
Victim’s) in the
bundlesobject when making an edit with
Victim’s page, with the message
Unable to load file - Try to load it again or send an error report.. Other
Viewers will not crash, and if they have the
Live editsaccessibility pane enabled, they will see that the edit was made by
Victim. The edit initiator (
Attacker) will be correctly shown in the
- Changing the
Request first lineonly changes the user of the
selectioncommands. So, it looks like
Attackeris typing in the name of
Victim, but actually,
Attackeris only moving the cursor in the name of
Victim, and editing using her own account. So, checking
Version historywill correctly show that the edits were made by
- 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.
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.