MEDCIN Engine Vulnerability exploitation details
Popular Science: The MEDCIN engine is an electronic medical record system for doctors and nurses.
A few months ago, I found a vulnerability in the earlier version of the MEDCIN engine's security assessment. So I reported the vulnerability to the vendor and fixed it. Then I found several vulnerabilities when I checked the latest code of the program.
In earlier versions of this program, vulnerabilities can process emails from remote clients and run system-level permissions on Windows without authentication. In addition, the original binary file lacks the memory protection during compilation. So I first checked whether the developer put the memory protection feature during compilation into their latest version. I quickly browsed several arbitrary functions. I saw that the cookie Stack has been added and the binary files in it have been compiled by SafeSEH. With these new protection measures, any stack-based buffer overflow vulnerability will be more difficult to exploit.
So I used various information parsing routines I found in the original executable files for tracking. In combination with previous operations on binary files, I quickly compiled a simple fuzzy tool to provide random data to application services. After several weeks of fuzzy testing and static analysis, I found eight code execution vulnerabilities. These bugs include stack, heap, Data Segment buffer overflow, memory leakage, and arbitrary memory write control.
CVE-2015-2898
After investigating a bunch of vulnerabilities, I decided to start to discover stack-based buffer overflow at the beginning. However, the combination of stack cookies and binary files compiled by SafeSEH does not allow us to gain control of executable files from the application. If the cookie of the stack cannot be leaked, I cannot exploit this vulnerability.
CVE-2015-2901
The next bug is that the string buffer register overflows to the Data Segment and then leaks through the socket. This vulnerability is useful because it not only overwrites the entire data segment, but also returns the data segment to the memory address. However, this vulnerability has an obvious restriction. I can only overwrite the NULL bytes of the Data Segment. Is the pseudocode of the vulnerability.
It took a lot of time and effort to gain control of execution through this vulnerability. I found that only when the data segment is corrupted or the program crashes will it take a short time for us to pass through. However, program crashes are random and often cannot be entered. I cannot expose the cookie or stack address. But! Some useful heap addresses can be leaked.
CVE-2015-2900
Then I looked at the vulnerability that could control some arbitrary memory writes. This special bug was found when the program crashed during a fuzzy machine running. It appears to be from the user-controlled index (signed integer) that is added to the heap pointer address in the data segment ). The function in cannot verify whether the input integer is greater than zero. However, I think this vulnerability is partly controlled because the heap address for adding an index is dynamic. Below are some pseudocode of the bug.
After some investigation, I found that the heap address that stores our controlled index is below the buffer register of the string connection of the CVE-2015-2901. This means that we can leak this address and have full control over the location where the data is written. As you can see in the code snippet, the written value is a heap pointer, which is allocated before any write.
Now that we can write a pointer anywhere in the memory, the next thing we need to do is determine whether we control the data pointed to by the pointer and find a useful target address to override our pointer. After confirmation, We will rewrite a function pointer to trigger the command to get the code for execution. However, the premise is that the data pointed to by the pointer can be controlled for execution.
By searching for binary files, I only find a very small number of function pointers at static locations. Fortunately, one of these function pointers can directly access the information parsing function. Wow! We seem to have implemented code execution on the stack.
This is because the application is not compiled under Data Execution Protection. On Windows 7, I set DEP to "accept ". Most people only know that DEP disables the execution on the stack, but it also protects the stack.
After the code is executed, you must understand how much data is controlled by the function pointer that we rewrite. I looked at the code and found that although I had a good control of the cache, it still exceeded 0 × 100 bytes in the buffer. I tried to jump from an uncontrollable place to the control part of the buffer each time I replaced, but all failed. Are there other vulnerabilities that we can achieve?
CVE-2015-2899
This vulnerability is the last obstacle to implementing code execution to control the data pointed to by the rewritten function pointer. Since our data is on the heap, the next step is to see if we can directly overflow the heap allocation in some way to fill it with controllable data. Fortunately, we have a heap buffer overflow.
In, we have a classic heap buffer overflow because the target buffer size is static and the source string length is not detected. So I decided to try to create a heap by using the method of memory allocation overflow to my target allocation, so that the rewritten function pointer will point to the controlled data.
Here I need to keep the memory allocation from being released, and it is better to control the size. Finally, I found a function in a bunch of information analysis functions that allows me to allocate memory at will. Without a real study of heap splitters for Windows 7, I directly tested which sizes and allocated quantity can meet my needs. Below is the general structure of my opinion verification program.
As expected, my results were rather unreliable because I was not clear about the internal working principles of windows 7 heap splitters. In addition, I do not know whether other memory allocation and release are out of my control. So I need a visualization tool that can monitor distribution and release of the distributor.
Just as I was happy to find a heap monitoring tool online. I found that none of these were what I wanted! They either take a memory snapshot and let you analyze it, or they are embedded in a debugger. I also hoped that the functions used with the hooking library could not only share but also run 64-bit functions.
However, I found the source code of a tool called Heapy on the Internet. It uses an open-source hooking library named MinHook to support Hook Functions and supports x86 and x64 architectures. It also has sample code for hooking dynamic memory allocation. So I decided to use this MinHook as part of my tool.
Heap Monitor
With the new HeapMonitor visualization tools and code, I started to use HeapMonitor (my own name ). First, I write code in the DLL Injector to connect a service-level process. Then I changed the policy and wrote the hook details to a file instead of transmitting them through socket. In this way, my visual GUI can be applied to all systems. I also attached a stack trace to facilitate tracing of the called functions.
I decided to write the GUI using the most familiar Java. In the list on the right of the page, I display the allocation and release in real time. The main framework is a block view that displays memory pages and updates information in real time. The second tab on the main framework lists the stack tracing of the selected allocation and release in all lists. To prevent the division of the allocated memory page, I also added the memory navigation bar at the top to use the memory quick navigation.
To better handle the internal work of the Windows 7 heap splitter, I found a lot of security reports. Among them, the most useful tool for me is Chris Valasek's "Understanding the low fragment heap", Steven Seeley's "ghost in the distributor ", and Jeremy Fetiveau's "using low-fragment heaps for profit and fun ". Their research was also confirmed through my heap visualization tools.
CVE-2015-6006
There is a big problem in my operations. Whenever I set the allocation to continuous allocation, it will always be automatically closed after it reaches 0 × 1000 bytes. This means that my heap overflow must be quite large. After looking at the latest research on heap splitters on Windows 7, I realized that it was not because low-fragment Heaps Were enabled. This was also confirmed through the heap Monitor Tool. But I still cannot allocate the same size because the CVE-2015-2899 is static, 0XF0, And the CVE-2015-2900 must be at least 0x100 bytes (passed_alloc_size + 0x100 ).
At the end, I admit that it is impossible to achieve a 100% reliability. It happens that calling a function for any Write Vulnerability (CVE-2015-2900) has two bugs. It is truncated to a 16-Bit Signed short type before the data provided by the user is transmitted to any write function allocation buffer. After this function is returned, all user data is copied to the newly created buffer in the form of a string. This means that we can provide a string larger than the MAX_SHORT string, resulting in a heap overflow of the string copy. This also means we can control the allocation size. Is the vulnerability code.
Once the low fragment heap is activated, I can create gaps in the allocation order and reassign them for my heap overflow. Adjusted some additional memory allocation. My attack is almost 100% feasible!