WP Manifestindependent plugin directory
manifest / ecommerce / exchange-addon-licensing

iThemes Exchange - Licensing Add-on WP Registry grade D+. High-severity findings · 2 findingsWP RegistryHigh-severity findings · 2 findingsOpen the reportD+

iThemes Exchange Licensing Add-on

★ 6stars
27release downloads
≈10active sites
v1.0.1latest · 10 years ago

Install

Download exchange-addon-licensing-1.0.1.zip From the v1.0.1 release on GitHub, Dec 16, 2015

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/iron-bound-designs/exchange-addon-licensing/releases/download/v1.0.1/exchange-addon-licensing-1.0.1.zip
Updates itself. It ships its own updater, so new versions appear under Dashboard → Updates.

Licensing add-on for iThemes Exchange

Licensing for iThemes Exchange allows you to sell license keys for your digital products.

Licensing is a commercial plugin available from Iron Bound Designs. The plugin is hosted here on a public Github repository in order to better faciliate community contributions from developers and users alike. If you have a suggestion, a bug report, or a patch for an issue, feel free to submit it here. We do ask, however, that if you are using the plugin on a live site that you please purchase a valid license from the website. We cannot provide support to anyone that does not hold a valid license key.

Installation

Stable

Download the latest version from the Releases tab on GitHub.

Trunk

Licensing uses composer for dependency management. After cloning the repository run the following command:

composer install --no-dev

Demo Data

Licensing comes with a bash script to create demo data. I recommend doing this on a clean WordPress install. Before running the import script, be sure to add at least one zip file to your media library. This is used to create demo products and releases.

From the main plugin directory run the following commands:

cd wp-cli
./demo-data.sh <size>

Size can be one of small, medium, large, or giant. I'd recommend sticking with small or medium, as the default Exchange admin won't scale well to a large purchase count.

Running the demo data script will create customers, product, releases, activations and renewal records.

  1. Recurring Payments. The Recurring Payments add-on allows you to limit the length of a license. It also allows you configure the license to auto-renew.

  2. Variants. The Product Variants add-on allows you to offer different activation limits depending on the type of license purchased. For example: individual, developer and unlimited license types.

  3. Stripe. The Stripe add-on is the easiest way to accept payments for your products. However, all payment gateways should work.

  4. wpMandrill. Licensing sends renewal reminders to your customers when their license key is about to expire. Additionally, emails can be sent to customers who have not yet updated to the latest version of your products. By installing the wpMandrill plugin, these notifications will be automatically sent out using Mandrill's HTTP API instead of wp_mail(). This should significantly improve the speed notifications are sent at.

  5. Manual Purchases. The Manual Purchases add-on allows you to manually create license keys if needed.

Help

Documentation can be found in our Help Center. Additionally, on every admin page has a Help tab with inline help for that screen.

HTTP API

Licensing comes with an HTTP API for handling product updates, site activations and deactivations, etc... The API is authenticated using Basic Auth for providing license keys and activation records.

A sample Plugin Updater and Theme Updater are provided. You can check these out to see how the API can be consumed.

WP CLI

Licensing has robust support for WP CLI. Just about anything you can do from the admin UI can be done via the command line. All commands are under the main itelic command followed by a grouping command.

For example this following will list the first 20 license keys:

wp itelic key list

This will disable the license key abcd-1234

wp itelic key disable abcd-1234

You can create a new release from the command line like so. This will create a new major release for the product with an id of 7. The new version will be 1.2 and the file ID used for updates is 7. This can be used in combination with the wp media import command to streamline how you release new updates for your software.

wp itelic release create --product=5 --version=1.2 --file=7 --type=major

Screenshots

Licenses

Edit License

Releases

New

New Release

Overview

Release Overview

Stats

Release Stats

Notification Editor

Release Notify

Reports

Renewals

Renewal Report

Licenses

Licenses Report

Installed Versions

Versions Report

Product

Edit Product

Releases

4 releases. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
v1.0.1 latest
Dec 16, 2015 10 years ago
exchange-addon-licensing-1.0.1.zip
15
Nov 11, 2015 10 years ago
exchange-addon-licensing.zip
6
Nov 3, 2015 10 years ago
exchange-addon-licensing-1.0-beta.zip
2
Oct 14, 2015 11 years ago
exchange-addon-licensing-1.0-alpha.zip
4

Active-site estimate ≈10 comes from the median of recent superseded releases. Method.

D+ grade

Security

iThemes Exchange - Licensing Add-on 1.0.1 · audited by WP Registry

High-severity findings.

2 high
Audited release
1.0.1
Findings
2
Worst severity
high
Content hash
8fa684b1a2183de944cdbd0f…

Findings

  • high Any logged-in user can read unused license-key inventory via AJAX

    missing_capability

    wp_ajax_itelic_get_key_type_settings is registered from Product\Feature\Base's constructor on every request. The handler takes $_POST['type'] and $_POST['product'] with no wp_verify_nonce and no current_user_can. It loads it_exchange_get_product_feature(..., 'licensing', field type.$type) and fires itelic_render_key_type_{type}_settings. For type=list that prints a textarea of remaining unused keys (the From-List generator pops the first line on each sale). A Subscriber POSTs admin-ajax.php?action=itelic_get_key_type_settings with type=list and a public product ID and receives the inventory. Those strings are not yet rows in wp_itelic_keys, but they become valid API credentials the moment a customer purchases; the attacker then uses PHP_AUTH_USER=<stolen key> against /itelic-api/activate and /itelic-api/product to burn activations and fetch the HMAC download URL for the paid release zip. type=pattern also leaks the generation pattern. Admin product-edit JS (itelic-add-edit-product.js) inserts the same HTML via jQuery.html() with no nonce either.

    lib/Product/Feature/Base.php:283-289

    Recommendation

    Require current_user_can('edit_post', $product) (or manage_options) and a nonce localized only on the product edit screen. Do not return remaining list keys to any role that cannot edit the product. Fail closed if type/product are missing.

  • high Checkout renewal key is unsanitized and not ownership-checked (stored XSS / IDOR)

    xss_stored

    process_purchase_requirement_renewal_checkout runs on init for any visitor who posts itelic_renew_keys_checkout + a valid itelic-renew-keys-checkout nonce. When the Exchange session slot for a product is null (logged-out Renew click, or a customer with multiple renewable keys), it copies $_POST['itelic_key'][$product] into the session with no sanitize and no check that the string belongs to the current user. save_renewal_info_to_transaction_object then stores that string as the transaction product's renewed_key. Sinks: ITELIC\display_renewal_on_confirmation_page echoes it on the confirmation and purchases pages; ITELIC\add_renewal_info_to_payments_screen echoes it unescaped on the admin transaction detail screen, so <script> in the posted key runs as the shop admin. If the string is a real third-party license, ITELIC\renew_key_on_renewal_purchase calls Key::renew() on it and apply_renewal_discount prices the cart from that key. Contrast: the sibling AJAX handler process_purchase_requirement_renewal_ajax does check it_exchange_get_current_customer_id() == $key->get_customer()->id.

    lib/hooks.php:635-650

    Recommendation

    Resolve $_POST['itelic_key'] through itelic_get_key(), require the key's customer ID to match the current customer, and store only $key->get_key(). Escape all echoes with esc_html(). Reject unknown keys instead of persisting arbitrary strings onto the transaction.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.