FREE: Secure Your EDD Stripe Keys – Fortress Vaults & Pillars in Practice

| in


Introduction

In this guide, we’ll walk you through the process of securing your Easy Digital Downloads Stripe keys using Fortress Vaults & Pillars. By the end of this tutorial, your sensitive Stripe keys will be securely encrypted, and the risk of malicious access will be significantly reduced.

We will be using the following Software versions:

Note: This tutorial is part of a series demonstrating how to implement Fortress Vaults & Pillars across various plugins. If you’re unfamiliar with Fortress Vaults & Pillars, you may first want to read our comprehensive introduction to understand the full context and learn how to get FREE access.

The Status Quo

In EDD, sensitive Stripe keys are stored in plaintext within the WordPress options table. This practice leaves your site vulnerable to malicious attacks, potentially exposing confidential information to unauthorized users if any plugin or theme on your site contains SQL-Injection vulnerabilities.

EDD itself had an SQL-Injection vulnerability as recently as January 2023.

It’s essential to recognize that EDD does not utilize restricted Stripe keys as of the current version. This leaves the compromise of API keys an extremely critical vulnerability with potentially devastating consequences.

If an attacker were to access these keys, they might be able to:

  • Commit Fraud: An attacker can initiate fraudulent transactions by gaining access to your Stripe keys. A recent example is a WordPress Agency that experienced a $70k fraud due to compromised Stripe keys.
  • Delete Customers & Subscriptions: A disgruntled hacker could erase all your valuable customer data and subscriptions, causing existential disruption to your business.
  • Gain Unauthorized Access to Sensitive Data: Stripe keys grant unrestricted access to all data in your account, such as sensitive customer data, leading to potential privacy breaches and legal liabilities.
A screenshot that shows how EDD uses Stripe's Oauth flow to get access to the API keys with little friction for the end-user.
EDD uses Stripe’s Oauth flow to get access to the API keys with little friction for the end user.

After connecting our Stripe Account to EDD, we can assert that our API keys are indeed stored as plaintext in the wp_options table.

 wp option list --search=edd_settings* --unserialize --format=json | jq '.[].option_value'
{
  "purchase_page": 6,
  "success_page": 7,
  "failure_page": 8,
  "purchase_history_page": 9,
  "confirmation_page": 10,
  "stripe_elements_mode": "payment-elements",
  "test_mode": "1",
  "gateways_order": "",
  "payment_icons_order": "",
  "test_publishable_key": "pk_test_51HFiwWH81jF8atYWAArpOXx6XJpg8GgZKDVIpTfll1vG8ogU8V9GcS7ywMW7TT4e9avPehZEYdKTfUW1yCuuytFH00UlA9wDJS",
  "test_secret_key": "sk_test_VALUE_SANITIZED_BY_EDITORIAL_TEAM",
  "stripe_connect_account_id": "acct_VALUE_SANITIZED_BY_EDITORIAL_TEAM",
  "stripe_connect_account_country": "de"
}

Step-by-Step Guide to Adding Vaults

We’ll now walk you through using Fortress Vaults & Pillars to secure the required sensitive data within the plugin.

Note: If you’re unfamiliar with Fortress Vaults & Pillars, refer to the announcement and check the developer documentation for more information.

Finding the Correct WordPress Option

Jump to the final configuration.

Before securing sensitive data, we must identify the specific WordPress option where EDD stores the Stripe keys. There are several ways to do this, but we will use WP-CLI for our demonstration.

First, list all option names starting with “edd” with the following command:

wp option list --search=edd* --unserialize --format=json | jq '.[].option_name'

The output will be something like this:

"edd_activation_date"
"edd_completed_upgrades"
"edd_default_api_version"
"edd_licensed_extensions"
"edd_settings"
"edd_tokenizer_signing_key"
"edd_use_php_sessions"
"edd_version"
"edds_notice_edd-stripe-core_dismissed"
"edds_stripe_version"

Here, we’ve identified the correct option name:

edd_settings

Now, we can find the correct sub key for the Vaults by running:

wp option list --search=edd_settings* --unserialize --format=json | jq '.[].option_value'

The result will be a JSON object showing the keys and values:

{
  "purchase_page": 6,
  "success_page": 7,
  "failure_page": 8,
  "purchase_history_page": 9,
  "confirmation_page": 10,
  "stripe_elements_mode": "payment-elements",
  "test_mode": "1",
  "gateways_order": "",
  "payment_icons_order": "",
  "test_publishable_key": "pk_test_51HFiwWH81jF8atYWAArpOXx6XJpg8GgZKDVIpTfll1vG8ogU8V9GcS7ywMW7TT4e9avPehZEYdKTfUW1yCuuytFH00UlA9wDJS",
  "test_secret_key": "sk_test_VALUE_SANITIZED_BY_EDITORIAL_TEAM",
  "stripe_connect_account_id": "acct_VALUE_SANITIZED_BY_EDITORIAL_TEAM",
  "stripe_connect_account_country": "de"
}

We highlighted all sensitive sub-keys stored as part of the option.

Creating the Final Configuration

Now that we identified all sensitive parts of the EDD Stripe Settings, we can use the following configuration to turn all of them into Vaults:

{
  "vaults_and_pillars": {
    "option_vaults": {
      "edd_settings.test_secret_key": {},
      "edd_settings.live_secret_key": {},
      "edd_settings.stripe_connect_account_id": {}
    }
  }
}

We also added the edd_settings.live_secret_key option. EDD determines whether to use the live or test secrets based on configuration settings:

public function set_api_key() {
    $secret_key = edd_get_option( ( edd_is_test_mode() ? 'test' : 'live' ) . '_secret_key' );

    Stripe::setApiKey( trim( $secret_key ) );
}

Note: Refer to the developer documentation for more information.

The Final Result

All sensitive Stripe data is now stored securely encrypted.

{
  "purchase_page": 6,
  "success_page": 7,
  "failure_page": 8,
  "purchase_history_page": 9,
  "confirmation_page": 10,
  "stripe_elements_mode": "payment-elements",
  "test_mode": "1",
  "gateways_order": "",
  "payment_icons_order": "",
  "test_publishable_key": "pk_test_51HFiwWH81jF8atYWAArpOXx6XJpg8GgZKDVIpTfll1vG8ogU8V9GcS7ywMW7TT4e9avPehZEYdKTfUW1yCuuytFH00UlA9wDJS",
  "test_secret_key": "FORTRESS_VAULT|MUIEAAbDtDvlTNLnsJCgt8JpRXI0DE24W6xTsGq_0Mhr-Ub9aHRnzMLUkTgaKbDuCQwcHpy9xgwibY53zzuVvy3qghJsMgMt8xOhAIHXPyPsAVlOyxIWNTslgsSXQseIQtTEFUfm7OXbglrCrKVYsHSAYmuhout_uISOXEgce_XW38hUgne2iwmZhHLl5WcNTVrtY-0TxDBgGgMfIRMaFoUaXI7Ble4R7mRWzumHZ9utvX-36-V7Mm7GFhJ9kLD22ZwnsrFb4-j2PhNulQ8G-fq5iBZ3MQUsSFSpNbhGiHZ8s4zU1Jva1JhFhhXfWq2H",
  "stripe_connect_account_id": "FORTRESS_VAULT|MUIEAOq0krDQHIlkQ0Zbyp-J4NOJST_75SL5erpf2gPTJ9hHkbCWRVeS_LPHRWGrO348eM8W6TqEfMN9M72PJU_7v7mlIsmsG9j8flh55vdILvKxjEtZOlgrHaPVTajRFoWTSFIOwP6OrE0HwkTnlBrAw6Zv0XFSO9xmPs9Eh47gqiDu0uRZqGp_H_xAm_d_K39ECl7WUxul",
  "stripe_connect_account_country": "de"
}

Let’s now verify that everything, indeed, still works by checking our EDD Stripe Connection status.

You can do so by navigating to “Downloads => Settings => Payments => Stripe => Connecting Status“:

A screenshot showing that EDD can still connect to our Stripe Account even though the API keys are stored securely encrypted.
EDD can still connect to our Stripe Account even though the API keys are stored securely encrypted.

Note: This is not an exhaustive list of sensitive data in EDD.

At the bare minimum, you’ll also want to turn API keys of other payment gateways (PayPal, etc.) into Vaults.

Get FREE Access to Fortress Vaults & Pillars and Secure Your Plugins Now!

Now that you’ve seen how Fortress Vaults & Pillars can add an essential layer of security to plugins without requiring codebase changes, it’s time to take action.

Explore our announcement post to learn more and get FREE access to Fortress Vaults here.