HexBrain

Shopify · Report #1086108

[h1-2102] FQDN takeover on all Shopify wholesale customer domains by trailing dot (RFC 1034)

Validstatus
mediumseverity
$3,100bounty
166upvotes
25 Mar 2021disclosed

Summary

Check out my show and tell: https://youtu.be/LSwWQPQ5IG8

How it was found

Summary:

Due to a missing domain format check in Shopify's wholesale functionality, it is possible to serve arbitrary content on the customer's domain through existing DNS records already configured to work with Shopify. I only tested with domains that I own but as far as I understand, this would work with just any domain or subdomain that it set up to work with Shopify wholesale.

This exposes Shopify wholesale customers to several risk, similar to classic subdomain takeovers:

  • Loss of domain integrity: attackers could host malicious content on the customer's domain
  • Phishing attacks: attackers could use login/sign up page to capture PII and
  • Scams: scammers could recreate trusted wholesale shops, host them under the official domain and collect money

Steps To Reproduce:

{F1170259}

In real-life attacks, attackers could perform reverse CNAME lookups through e.g. Alien Vault's OTX.

  • Now log in as attacker and try to add shop.inti.io as a domain name in your preferences. This will not work, because there's already a store attached to it:

{F1170265}

  • Attacker now sits down, takes a nip of coffee and reads RFC 1034. Attacker notices the following:
Since a complete domain name ends with the root label, this leads to a
printed form which ends in a dot.  We use this property to distinguish between:

   - a character string which represents a complete domain name
     (often called "absolute").  For example, "poneria.ISI.EDU."

   - a character string that represents the starting labels of a
     domain name which is incomplete, and should be completed by
     local software using knowledge of the local domain (often
     called "relative").  For example, "poneria" used in the
     ISI.EDU domain.

In theory, all domain names should have a trailing dot at the end, but since literally no one does that both a domain name with and without a trailing dot will essentially result in the same records being served. Since Shopify does not implement DNS-based verification and only checks whether the record is already present, we can enter the trailing dot version of the domain name to bypass this check:

{F1170267} {F1170268}

  • Now attacker waits for a few minutes to allow the DNS / SSL changes to propagate. Depending on your browser's cache, it can take a while, but normally after a few minutes the malicious shop should pop up at https://shop.inti.io./accounts/sign_in.

Final results

Real store: https://shop.inti.io/accounts/sign_in

{F1170269}

Hijacked store: https://shop.inti.io./accounts/sign_in

{F1170270}

Note to triagers - I have released shop.inti.io. in my shopify so you can claim it and reproduce. This means that the hijacked store is no longer accessible.

This could be done by anyone for any wholesale connected store, without having access to the DNS records.

Recommended fix

Do not consider trailing dots when checking whether domain names already exist on your back-end

Supporting Material/References:

*Trailing Dots in Domain Names, CHESHIRE S., http://www.dns-sd.org/trailingdotsindomainnames.html

Impact

This exposes Shopify wholesale customers to several risk, similar to classic subdomain takeovers:

  • Loss of domain integrity: attackers could host malicious content on the customer's domain
  • Phishing attacks: attackers could use login/sign up page to capture PII and
  • Scams: scammers could recreate trusted wholesale shops, host them under the official domain and collect money

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original