Repository navigation
Conversation
The signed query strings in these tests were created at 2016-06-16 19:41:23 UTC. Running the tests at that time keeps them valid once the verification takes the request's timestamp into account.
Shopify signs every app proxy request with the current time, but AppProxyVerification only checked the signature, so a signed proxy URL stayed valid forever and could be replayed. Requests whose timestamp is missing, not a single integer, or more than 90 seconds from now are now rejected with 403, matching the tolerance in @shopify/shopify-api. The tolerance is configurable through app_proxy_timestamp_tolerance (seconds); nil disables the check.
Adds a breaking-change entry to the changelog, an upgrade note with the reason and the migration steps, and a paragraph on the timestamp check and app_proxy_timestamp_tolerance to the app proxy section of the engine docs.
Author
|
I have signed the CLA! |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does
ShopifyApp::AppProxyVerificationchecks the HMACsignatureof an app proxy request but never looks at itstimestamp. Shopify signs every proxy request with the current time, so a signed proxy URL never expires: anyone who gets hold of one (from request logs, an APM or error tracker, a log pipeline) can replay it against the app for as long as they like, acting as thelogged_in_customer_idit carries. Since the signature covers only the query parameters, the same query string also works on the app's other proxy paths.@shopify/shopify-apialready guards against this:validateHmacrejects app proxy requests whose timestamp is more than 90 seconds from now (HMAC_TIMESTAMP_PERMITTED_CLOCK_TOLERANCE_SECinlib/utils/hmac-validator.ts). This PR brings the Ruby gem in line:timestampis missing, not a single integer, or more than 90 seconds from the current time (in either direction) are rejected with 403, after the signature check.config.app_proxy_timestamp_tolerance(seconds, default90). Setting it tonildisables the check.travel_to), so they keep testing the signature as before.I came across this after seeing unusual requests to our own app's proxy endpoints: within seconds of a genuine storefront request, the same signed URL was sent directly to our server, once unchanged (accepted) and once with an altered signature (rejected). The signature check did its job, but the unchanged replay went through, and it would have kept working indefinitely. We've deployed the same check in our app. Tested through a development store's storefront, Shopify's own proxy requests arrived with timestamps only a few seconds old, well inside the tolerance.
Reviewer's guide to testing
bundle exec rake test TEST=test/shopify_app/controller_concerns/app_proxy_verification_test.rb. The new tests cover:timestampis rejectednildisabling the checkbundle exec rake test TEST=test/shopify_app/configuration_test.rbfor the default and the setter.Things to focus on
@shopify/shopify-apiand so existing apps are protected without changes. Requests forwarded by Shopify are unaffected, but apps whose own tests sign proxy requests without atimestampwill see those tests fail, so I marked it⚠️ [Breaking]in the changelog and added an Upgrading entry. Happy to make it opt-in instead, or to land it behind a different default, if you'd rather ship it in a minor release.app_proxy_timestamp_tolerancein plain seconds,nilto disable. Open to a different name or anActiveSupport::Duration.timestampis accepted, mirroring the hardening in Shopify/shopify-app-js (d282da59): decimal, negative, exponent and repeated values are rejected.Checklist
CHANGELOG.mdif the changes would impact usersREADME.md, if appropriate. (not needed: the README doesn't cover app proxies)/docs, if necessary (docs/Upgrading.md,docs/shopify_app/engine.md)@shopify/shopify-api, and exploiting the gap requires access to an app's own logs or infrastructure.