From Project Basecamp, we learned that the Koyo series of PLCs has some pretty fun security issues.
The first issue is with our test device’s built-in webserver. In addition to having denial-of-service vulnerabilities, the web server itself requires no authentication and allows changes to the PLC configuration, such as its IP address. To top things off, the server does not properly validate user input, and is vulnerable to cross-site scripting attacks (XSS).
There aren’t very many ECOM100 modules available on the internet, although a clever searcher could find a few dozen. Our researcher tells us that the standard ECOM module is far more popular than the ECOM100. The ECOM module lacks a built-in webserver, but should still be vulnerable to the ECOM100’s other issue: a limited password space and no lockout/timeout for authentication attempts.
Part of our Valentine’s Day tool release is going to be a module to brute-force the Koyo’s password. This should save some end users money: from Automation Direct’s FAQ, a lost password means that the end user must send the device in for a reset.
The biggest challenge in implementing the Koyo password brute-forcer was determining the DirectNet protocol’s CRC algorithm. The HAP protocol documentation (more on how we got this below) just says, “The CRC is computed using an algorithm which implements a moving exclusive-or and a translation table.” Not terribly informative. The 16-bit CRC is placed inside of the UDP packet’s payload (I call this ‘encrapsulation’, because UDP has its own CRC-16 in its header, making this CRC somewhat redundant).
I started disassembling the .DLLs and .EXEs included with Host Engineering’s DirectNet SDK, searching them for the string ‘CRC’. I found that the NetEdit3.exe utility included some printf()’y looking messages about CRC failures. So, I figured there must be a function in that program that was computing the CRC for the HAP protocol. Sadly, I couldn’t trace the data xrefs to these error messages back to the CRC function very quickly.
Being a lazy reverse engineer, I came upon a silly idea: instead of grasping through code xrefs to find the CRC function, why not just search the disassembly for instructions where the mnemonic is ‘xor’ and the src and target registers differ? xor is often used in x86 assembly for clearing a register, i.e. xor eax,eax to clear the eax register, so a little IDAPython was required.
The first two search results were inside the correct function, located at 0x4246E0 in the disassembly
So we see that it does a few xors, a right shift, and uses a lookup table to compute the CRC. I spent a while implementing the algorithm in Ruby, when a silly idea hit me: why not just google for the bytes of the lookup table? A lot of CRC algorithms have a ‘fast’ implementation using a small dictionary to speed them up, and a clever Ruby programmer may have implemented this one before, if I know what it’s called. The table starts 0x00, 0x00, 0x21, 0x10…
It turns out this is just CRC16-CCITT. There is already a one-liner Ruby implementation, making the upcoming Metasploit module far cleaner.
I’d like to give Digital Bond alumni Daniel Peck a huge amount of gratitude — he managed to find the protocol specification nugget that gave us the ability to make the module possible. I only wish that I could give our anonymous researcher some public acknowledgement (because this person is really smart and did a lot of hard work as a volunteer).
Image by erikcharlton