~3 mins

Disclose Facebook Server Info With A Strange Poll

Chat Group Poll’s question type are expected to be only multiple-vote (i.e. CHOOSE_MULTIPLE) on both client-side and server-side. By updating a single-vote (i.e. CHOOSE_ONE) Chat Group Poll with multiple votes, the server does not know how to handle it.

Hypothesis

When the TAO/Database server is associating the first vote on a single-vote poll, everything is fine. However, since it never expected to associate the second vote on the same single-vote poll, it will cause error on TAO/Database side.

Impact

It exposes:

  • Details of the database operation errors
  • Database ID
  • Server Host and Port
  • Cache identifiers
  • TAO version
  • Server’s data directory structure
  • showUser

None of these should have been made publicly-available.

Reproduction Steps

Step Zero: Ingredients

For this recipe, you will need:

  • A accesstoken that is created for Facebook Messenger for Android (for this PoC, let’s say accesstoken = TOKEN)
  • A chat group on Messenger (for this PoC, threadid = `THREADID`)
  • A user that owns the above accesstoken and part of the above chat group (for this PoC, userid = USER_ID)
  • A GraphQL Persisted Query Document that creates a Group Poll (for this PoC, docid = `DOCID`)

Step One: Create a Chat Group Poll using Graph API

variables.input.question_type must be CHOOSE_ONE variables.input.answers_state must be OPEN CHOOSE_ONE is the key part for making the error in Step 2 possible.

HTTP Request

HTTP POST https://graph.facebook.com/v3.0/graphql
access_token=TOKEN
doc_id=DOC_ID
variables={
  input: {
    client_mutation_id: 1,
    actor_id: ACTOR_ID,
    question_text: 'Any Text',
    question_type: 'CHOOSE_ONE',
    answers_state: 'OPEN',
    target_id: THREAD_ID,
  }
}

HTTP Response

{
  "data": {
    "create_group_poll": {
      "question": {
        "id": "(redacted_question)"
      },
      "error_code": "1545015",
      "error_title": "Unknown Error",
      "error_message": "Something went wrong. Please try again."
    }
  }
}

Based on Reponse, data.creategrouppoll.question.id = (redacted_question)

Therefore, we will use (redacted_question) for the Chat Group Poll Question ID.

Step Two: Updating the CHOOSE_ONE Chat Group Poll with multiple votes

new_options must be an array with 2-100 elements (2 being more than ‘ONE’, 100 due to vote amount limit)

AsyncRequest (in JavaScript)

uri = '/messaging/group_polling/update_vote'
data = {
  question_id: '(redacted_question)',
  new_options: ['Foo', 'Bar']
}

HTTP Response

{
  "__ar": 1,
  "payload": {
    "status": "failure",
    "errorMessage": "(redacted)",
    "showUser": null //redacted
  },
  "bootloadable": {},
  "ixData": {},
  "gkxData": {},
  "lid": "(redacted)"
}

Based on Response, payload.errorMessage is unusually verbose, and contains:

  • Details of the database operation errors
  • Database ID: (redacted)
  • Server Host: (redacted)
  • Cache: (redacted)
  • TAO version: (redacted)
  • Server data directories
  • showUser: (redacted)

The details in this errorMessage should have been hidden with something like “Something went wrong. Please try again” instead.

Timeline

2018-06-29: Report Submitted

2018-06-29: Request for additional details by Facebook

2018-06-29: Additional details sent

2018-06-29: Request for additional details by Facebook

2018-06-29: Clarification sent

2018-07-02: Request for additional details by Facebook

2018-07-02: Clarification sent

2018-07-03: Request for additional details by Facebook

2018-07-03: Clarification sent

2018-07-04: Further Investigation by Facebook

2018-07-20: Fixed by Facebook

2018-08-01: Bounty Awarded by Facebook