####################################################################### Luigi Auriemma Application: Pro-face Pro-Server EX WinGP PC Runtime http://www.profaceamerica.com/cms/resource_library/products/9e3c2a7965a27592/index.html Versions: ProServr <= 1.30.000 PCRuntime <= 3.1.00 Platforms: Windows Bug: A] "Find Node" invalid memory access B] memset integer overflow C] Unhandled exception D] Invalid memory read access and disclosure E] Possible limited memory corruptions Exploitation: remote Date: 13 May 2012 Author: Luigi Auriemma e-mail: aluigi@autistici.org web: aluigi.org ####################################################################### 1) Introduction 2) Bug 3) The Code 4) Fix ####################################################################### =============== 1) Introduction =============== From vendor's homepage: "Pro-Server EX is a powerful, yet cost effective data management server that provides real-time reporting of automated manufacturing and production environments at a fraction of the price of a full SCADA system." ####################################################################### ======= 2) Bugs ======= By default Pro-Server EX (ProServr.exe) runs as a stand-alone server but it can be set as a Windows service during the installation, this second mode is suggested by the vendor. ------------------------------------ A] "Find Node" invalid memory access ------------------------------------ The server trusts a 32bit "number of elements" value used locate the subsequent string in the received packet. If the packet contains a particular flag then the following function will try to check the presence of the string "\x1c" "Find Node\0" "ASP" at that arbitrary location: 0033650C |. 8D4486 04 LEA EAX,DWORD PTR DS:[ESI+EAX*4+4] ; seek ... 00336400 /$ A1 9C7A3A00 MOV EAX,DWORD PTR DS:[3A7A9C] ; the function 00336405 |. 8038 1C CMP BYTE PTR DS:[EAX],1C 00336408 |. 74 03 JE SHORT TDASforW.0033640D 0033640A |> 32C0 XOR AL,AL 0033640C |. C3 RETN This bug works also if the server is protected by password (max 8 bytes xored with 0xff) and the attacker doesn't know it. -------------------------- B] memset integer overflow -------------------------- Through the opcode 0x07 -> 0x5/0x6/0x7 it's possible to exploit an integer overflow for allocating a buffer of 0 bytes but a memset() after it allows only to exploit this bug for crashing the server due to a buffer-overflow of zeroes (unfortunately memcpy can't be reached): 0033660C |. 8B7D 18 MOV EDI,DWORD PTR SS:[EBP+18] ; our 32bit value 0033660F |. 83C7 18 ADD EDI,18 ; + 0x18 00336612 |. B9 988C3A00 MOV ECX,TDASforW.003A8C98 00336617 |. 8D1C07 LEA EBX,DWORD PTR DS:[EDI+EAX] 0033661A |. E8 C14CFFFF CALL TDASforW.?Lock@GaMutex@@QAEXXZ 0033661F |. 8B35 3C8C3A00 MOV ESI,DWORD PTR DS:[3A8C3C] 00336625 |. 03F3 ADD ESI,EBX 00336627 |. B9 988C3A00 MOV ECX,TDASforW.003A8C98 0033662C |. 8935 3C8C3A00 MOV DWORD PTR DS:[3A8C3C],ESI 00336632 |. E8 A921FFFF CALL TDASforW.?Unlock@GaMutex@@QAEXXZ 00336637 |. 8D4B 04 LEA ECX,DWORD PTR DS:[EBX+4] 0033663A |. 51 PUSH ECX 0033663B |. E8 045F0300 CALL ; malloc + 4 00336640 |. 53 PUSH EBX 00336641 |. 8D70 04 LEA ESI,DWORD PTR DS:[EAX+4] 00336644 |. 6A 00 PUSH 0 00336646 |. 56 PUSH ESI 00336647 |. 8918 MOV DWORD PTR DS:[EAX],EBX ; memset crash 00336649 |. FF15 28803800 CALL DWORD PTR DS:[<&GAOS.?osUTmemset@> 0033664F |. 57 PUSH EDI 00336650 |. 55 PUSH EBP 00336651 |. 56 PUSH ESI 00336652 |. FF15 24803800 CALL DWORD PTR DS:[<&GAOS.?osUTmemcpy@> ---------------------- C] Unhandled exception ---------------------- Through the opcode 0x07 -> 0x5/0x6/0x7 it's possible to terminate the server due to an unhandled exception ("Runtime Error") caused by a too big amount of data to allocate. -------------------------------------------- D] Invalid memory read access and disclosure -------------------------------------------- Through the opcode 0x07 -> 0x5/0x6/0x7/0x14 it's possible to crash the server specifying a big size value so that it's impossible to copy the data from the source packet using the osUTmemcpy function. The opcode 0x7 -> 0x14 is a bit more interesting because it returns a desired amount of memory back to the client and so it's possible to see all the memory till the end of the buffer. -------------------------------------- E] Possible limited memory corruptions -------------------------------------- Often the server reuses the same memory used for the input packet for modifying it and then sending it back to the client. The lack of checks on the size of the received packet allows an attacker to send a small packet and then forcing the server to write its fields at those positions higher than the allocated packet size corrupting the heap. An example of these memory corruptions happen with the opcode 0x7->0x14: 0033CE2F . 33C9 XOR ECX,ECX 0033CE31 . 3BD1 CMP EDX,ECX 0033CE33 . 66:8948 04 MOV WORD PTR DS:[EAX+4],CX 0033CE37 . C740 1C 16260000 MOV DWORD PTR DS:[EAX+1C],2616 0033CE3E . 8948 24 MOV DWORD PTR DS:[EAX+24],ECX 0033CE41 . 8948 28 MOV DWORD PTR DS:[EAX+28],ECX 0033CE44 . 8948 2C MOV DWORD PTR DS:[EAX+2C],ECX 0033CE47 . 8948 30 MOV DWORD PTR DS:[EAX+30],ECX 0033CE4A . 8948 34 MOV DWORD PTR DS:[EAX+34],ECX 0033CE4D . 8948 38 MOV DWORD PTR DS:[EAX+38],ECX 0033CE50 . 8948 3C MOV DWORD PTR DS:[EAX+3C],ECX 0033CE53 . 8948 40 MOV DWORD PTR DS:[EAX+40],ECX Anyway in this example ECX is just zero so not much useful but it's only to demonstrate a big chunk of code since there are some other places where are performed no checks on the received packet size. Note that this attack is possible only if no bigger packets have been received previously because the memory buffer is one and fits the latest biggest packet. PCRuntime.exe uses also the TCP port 8000 which is fully compatible with the protocol running on the UDP one (type, flags, size, data). ####################################################################### =========== 3) The Code =========== http://aluigi.org/poc/proservrex_1.zip ####################################################################### ====== 4) Fix ====== No fix. #######################################################################