As a newbie in the field of OT Security, learning the protocols used in industrial environments is a necessity for me. That's why
OPC UA is a protocol I can't ignore.
As we know PLC is a key point in OT network operation, and it is operated by proprietary protocols and products from different vendors, which makes interoperability with ICS/SCADA protocol becomes difficult. So the protocol is now used as a standardized protocol to allow a host to be able to communicate with all endpoints in the OT network easily.
I will focus on researching this protocol-enabled product from Kepware PTC, a leading industry product supplier.
Surfing the internet, I downloaded a public version of KEPServerEX version 6.6.350 and read an article summarizing the error on team82's Kepware PTC product.
There is some important information here, there is a Stack Overflow occurring during OPC string decoding which can overflow the 1024-byte buffer and can especially trigger pre-validation. Quite interested in this information so I will try to analyze this vulnerability, I think this is the right thing to do when starting to learn more about the protocol.
Use Prosys OPC UA Browser as Client and make a connection to KEPServerEx.
The first message sent from the client is a
Hello message, containing the parameters to initiate the connection. This is followed by an
OpenSecureChannel request, If all goes well, the server will return a
channel ID. When the secure channel is open, all messages exchanged will be sent over this channel. When the connection is closed, a CLose message will be sent to disconnect.
Since this hip hole is pre-auth enabled, I will focus on the first two packets, Hello (HEL) and OenSecureChannel (OPN).
The HEL packet will have some information such as
Buffer size, and the
address of the connected server. Before the
EndpointUrl will be 4 bytes the
size of the EndpointUrl string.
KEPaboo to debug, after checking the loaded modules, I will focus on 2 modules,
libua.dll to handle opc ua tcp and
libsocket.dll to create a stream to receive packets from the clients. Proceed to debug and reverse.
When an event is read, the
ProcessReadEvent function is called and the
FD_READ flag is set to 1 and the
handleEventdRead function is called to process the packet.
Message Size of the packet will be checked, then the
3rd-level pointer reference to the
OPC request will be saved to
updateRefAddrReq and passed to the
The program will use the
Peek function to save 8 bytes including
Chunk Type, and
Message Size into
bufMsgType, then pass it to
callCheckMsgTypeHEL to check if it is the correct
Message Type or not based on a hard-fixed string of packet types.
There are Message types as follows:
- HEL: Hello message
- ACK: Response message
- OPN: OpenSecurityChannel message
- MSG: Data exchange message
- CLO: CloseSecurityChannel message
- ERR: Error message
When the test is successful, now
handStringReqHEL will be responsible for cutting the information in the packet and processing it. When reverse to the
getStrReq, something special happens.
Read function inside
libsocket is called, which has the function to copy
size bytes to
buf from the
OPC request stored in this.
On to the main problem, the
Read function will be called, cutting 4 bytes of the
EndpointUrl length from the
OPC Request stored into the variable
lenStr, which is a
signed int. This value is completely controllable. If we set the
lenStr value to
lenStr > 0 (pass first check), then
0x7fffffff + 1 will overflow, and the
result < 1024 (pass 2nd check). At this time,
bufStack of size 1024 bytes will be selected as the buffer to store
EndpointUrl, the result will stack overflow. Just like the information and reports Team82 wrote.
But life is not like a dream, actually the program is like this.
Results have been converted to
unsigned int and can't overflow here lollllll. A question mark arises, whether the version I installed has been fixed, I immediately re-read the information, and the vulnerability was found by team82 on ThingWorx Kepware Server 6.8 - 6.9.
I immediately went to the homepage to download the V6.8.0 demo to check, and now only V6.8.875 is the lowest.
The code has added exception handling with the value 0x7fffffff. With this type of code, I guess the vulnerability CVE-2020-27265 actually happened here. Or maybe I'm the wrong lollllll. Sorry, I couldn't find 6.8.0 to verify. Thank you to everyone who has read this far. I will share more new information I find in the next posts.