Our latest adventures took us to the magical world of… FIX protocols!
The Financial Information eXchange (FIX) protocol manages the processing of real-time exchanged information within Financial Markets. It was originally authored in 1992 and became very famous very quickly as it helped shift the communication of trading data from the inefficient telephone to always connected, asynchronous and reliable systems.
The FIX protocol messaging comprises of tag value pairs. Each tag contains of different fields (Shares, OrderID, Quantity, Price, Value) and each field has a value. For instance, the field 35 is responsible
for the message type and “35=A” indicates that the current message is part of the authentication process which usually kick-starts the FIX client-server communication.
Consider the following FIX message:
8=FIX.4.2 | 9=178 | 35=8 | 49=PHLX | 56=PERS | 52=20071123-05:30:00.000| 11=ATOMNOCCC9990900 | 20=3 | 150=E | 39=E | 55=MSFT | 167=CS | 54=1 | 38=15 | 40=2 | 44=15 | 58=PHLX EQUITY TESTING | 59=0 | 47=C | 32=0 | 31=0 | 151=15 | 14=0 | 6=0 | 10=128 |
The goals of the protocol are limited to reliability and low latency and do not extend to security goals such as confidentiality of data and non-repudiation of transactions. In fact, the FIX protocol leaves the choice of all appropriate security measures open to the user community.
Even with a relatively secure implementation of FIX – with dedicated leased lines, P2P communication, session management, common security threats may lurk. Web-based attacks such as SQLi and access control violations are still possible and very much dependent on the respective implementation.
We soon wandered off away from “common” testing and started inspecting the behavior of the FIX server. Fuzzing proved to wield very interesting results as different messages were soon returned by the FIX server. To that end, we developed a simple python function to produce unusual input, incremented the size of the payload gradually and compared the results in terms of response length and response times.
During our last adventure we modified a tool developed by Gotham Digital Science to test for such flaws in a more targeted and hence, optimal fashion. (https://github.com/GDSSecurity/Fizzer)
For our needs, the tool was converted from C# to python for additional portability and extra functionality was added:
- Fuzzing specific parameters
- Passing multiple parameters for fuzzing
- Handling multiple requests from raw files
- An auto-fuzz functionality was introduced to generate unusual input while allowing the user to control the length and the step of the fuzzing process
- The user can now pass a file containing a list of his own payloads for fuzzing
The results were rewarding as denial of service conditions were identified against the main processing controller of one FIX server implementation.
Although, exploitation might seem trivial, the associated risk of such an attack can be extremely critical, as an internal attacker could render the server unresponsive and hence, cause complete disruption to all business operations, including trade requests.
Fixer code is available from https://github.com/SECFORCE/fixer