A Tale of an OFTP2 Vulnerability

This is a guest post from Thomas Smits.

A long time ago in a galaxy far, far away….

In my ordinary life, I teach computer science at the University of Applied Sciences in Mannheim but for some months, I was an intern at ERNW learning a lot about IT security and penetration testing. One of these learnings is that old protocols can be fun and breaking them even more. But let’s start at the beginning of the story…

Back in the year 1986: Top Gun, Platoon, and Crocodile Dundee were the top-grossing films in the cinema and IBM sold the very first laptop computer, called IBM PC Convertible (model 5140). The Internet Engineering Task Force (IETF) was just founded and Boris Becker won the Wimbledon Championships for the second time. A group of engineers of the Organisation for Data Exchange by Tele Transmission in Europe (ODETTE) met and specified OFTP, a protocol to transfer files over … no, there was no Internet commercially available at that time … X.25 networks. X.25 itself dates back to 1976 and is a packet-switched protocol for WANs. The OFTP protocol tried to “address the electronic data interchange (EDI) requirements of the European automotive industry” RFC2204, page 3. With the rise of the Internet, OFTP was extended in 1997 to support TCP/IP in addition to X.25 as the transport protocol (RFC2204) and in 2007 again to include encryption and authentication (RFC5024). With RFC5024 we have the most recent specification of the protocol which is called “OFTP2”. They somehow skipped their 10-year cycle (86, 97, 07) and did not release a current specification in the last 14 years.

Implementing an OFTP2 client

During a penetration test, we encountered a service listening on port 3305. It greeted any visitor with the banner “IODETTE FTP READY ” (the blank at the end is not a typo but part of the message). This was my, and everybody else’s, initial encounter with OFTP2. The following question was, how to evaluate a service for security vulnerabilities if you cannot speak its protocol? The answer is: You have to learn the protocol and write a tool that speaks it. There is one open-source implementation of OFTP2 available, but it is relatively complex and did not look like something we wanted to use. As an intern, I had some time and sat down to write a clean-room implementation of the OFTP2 protocol only based on the RFC.

You can find the implementation of the OFTP2-Client on GitHub.

There are some fun facts about OFTP2:

  • Every message exchanged between client and server starts with a one-letter command, like the I in the banner.
  • Some numeric values are transferred as strings like 01024, padded to a fixed length with leading zeros, for example, the maximum size of a message (SSIDSDEB).
  • Some numeric values are transferred as binary data in network byte order, for example, the length of an authentication challenge (AUCHCHLL).
  • Boolean values and flags are indicated by the characters Y and N.
  • Blanks are important because message fields are padded with blanks to their specified length, e.g. “X5O2010CUSTOMER 01024RNNN099N ” showing us a server response.
  • The actual data sent to the server during the file transfer has to be broken down into sub-records of 63 bytes. The sender has to split the data into these chunks; the receiver has to reassemble them.
  • The addressing of communication partners is based on the so-called Odette ID.

All things considered, it looks like a protocol extended several times with a little lack of orthogonality.

Know your Odette ID

Once you have a client that talks OFTP2, you need to know at least one valid Odette ID that is configured as a communication partner on the server. Otherwise, the server will not accept your message and will not initiate a session with you.

If you know such an ID, the server will tell you its Odette ID as part of the session handshake. This is quite an attractive feature because you can use it to find new Odette IDs — just try a known one on some servers and collect the IDs you receive as an answer to collect even more IDs.

The format of the ID is: Onnnnccccccccccccccssssss

  • O: the first character is always O
  • nnnn: a four-digit number with leading zeros, called the International Code Designator (ICD). Only the numbers 0002-0189 are globally registered (see ICD list). In Germany, you can expect to see 0013 and 0177 quite often because they are registered to the VDA and Odette consortium.
  • cccccccccccccc: A 14 character Organisation Code that typically consists of the character set [A-Z\-0-9]. Which characters are allowed, depends on the ICD.
  • ssssss: a 6 character computer sub address that normally consists of the character set [A-Z\-0-9].

The ID has not to take up the full 25 characters but can be shorter. In this case, it is padded with blanks to the right.

If the Odette ID starts with O013 the next six characters are numeric, e.g. O0013000243AEG.

LOCAL and O1999MENDELSONDE work out-of-the-box on some server implementations. Additionally, companies sometimes publish the ID or you can ask if you are good at social engineering.

In the case of the penetration tests, we knew valid Odette IDs due to other security vulnerabilities.

Finding a directory traversal

The protocol is made to transfer files, so it accepts arbitrary data and stores it somewhere on disk. Therefore, the first vulnerabilities to search for are directory traversals: Can we store our file at a location we chose?

OFTP2 maintains no notion of directories, thus there is no “change dir” command like in FTP. The sender provides a name for the file (called virtual dataset name, SFIDDSN) and a bunch of other information like file date, sizes, etc. How the server determines the local file name and its location is completely up to the server’s implementation.

The server we encountered during our tests was from the German company Mendelson GmbH. This particular implementation stores the received files in a dedicated folder for every sender’s ID and transfers them to another folder after processing. The local file name is taken from the virtual dataset name (SFIDDSN) and the file’s date (SFIDDATE) and time (SFIDTIME) are concatenated to distinguish different files with an identical name. The OFTP2 specification allows the characters [0-9A-Z/\-.&() ] for the virtual file name and the characters [0-9] for the date and time fields (5.3.3. in RFC5024). The . and / in the virtual file name looked promising but the / was filtered out by the implementation, so no directory traversal via the data set name (SFIDDSN). What the developers missed is that the date and time fields should contain only [0-9] according to the specification, but the client may ignore this and send any character.

Bingo! There is a directory traversal: Set the virtual file name (SFIDDSN) to .., the date (SFIDDATE) to //./../. and the time (SFIDTIME) to ./../test1 and the server will concatenate all three to the filename ..//./../../../test1.

The resulting path must have exactly 20 characters due to the length limitations of the used fields. Nevertheless, by using /./ and //, any target path shorter than 20 characters can be transformed into one with exactly 20 characters.

Although the number of directories you can walk up and down the file system hierarchy is limited due to the fields’ length restrictions, it is at least possible to reach the main installation directory of the OFTP2 server and replace configuration files or do other harm.

This vulnerability was reported on the vendor website and fixed in version OFTP2 1.1 b43, released 2021-01-13.


Ancient protocols are cryptic, and implementing them can be a pain, but they are not in the focus of security researchers. Therefore, there may be some fame still waiting for you.

And never have trust in the fact that the communication partner will adhere to the protocol. At least the bad guys will not.


Name of affected product: mendelson OFTP2
Fixed version: 1.1 b43
Vulnerability type: Directory Traversal
Root cause: Inproper Input Validation
Impact: File write to arbitrary directories