ShowMeCon2016 - Show Me Your Credit Card Tokens
-
Upload
tim-malcomvetter -
Category
Technology
-
view
271 -
download
1
Transcript of ShowMeCon2016 - Show Me Your Credit Card Tokens
ShowMeCon 2016@malcomvetter
About Me: Tim MalcomVetter (@malcomvetter)
• Local: Born & Raised in STL
About Me: Tim MalcomVetter (@malcomvetter)
• 15 Years in IT: Defender, Builder, Breaker
About Me: Tim MalcomVetter (@malcomvetter)
• Director, Red Team @ Fortune 1 (a.k.a. APT in 25th largest economy in the world)
About Me: Tim MalcomVetter (@malcomvetter)
• Presenter: BlackHat Arsenal, BSides, ArchC0N, Secure World Expo, Developer Conferences, etc.
About Me: Tim MalcomVetter (@malcomvetter)
• Spent too much time in school• (including a couple Univ of MO campuses)
About Me: Tim MalcomVetter (@malcomvetter)
• CVEs and ABC Soup
Disclaimer #1
• All content derives from my own opinions and does not represent my employer’s views or opinions.
@malcomvetter
Disclaimer #2
• All example requests/responses are sanitized examples observed from consulting clients from my prior life as a security consultant.
@malcomvetter
Agenda
• Refresher: Truncation vs. Tokenization• Tokenization Attacks:• Malicious Insiders vs. Tokenization Flaws• Side Channel Attacks• Careless Tokenization Software Bugs• DevOps, Tokenization, & You• RAM Scraping Servers
@malcomvetter
Quick Poll
How many Defenders?
@malcomvetter
Quick Poll
How many Builders?
@malcomvetter
Quick Poll
How many Breakers?
@malcomvetter
Quick Poll
How many Implemented Credit Card Tokenization?
@malcomvetter
Quick Poll
How many unsure if your transactions are tokenized?
@malcomvetter
Truncation vs Tokenization
@malcomvetter
Credit Card Truncation
@malcomvetter
Credit Card Truncation
6 digits in the middle
@malcomvetter
Credit Card Truncation
PAN: 4111-1111-1111-1111
Truncated: 4111-11XX-XXXX-1111
4 111 11 11 1111 111 1
Issuer Bank ID Account # Check Digit
@malcomvetter
Computational Complexity for Truncation
So how hard is it to guess the missing digits?
@malcomvetter
Computational Complexity for Truncation
106 = 1 Million Guesses (worst case)
@malcomvetter
Computational Complexity for Truncation
500K guesses (average case)
@malcomvetter
Computational Complexity for Truncation
Luhn Algorithm(a.k.a. “Mod 10” rule)
@malcomvetter
PAN: 4111-1111-1111-1111
Truncated: 4111-11XX-XXXX-1111
4 111 11 11 1111 111 1
Issuer Bank ID Account # Check Digit
@malcomvetter
Computational Complexity for Truncation
Last Digit is Check Digit(Luhn/Mod 10)
Computational Complexity for Truncation
So actually 105 = 100,000 Guesses (worst case)
@malcomvetter
Computational Complexity for Truncation
50,000 Guesses (average case)
@malcomvetter
Computational Complexity for Truncation
Easy to brute force offline!
@malcomvetter
PAN: 4111-1111-1111-1111
Truncated: 4111-11XX-XXXX-1111
4 111 11 11 1111 111 1
Issuer Bank ID Account # Check Digit
@malcomvetter
Computational Complexity for Truncation
PCI Allows Storage of Truncated PANs
PAN: 4111-1111-1111-1111
Truncated: 4111-11XX-XXXX-1111
4 111 11 11 1111 111 1
Issuer Bank ID Account # Check Digit
@malcomvetter
Computational Complexity for Truncation
PCI DSS 3.4 Warning(homework for later)
Credit Card Tokens
So what do tokens look like?
@malcomvetter
Credit Card Tokens
Tokens are typically derived values
@malcomvetter
Credit Card Tokens
hash68bfb396f35af3876fc509665b3dc23a0930aab1
@malcomvetter
Credit Card Tokens
subsitution4716-6290-9207-1441
(legacy systems)
@malcomvetter
Credit Card Tokens
Database ID or GUID4b3f7ce6-2228-4df8-adcd-8f807a4b37f6
@malcomvetter
Credit Card Tokens
EncryptedaL+zlvNa84dvxQlmWz3COgkwqrE=
(base64)@malcomvetter
Credit Card Tokens
Encrypted? Where are the keys??
@malcomvetter
Our Discussion Scope Today
Enterprise Targets
@malcomvetter
Our Discussion Scope Today
DIY / Self-hosted Tokenization
@malcomvetter
Our Discussion Scope Today
Large Scale Retail or eCommerce
@malcomvetter
Our Discussion Scope Today
Not Payment Gateways or Clearinghouses
@malcomvetter
Our Discussion Scope Today
(Although some principles carry over to service providers)
@malcomvetter
Our Discussion Scope Today
Not Attacking the Crypto!
@malcomvetter
Our Discussion Scope Today
Attacking the “seams” between payment & commerce
@malcomvetter
Our Discussion Scope Today
Be careful rolling your own tokenization
@malcomvetter
Malicious Insiders vs. Tokenization Flaws
@malcomvetter
A Malicious Insider …
Probably IT Support Personnel
@malcomvetter
A Malicious Insider …
(System/Network/DB Administrator or Developer)
@malcomvetter
A Malicious Insider …
Has access to Commerce App’s DB
@malcomvetter
A Malicious Insider …
Access to: Customer Billing Info
@malcomvetter
A Malicious Insider …
Access to: Truncated Credit Cards
@malcomvetter
A Malicious Insider …
Access to: Tokens
@malcomvetter
A Malicious Insider …
Has knowledge of Tokenization Architecture
@malcomvetter
A Malicious Insider …
Knowledge of: Web Service APIs
@malcomvetter
A Malicious Insider …
Knowledge of: URLs
@malcomvetter
A Malicious Insider …
Access to: Request Logs
@malcomvetter
Best Case Scenario
A Malicious Insider must…
@malcomvetter
Best Case Scenario
Enumerate Credit Cards == Truncation
@malcomvetter
Best Case Scenario
50,000 guesses (average case) per Credit Card record
@malcomvetter
Best Case Scenario
But Validation is Online, not Offline
@malcomvetter
Best Case Scenario
Live Transactions against Credit Card Auth Server
@malcomvetter
Best Case Scenario
Fraud Detection/Throttling Saves the Day
@malcomvetter
Worst Case Scenario
Tokenization URL is Internet Facing
@malcomvetter
Worst Case Scenario
Commerce App Performs Auth, but…
@malcomvetter
Worst Case Scenario
Payment Service Does NOT Auth Requests!
@malcomvetter
Worst Case Scenario
Payment Service Does NOT Auth Requests!
(Actually Quite Typical)
@malcomvetter
Worst Case Scenario
Why?
@malcomvetter
Worst Case Scenario
Payment Server Physically Separatedin PCI DMZ
@malcomvetter
Worst Case Scenario
@malcomvetter
Worst Case Scenario
Payment Server Physically Separatedin PCI DMZ
@malcomvetter
Worst Case Scenario
Payment Server Physically Separatedin PCI DMZ
(no sharing of session state)
@malcomvetter
Worst Case Scenario
Different DNS Domain for Payment Server
@malcomvetter
Worst Case Scenario
Different DNS Domain for Payment Server
(Session Cookies do not interchange)
@malcomvetter
Worst Case Scenario
No Request Throttling on Payment Service!
@malcomvetter
Worst Case Scenario
No Request Throttling on Payment Service!
(also quite typical)
@malcomvetter
Worst Case Scenario
No Request Throttling on Payment Service!
(Identifying abusers is difficult)
@malcomvetter
Worst Case Scenario
Sort of a Design Flaw 0Day…
@malcomvetter
Worst Case Example(based on actual retailers)
@malcomvetter
Worst Case Example
1. Customer checking out from store.example.com
@malcomvetter
Worst Case Example
2. Browser places payment request
(based on actual retailers)
@malcomvetter
Worst Case Example
POST /api/generateCcToken HTTP/1.1Host: payment.example.comConnection: keep-aliveAccept: */*Content-Type: application/jsonContent-Length: 51Cookies: […Session Cookies Here...] {"cc":"4111111111111111", "expmm":"12", "expyy":”17"}
@malcomvetter
Worst Case Example
Send it again, this time no cookies!
@malcomvetter
Worst Case Example
POST /api/generateCcToken HTTP/1.1Host: payment.example.comConnection: keep-aliveAccept: */*Content-Type: application/jsonContent-Length: 51 {"cc":"4111111111111111","expmm":"12","expyy":”17"}
@malcomvetter
Worst Case Example
Server Response (again, based on actual retailers)
@malcomvetter
Worst Case Example
HTTP/1.1 200 OKContent-Type: application/json {"token": "4a680016becd130b717e2f72562ceaadc9a1a5358578add7a68e4001df8416f6"}
@malcomvetter
Worst Case Example
No “Access Denied” response
@malcomvetter
Worst Case Example
No “Access Denied” response(even though no cookies)
@malcomvetter
Worst Case Example
Server just takes a PAN, gives you a token.
@malcomvetter
Worst Case Example
No cookies required.
@malcomvetter
Worst Case Example
No cookies required. (Why?)
@malcomvetter
Worst Case Example
Different Servers.Different Domain.
@malcomvetter
Worst Case Example
No sharing of data.
@malcomvetter
Worst Case Example
PCI Cooties.
@malcomvetter
Worst Case Example
Malicious Insider can …
@malcomvetter
A Malicious Insider Can …
1. Compute all PANs
@malcomvetter
A Malicious Insider Can …
1. Compute all PANs(based on truncated PANs)
@malcomvetter
A Malicious Insider Can …
1. Compute all PANs(50K guesses average case)
@malcomvetter
A Malicious Insider Can …
1. Compute all PANs2. Iterate through each
@malcomvetter
A Malicious Insider Can …
1. Compute all PANs2. Iterate through each
3. Submit Requests Anonymously
@malcomvetter
A Malicious Insider Can …
1. Compute all PANs2. Iterate through each
3. Submit Requests Anonymously(bonus points for botnet/mining/randomizing requests)
@malcomvetter
A Malicious Insider Can …
1. Compute all PANs2. Iterate through each
3. Submit Requests Anonymously4. If (response == token): Win!
@malcomvetter
A Malicious Insider Can …
You sunk my battleship!@malcomvetter
Worst Case Example
Throttling on the Payment Server is Difficult.
@malcomvetter
Worst Case Example
no unique cookies
@malcomvetter
Worst Case Example
no unique cookies(attacker could throw them away anyway)
@malcomvetter
Worst Case Example
Blocking by IP Address?
@malcomvetter
Worst Case Example
What about NAT’ed customers?
@malcomvetter
Worst Case Example
What about cloud/botnet attackers?
@malcomvetter
Worst Case Example
Split the load like bitcoin mining.
@malcomvetter
Worst Case Example
“Slow cook” the Payment Server
@malcomvetter
Potential Solution
How to solve this?
@malcomvetter
Potential Solution
Authentication Hand-off across domain boundaries
@malcomvetter
Potential Solution
Authentication Hand-off across domain boundaries
(a.k.a. federated authentication)
@malcomvetter
Potential Solution
POST /api/generateCcToken HTTP/1.1Host: payment.example.comConnection: keep-aliveAccept: */*Content-Type: application/jsonContent-Length: 161
{"authToken":"VGhpcyBpcyBqdXN0IGFuIGV4YW1wbGUuIEEgcmVhbCBvbmUgd291bGQgYmUgYmV0dGVyLg==", "cc":"4111111111111111","expmm":"12","expyyyy":"2017"}
@malcomvetter
Potential Solution
AuthToken must be generated by Commerce App Server
@malcomvetter
Potential Solution
(similar to Commercial Payment Processors which “sign” data elements)
@malcomvetter
Potential Solution
Don’t implement in JavaScript!
@malcomvetter
Potential Solution
Don’t implement in JavaScript!(attackers can unravel/replicate that logic)
@malcomvetter
Side Channel Attacks
@malcomvetter
Side Channel Attacks
My Favorite Variety of Attacks
@malcomvetter
Side Channel is:
Unintended Channels of Information Flow
@malcomvetter
Side Channel is:
Find a 1 or 0 in the Noise
@malcomvetter
Side Channel Attacks
Extra Credit Homework: Refer to Shannon’s Law
@malcomvetter
Side Channel Attacks
Side Channel #1: Timing Attacks
@malcomvetter
1. Timing Attacks
Very Difficult to Prevent
@malcomvetter
1. Timing Attacks
Seldom Considered by Developers
@malcomvetter
1. Timing Attacks
Inspiration comes from:
@malcomvetter
1. Timing Attacks
Inspiration comes from:1) Malicious Insiders with Truncated PANs
@malcomvetter
1. Timing Attacks
Inspiration comes from:2) Attackers who access a customer’s account
and view saved Credit Cards
@malcomvetter
The Trick:
Step 1: Submit previously unused PANs, record response times
@malcomvetter
The Trick:
Step 2: Submit a repeat batch, compare response times.
@malcomvetter
The Trick:
Step 3: Observe predictable deltas in response times.
@malcomvetter
Timing Attack Example
@malcomvetter
1. Timing Attacks
Previously Tokenized PANs take half as long to process
@malcomvetter
Timing Attack Example - Pseudocode
hash := sha256(Credit Card)dbResults := sql(select * from CC if hash=hash)if (dbResults > 0):
return dbResults[0]else:
sql(insert into CC (CreditCard))return hash
@malcomvetter
1. Timing Attacks
Did you catch the flaw?
@malcomvetter
1. Timing Attacks
New Tokens hit the DB twice, slows down response times
@malcomvetter
Timing Attack Example - Pseudocode
hash := sha256(Credit Card)dbResults := sql(select * from CC if hash=hash)if (dbResults > 0):
return dbResults[0]else:
sql(insert into CC (CreditCard))return hash
@malcomvetter
1. Timing Attacks
Response ~100ms == Actual Credit Card
@malcomvetter
Side Channel Attacks
Side Channel #2: MyProfile Attacks
@malcomvetter
2. MyProfile Attacks
Attacker steals customer’s session cookies or credentials
@malcomvetter
2. MyProfile Attacks
Attacker observes Truncated PANs
in “Saved Credit Cards”@malcomvetter
2. MyProfile Attacks
Developers: “But, our Commerce App does not even have Credit
Card data in it, just tokens!”
@malcomvetter
2. MyProfile Attacks
Okay.
@malcomvetter
2. MyProfile Attacks
(This affects literally hundreds of eCommerce applications right now.)
@malcomvetter
The Trick
Step 1: Submit a possible PAN to match a Truncated PAN
@malcomvetter
The Trick
Step 1: Submit a possible PAN to match a Truncated PAN
(using same billing information shown in profile)
@malcomvetter
The Trick
Step 2: Observe how many saved payment methods in “MyProfile”
@malcomvetter
The Trick
If count increased by 1, the Attacker guessed wrong.
@malcomvetter
The Trick
Bonus Points:
Delete the wrong credit card from the profile
(Automation)
@malcomvetter
The Trick
If count is the same, the Attacker wins!
@malcomvetter
The Trick
You sunk my battleship!@malcomvetter
The Trick
Force the server to provide a boolean logic response.
@malcomvetter
MyProfile Attack – Solutions
How to solve this?
@malcomvetter
MyProfile Attack – Solutions
Always add a new saved payment method
@malcomvetter
MyProfile Attack – Solutions
Always add a new saved payment method
(even if the billing info and PAN match previous)
@malcomvetter
MyProfile Attack – Solutions
This often has to be implemented on the Tokenization Server
@malcomvetter
MyProfile Attack – Solutions
(send the Commerce App a new token– don’t worry about token record
efficiency!)
@malcomvetter
Side Channel Attacks
Side Channel #3:Helpful Headers
@malcomvetter
3. Helpful Headers
Got RESTful G33ks?
@malcomvetter
3. Helpful Headers
RESTful G33ks ❤ Status Codes
@malcomvetter
3. Helpful Headers200 OK
201 Created202 Accepted
301 Moved Permanently302 Found
304 Not Modified400 Bad Request401 Unauthorized
404 Not Foundetc.
@malcomvetter
3. Helpful Headers
What if a token request results in:HTTP/1.1 201 CreatedContent-Type: application/json […snip…]
@malcomvetter
3. Helpful Headers
Instead of:HTTP/1.1 200 OKContent-Type: application/json […snip…]
@malcomvetter
3. Helpful Headers
Status codes indicate a token match, just like with MyProfile Attacks.
@malcomvetter
3. Helpful Headers
201 Created == NEW PAN/Token200 OK == PAN Hit!
@malcomvetter
Careless Tokenization Software Bugs
@malcomvetter
Oops!
Customer’s browsers accidentally sent PANs to the Commerce Server!
@malcomvetter
Oops!
How can this happen?
@malcomvetter
Tokenization Software Bugs
1) JavaScript bugs
@malcomvetter
Tokenization Software Bugs
2) Misunderstood Widgets in the Code Pile
@malcomvetter
Tokenization Software Bugs
3) Logic Edge Cases Not Tested in QA
@malcomvetter
Tokenization Software Bugs
Common in ASP.NET Web Forms(*.aspx)
@malcomvetter
Tokenization Software Bugs
Notorious for AJAX-ish “controls” and Partial Page Updates
@malcomvetter
Tokenization Software Bugs
Sends EVERYTHING in the form!
@malcomvetter
Tokenization Software Bugs
Example based on an actual retailer:
@malcomvetter
Tokenization Software Bugs
POST /CreditCardPayment.aspx?c29tZXBhcnRpYWx1cGRhdGVzdHJpbmdnb2VzaGVyZS1rdWRvc3RveW91Zm9yZGVjb2Rpbmd0aGlzIQ== HTTP/1.1Host: store.example.com:443X-Requested-With: XMLHttpRequestX-MicrosoftAjax: Delta=true[…snip…]ScriptManager1=upCcNumber&txtboxfname=Tim&cardNumber=4111111111111111&securityCodeNumber=123&txtboxlname=MalcomVetter&ddlExpMM=01&ddlExpYYYY=2017[…snip…]
@malcomvetter
Tokenization Software Bugs
Oops.
@malcomvetter
Solution is Simple
Don’t mix AJAX controls on Payment Pages
@malcomvetter
JavaScript Tokenization Bugs
Example listening to onkeypress()
@malcomvetter
JavaScript Tokenization Bugs
Intent: determine card type (e.g. Visa, MasterCard, etc.)
as the first 4-6 digits are typed
@malcomvetter
JavaScript Tokenization Bugs
POST /api/ccType HTTP/1.1Host: store.example.comConnection: keep-aliveAccept: */*Content-Type: application/jsonContent-Length: 55 {"ccPrefix":"41111111"}
@malcomvetter
JavaScript Tokenization Bugs
The JS accidentally sent a request after EACH KEY PRESS!
@malcomvetter
JavaScript Tokenization Bugs
4…
@malcomvetter
JavaScript Tokenization Bugs
41…
@malcomvetter
JavaScript Tokenization Bugs
411…
@malcomvetter
JavaScript Tokenization Bugs
4111…
@malcomvetter
JavaScript Tokenization Bugs
41111…
@malcomvetter
JavaScript Tokenization Bugs
411111…
@malcomvetter
JavaScript Tokenization Bugs
eventually...
@malcomvetter
JavaScript Tokenization Bugs
4111111111111111boom.
@malcomvetter
JavaScript Bugs
Another Example:
@malcomvetter
JavaScript Bugs
Commerce App set generic <form> tag on Payment Page
@malcomvetter
JavaScript Bugs
JS sets target to Payment Server
@malcomvetter
JavaScript Bugs
JS fails to load/execute
@malcomvetter
JavaScript Bugs
PANs sent to Commerce Server instead of Payment Server
@malcomvetter
JavaScript Bugs
Oops.
@malcomvetter
DevOps, Tokenization, & You…
@malcomvetter
Malicious DevOps Admins
Tokenization often relies on JS in the Browser
to Direct PANs to the Payment Server
@malcomvetter
Malicious DevOps Admins
JS doesn’t require a build/deploy
@malcomvetter
Malicious DevOps Admins
What if your DevOps admin edits the JS files on the web server?
@malcomvetter
Malicious DevOps Admins
Got integrity checking on JS files in webroot?
@malcomvetter
Malicious DevOps Admins
Got integrity checking on JS files in webroot?
(I’ve yet to see anyone do that.)
@malcomvetter
Malicious DevOps Admins
For example, modify JS tosend a copy of PANs to evil.com
@malcomvetter
Malicious DevOps Admins
Then redirect to payment.example.com
@malcomvetter
Malicious DevOps Admins
With JS, no Continuous Integration Builds Required!
@malcomvetter
Malicious DevOps Admins
What about intentional JS defects that leak PANs to the Commerce Server the
DevOps Admins can access?
@malcomvetter
Malicious DevOps Admins
What logging is in place on your web servers?
@malcomvetter
RAM Scraping Web Servers
@malcomvetter
A Note on RAM Scraping
Not just for Point of Sale Systems
@malcomvetter
A Note on RAM Scraping
If your Web Server accepts PANs, orIf your Web Server decrypts PANs
Then PANs are in Web Server’s RAM
@malcomvetter
A Note on RAM Scraping
(probably for several minutes or hours)
@malcomvetter
RAM Scraping
DevOps Admin: “I need to profile this service.”
@malcomvetter
Q&A
Twitter: @malcomvetterlinkedin.com/in/malcomvetter