Audit ATM – Replay Attack

ATMs have been an integral part of our lives for several decades now. But is the money really safe?

Over the past few years, we have had several opportunities to audit and execute penetration testing at various ATM manufacturers and vendors, and not limited to the Czech Republic. Over the course of the audit, we examined all the known vulnerabilities, both at the XFS layer and at the operating system layer. And naturally, we checked the physical security as well, as described by my colleagues in their article on ATM Security.

We got our hands on many applications providing an interaction with the ATM client and peripherals. The key finding was the discovery that each manufacturer applies its own solution, there is no standard or concept they would adhere to. During the audit, we came across applications written in various programming languages, such as C#, C++, Java, and many others. Most of them integrated the GUI in HTML as the primary interface for communication with the client, i.e. the things the client sees on the screen during operations on the ATM. The majority of the screens that a normal user sees during transactions are essentially pure HTML, controlled by one of the above-mentioned applications. These HTML pages are loaded from various service directories. It is quite clear why, since it is necessary to have room for quick updates, especially of advertisements.

So, the majority of ATMs are based on the following principle:

Basic ATM concept.
Basic ATM concept.

A service or an application launched at start, first executes a huge number of checks of all interfaces and availability of home servers and if there are no errors, it loads HTML pages and displays them on the ATM’s screen. ATMs in passive mode usually display advertising messages. In case the checks at the start fail, a notification will be displayed apologizing for the unavailability of the ATM. Passive mode changes at the moment when the client approaches the ATM and inserts the payment card into it. Immediately after inserting the card the screens for entering the pin are loaded and then, depending on the selected activity, for example pages for withdrawal, deposit, payment, checking the balance, pin change and many other operations, depending on the bank and the ATM type.

When a transaction is being selected, there is a function of the application called in the background that subsequently usually calls the XFS layer directly. This layer is then used for the communication with individual peripherals, such as pinpad, dispenser, printer, camera, and many others. The XFS layer is essentially the only standardized component of the whole ATM. The rest is fully in the hands of the manufacturer and the distributor. So with one of the tested ATMs, it happened that we came across a rather strange functionality which caught our eye, so we tried to examine it closer.

There was an application running on the ATM opening a large number of ports listening only on the loopback after the ATM was started. Then we could see the following information in the netstat statement, for example:


The listening ports and established connections would not have to present a problem, since the connection is established only within the loopback, therefore no one from the external network can access the ports and communication. Moreover, present ATM models are using new versions of Windows including the properly set up filtering on the integrated Firewall.

Nevertheless, we decided to go and examine what communication is taking place on these listening ports and who addressed the listening ports. Since we already had our rights elevated to the local administrator, we ran a sniffer that can eavesdrop on the loopback communication and tried to make an end-to-end withdrawal from the ATM including the printed confirmation of the transaction.

Then, after we analysed the intercepted traffic, we were instantly surprised that no authentication is required if data is sent to a particular port. We also discovered that during the withdrawal from the ATM, several ports were addressed and the communication which took place there was always partially binary. But it also contained readable information in XML format. After a more detailed analysis, we found out that 5 bytes of binary data is sent before each XML. A quick analysis revealed that it was basically a protocol header using these 5 bytes to define the length of the following transmitted data.

Intercepted communication – header analysis.
Intercepted communication – header analysis.

For example, the intercepted communication in the figure above contains a header with bytes DD 41 01 00 00:

  • DD – is most likely a delimiter between individual messages, but we are only assuming this, since it always occurred before the transmission of the following header and message.
  • 41 01 – is the HEX entry for the length of the following data. In this case it is 321 bytes of the body of the message, which definitely corresponds to the length of XML message.

We were still curious, so we tried a few more similar transactions. Again, we analysed the intercepted communication, but this time, we focused mainly on the body of the message, i.e. the XML as such. We found it interesting that the data sent to the port of the service serving the dispenser does not differ much. Only in a few bytes. A closer analysis revealed that it was only in the amount we requested a client to withdraw from the ATM as a customer. The XML did not include any checksum, no unique ID, or HMAC, nothing that could prevent a "Replay Attack".

So what could be done? We could try and send a packet header, a packet with XML and the required amount to the port of the service serving the dispenser. So we did it. We used one of our tools for sending arbitrary binary data via TCP protocol. We sent packets extracted from the sniffer directly to the listening service serving the dispenser port 50000. A well-known sound could be heard, and the dispenser began extracting banknotes from the cartridges in the vault. However that was the end of it, the money didn't slide out of the ATM. So we tried to send the same packet again, and again, with the same result, i.e. the sound of counting banknotes, but the shutter remained closed. We were perplexed at first, we thought that the ATM should also give us the money. So we went through the previously intercepted communication again. And we identified that the packet sent to the service serving the dispenser was followed by another packet for the extension of the card from the card reader, and only the packet sent after that addressed the service of the dispenser and also the shutter itself.

Intercepted communication for the withdrawal of 10 EUR – flow analysis.
Intercepted communication for the withdrawal of 10 EUR – flow analysis.

Communication analysis by individual packets:

  • Packet 342 – port 50000 – message header, binary data (5 bytes).
  • Packet 343 – port 50000 – contains XML with XFS commands, request for the withdrawal of 10 EUR (ulAmount 0xa).
  • Packet 344 – port 50000 – is the server answering that everything is OK.
  • Packet 345 – port 50002 – message header, binary data (5 bytes).
  • Packet 346 – port 50002 – contains XML with XFS command arranging for the return of the card from the Card Reader.
  • Packet 347 – port 50002 – message header, binary data (5 bytes).
  • Packet 348 – port 50002 – is the server answering that everything is OK (XML data).
  • Packet 349 – port 50000 – message header, binary data (5 bytes).
  • Packet 350 – port 50000 – contains XML with XFS command, request to open the shutter.

So, we extracted additional packets from the intercepted communication and sent them to the service serving the dispenser again.


ATM opened shutter after receiving the packet and we were able to withdraw money counted by the previous unsuccessful attempts.

If one thinks about the way a withdrawal from an ATM works, it must be immediately clear why several requests need to be sent to the ATM. Let’s walk through the flow of money withdrawal.

After entering the PIN, the client selects an activity, such as withdrawal, then they enter the amount and confirm it and then they can also choose whether they want a receipt. After confirming and verifying the correctness of the PIN, the dispenser starts working and counts the required amount, moves it to the shutter, but leaves it closed yet. Then the ATM usually emits an audible signal and returns the card to the client, and only after the card has been removed, it opens the shutter and the client can take the required amount.

This is the reason why the withdrawal has to be executed with two packets. One addresses the dispenser and counts the amount, the second one opens the shutter.

In the end we created basic application for withdrawal from ATM without a credit card. It uses replay attack.
In the end we created basic application for withdrawal from ATM without a credit card. It uses replay attack.

Basic glossary:

  • Card Reader – card reading mechanism.
  • Dispenser – mechanism over the vault section of ATM controlling the withdrawal of required banknotes from the vault section of ATM.
  • Shutter – compartment for withdrawal or deposit of money.