# Pranav Hivarekar

NOOB | SECURITY RESEARCHER | PUBLIC SPEAKER

Posted by Pranav Hivarekar on Feb 11, 2017

## Description

There are various Facebook products like Ads Manager, Business Manager, Messenger Payments, etc. which requires an `user` to add some payment method to their Facebook account which can be credit card, debit card, paypal, etc.
eg. If I want to run Facebook Ads then I need to add a `credit card` or any other relevant payment method so as to use it. Same is with other products.

Facebook assigns a unique `15 digit random number` to any `card` added to user's Facebook account and this `id` is known as `credential id`. This `credential id` is then used by Facebook to query about `credit card` details.

This `credential id` was querable via `GraphQL` and it allowed an attacker to use it(credential id) to get `credit card` details. But it exposed last 4 digits, address, expiry date, etc.

## How one can get `credential id`?

There are few methods to get `credential id` of your `card`...

1] I had reported a bug last year where `Ad Analyst` was able to escalate privileges and was able to access `funding sources` of the Ad account. This leaked the `credential id` of the payment method. Unfortunately this bug went duplicate but I was still able to use it to demonstrate the flaw.

2] Brute Force / Dictionary attacks :
We need to form 15 digit numbers so calculations are as follows...

1. We have digits [0-9]
2. We have 15 places
3. 1st digit can be [1-9] i.e only 9 combinations
4. Other 14 digits can be anything [0-9] i.e 10 combinations
So,
9x10^14 =
10^14 = 100000000000000 = 100000 billion
9x10^14 = 900000 billion combinations

This covers all the 15 digit numbers. We need ONLY 900000 billion numbers. This seems to be practically possible as it may take few weeks to do so.

But even if we consider it impossible, one can generate numbers in range like generating number from `931000000000000 to 999999999999999`. This will be a lot quicker than previous one. Also, if we reduce the range and only brute force `last 6-8 digits` still we can generate a lot of valid 15 digit numbers.

So, now we assume that we can generate a large amount of valid unique `15 digit` number.

*Note : I avoided running the real brute force/dictionary attack as it would get me access to real `credential ids` of real users which voids Facebook's terms. Instead, to prove my point I provided POC of my test accounts where I was able to show that brute force attack may work to get access to credit card details.

3] Other methods:
Ad account Admin removed from the Ad account having noted these ids can still use it now and get access `credit card` details.

Similarly, it applies to Business Manager as it has a separate `payment management`. A user having access to Business Manager but now removed from it can still have `credential ids`.

## Proof Of Concept

1] Get an `access_token` which can access `graphql`. This token can be obtained by observing requests/responses of your Android/IOS Facebook app or other Facebook owned apps.

2] Now, get yourself a `credential id` via any of the methods listed above.

3] Encode the `credential id` in order to form a string as `base64encode(p2p_credential_id)`.
eg. base64encode(p2p_999999999999999) --> cDJwXzk5OTk5OTk5OTk5OTk5OQ==

4] Make following graphql calls ...

*Note : (Use `access_token` which you derived in Step 1)

``````REQUEST

POST /graphql?q=node()
{
__typename,
id,
credit_card{
credential_id,
card_association,
number,
expire_month,
expire_year,
__typename,
postal_code ,
street,
city,
country,
postal_code
}
},
mobile_csc_verified,
zip_verified,
web_csc_verified,
method_category,
commerce_payment_eligible,
personal_transfer_eligible,
is_default_receiving
}

RESPONSE

{
"": {
"__typename": "PeerToPeerPaymentMethod",
"id": "",
"credit_card": {
"credential_id": "",
"card_association": "VISA",
"number": "",
"expire_month": "",
"expire_year": "",
"postal_code": "",
"street": "",
"city": "",
"country": "US"
}
},
"mobile_csc_verified": true,
"zip_verified": true,
"web_csc_verified": true,
"method_category": "DEBIT_CARD",
"commerce_payment_eligible": false,
"personal_transfer_eligible": true,
"is_default_receiving": false
}
}

``````

5] Here, my `credit card` details(last 4 digits, expiry details, card association,etc.) and other sensitive information(address, etc.) are leaked.

NOTE : Please note that `credential id` is never deleted from Facebook. So, anyone can access the details even if card is removed or account is deactivated.

## How one can exploit it?

1. Try to form a valid credit card :
According to my research, it is possible to validate a credit card number using Luhn algorithm (https://en.wikipedia.org/wiki/Luhn_algorithm). One can generate a large set of `credit card details` then filter out the credit cards based on `last 4 digits and pincode and expiry date`. This will return a very small set of valid credit cards. Later, cvv number can be brute force or any alternative attack can be done if we have valid credit cards.
This attack is sophisticated and will require a lot of time but it is not practically impossible.

2. Hacking combined with social engineering :
One can play smart and can make use of these details to compromise one's apple account or amazon account or other things
Reference : https://www.wired.com/2012/08/apple-amazon-mat-honan-hacking/all/

One can even think of innovative ways to use these stolen credit card details.

## Impact

Once attacker knows the `credential id` then attacker can access credit card details which exposed the following:

1. last 4 digits
2. expiry date
4. country and other relevant details

Facebook determined that brute force attack may take a long time but considering other methods they patched the bug by placing permission checks on the endpoint. Now, users can only access their own credit cards.

## Special Thanks

Thanks to Facebook for patching the vulnerability and all my friends who are supporting me for my work.

## Timeline

January 1, 2017 at 11:35pm - Report Sent
January 13, 2017 at 6:22pm - Initial Response by Facebook