Shopshifting: The potential for payment system abuse
Karsten Nohl, Fabian Bräunlein, and dexter.
This talk was at the same time as the New memory corruption attacks so I saw the recording.
- Cashier station to payment terminal: ZVT or OPI protocol.
- Payment terminal to payment processor over Internet: Poseidon protocol/ISO 8583. Many countries have their own dialect of ISO 8583.
Payment terminal: reads the card's mag stripe or PIN/chip.
ZVT in the shop over a network connection. Very old installations use a serial port and the protocol is designed for this, which shows.
Attack 1: Against the customer
ARP spoofing to get a man in the middle on the local network. Inside the shop or, if using wifi, even outside.
We send only a command “read the card”, then we have the mag stripe! Then we go ahead with the transaction.
But how do we get the PIN?
ZVT payment terminals are supposed to work with an HSM: the PIN shouldn't be seen outside.
ZVT has a function: “Display a text, then enter a number” but this function must be signed. Can we sign it ourselves?
To find a valid MAC... The HSM leaks the correct MAC through a timing side channel! They found an active JTAG on the main CPU and could talk to the HSM. Brute force of the first byte and count the response time. It's compared byte by byte in the HSM! Returns immediately if it doesn't match!
Attack 2: Against the merchant
ZVT allows local terminal hijacking.
ARP spoofing to become MITM like before.
Reset the terminal ID to your own terminal ID. The attacker needs to be a merchant as well and have a terminal ID.
There is no authentication between cashier and pay terminal.
Attack 3: Attack on Poseidon
Poseidon is a dialect of global payment standard ISO 8583. De facto standard in Germany.
Authentication uses pre-shared keys. However the key is the same for many, many terminals! This leaves just a user name: the terminal id. Which is public information and printed on receipts!
For the attack to succeed:
- Buy a payment terminal.
- Service management password. Just google for it! Or brute-force over ZVT, or read it out with JTAG...
- Your victim's Terminal ID. It's on the receipt! Or just guess. They are assigned incrementally, so if you know one good Terminal ID you know many others.
- Port number on the backend which your victim uses. Hundred different alternatives? Try them all!
Now you can, for example, print pre-paid call codes for your phone.
Another possibility is to “refund”, initiate a money transfer with a negative value! From any bank account! Completely independent from any earlier transactions.
Attack 4: Hardware
Buy a payment terminal on Ebay. It uses an internal HSM to protect secrets.
The HSM is a battery-backed SRAM under plastic cover. When a metal mesh in this plastic cover is breached the secrets are erased.
But the mesh is only connected in the corners. Can we get something under it? Yes! Inject a hypodermic needle and ground it. Ta-da! Then simply remove the lid.
There was an active JTAG port!
What can be done?
- Individual keys! Different keys for all payment terminals. The good news is that the Poseidon protocol can be used to distribute new keys.
- Switch off functionality that you don't need.
- Refund is activated by default. Turn off!
- Detect suspicious behaviour.
- Create better protocols.
The main ZVT alternative is OPI, Open Payment Initiative. OPI still lacks authentication and encryption even though it's from 2003!
Poseidon's family: ISO 8583. Dialects used everywhere. The bad system-wide symmetric keys are not mandatory in the protocol and key distribution through Poseidon possible.
New memory corruption attacks
Mathias Payer & Nicholas Carlini.
HexHive Group, https://hexhive.github.io/
Status of deployed defenses
- Data Execution Prevention, DEP. R-X on text segment. No new code can be injected, an attacker will have to use ROP or similar.
- ASLR - Address space layout randomization, harder to use ROP especially on 64 bit architectures, since gadget addresses are not known.
- Stack canaries. Place strategic values on the stack that shouldn't be overwritten.
- Safe exception handlers.
ASLR and DEP only effective in combination.
- Stack integrity
- Control-flow integrity
- Enforce dynamic restriction on return instructions.
- One example: protect return instructions through a shadow stack. Enforce on hardware label that we only can return to the calling function!
Control-flow integrity, CFI
- Never leave the control-flow graph.
- Find set of allowed targets for each location in compile time.
- Online set check: check if we're allowed this target.
New attacks: control-flow bending
Bend a valid graph... Not calling new code, but allowed targets.
Circumvent control-flow integrety.
CFI'S limitation: statelessness.
Each state is verified without context. Unaware of constraints between states.
Weak CFI is already broken. Lots of papers about it.
Microsoft's control-flow guard is an instance of a weak CFI.
- Precise control-flow graph: no over-approximation.
- Stack integrity through a shadow stack.
- Fully-precise static CFI: a transfer is only allowed if some benign execution uses it.
How secure is CFI? With and without stack integrity?
Analysis found a few functions, like
everyone uses. If everyone use them you can return to a lot of
functions and build ROP chains easily.
Result: CFI without stack integrity is broken.
When we add stack integrity to the mix we can greatly increase the protection of the current systems, then:
- ROP no longer an option
- attacks becomes harder
However: an interpreter will still be vulnerable!
And there's lots of interpreters out there! An example is
printf() format strings include: memory reads
%s, memory writes
%.#d, therefore: a Turing complete Brainfuck
interpreter. In printf formats!