Late last week the Yokogawa Electric Corporation released security updates for its industrial control systems to address 3 critical CVEs (defined). These products provide management and control functions for industrial systems as well as providing event analysis.
Each of these security vulnerabilities involves a stack overflow (please see Aside below for a definition). 2 of these vulnerabilities can be used by a remote attacker to cause a denial of service issue (defined) while the remaining vulnerability can enable a remote attacker to execute arbitrary code (carry out any action they choose).
Why Should These Issues Be Considered Important?
Since these products control large industrial systems e.g. the types used in pumping stations, power plants and large manufacturing plants there is the potential for these attacks to have physical consequences/destruction.
How Can I Protect Myself From These Issues?
Please follow the instructions within this ICS CERT security advisory (specifically the Mitigation section) to update any affected Yokogawa industrial products that you may be using. A full list of the affected products is also provided within that advisory.
What is a stack overflow?
A stack is continuous block of memory. It is similar to a buffer (defined: please see the Aside within that post) which are used by functions (defined: please see the Aside within that post). These functions are part of a wider/larger program. The stack is a data structure (a method of organizing data).
Stacks are different to other data structures in that new items are added to the top of the stack (using a PUSH operation) and are removed from the bottom of the stack (using a POP operation). This is known formally as a Last In First Out (LIFO) data structure. Stacks grow/increase in size as more items are added to them but they grow from upper memory (higher values) to lower areas of memory (i.e. they grow from the top down as opposed to the bottom up).
Note that the PUSH and POP operations above correspond to the names of instructions to carry out these tasks in assembly language (defined).
Now that a stack has been described using the figure below I will explain how a stack overflow occurs:
Using some C code if we declare a string of length 20 but actually store 80 characters (shown as Function Variable Name within the figure below) rather than the 20 characters allocated we will cause a buffer overflow.
If we make all of the characters within the string be the letter C (which is 0x43 in hexadecimal) when the buffer overflows it will overwrite both the values of EBP and EIP. While I mentioned that stacks grow into lower locations in memory, EBP and EIP will be overwritten since that the space that was allocated to them will instead be used by the 80 character string that we declared above. These registers will contain the letter “C” represented in memory as 0x43434343, as mentioned above.
In assembly language the EBP (extended base pointer) register points to the beginning of the local environment for a function and represents the base of the current stack frame. The ESP (extended stack pointer) points to the top of the stack (which is a lower memory address than the base of the stack).
Finally the EIP (extended instruction pointer) register contains the address of the original location in the overall program code where a function was called from so that the program can return to that location when that function has carried out it’s task. This address is known as the return address. As mentioned in previous blog posts (here and here) the goal of an attacker is to overwrite this return address with the address of their choice, usually pointing to shellcode (defined) that will exploit a vulnerability allowing them to carry out any action they choose which will usually consist of elevating their privilege as high as possible (root level on Linux/Unix/Apple Mac OS X and kernel/system level on Windows are preferred) and then using that privilege to install a backdoor (defined).
With the address within the EIP overwritten by the buffer overflow (which the attacker has been careful to ensure it is a value of their choice), when the function attempts to return to the original location from where it was called, it will instead return to the location the attackers wishes. When this happens the actions of the attacker’s choice (mentioned above) will be carried out.
If our program also contained a function such as printf() and this was used to print the values of the Parameters shown in the figure it too would encounter an issue since those parameters have been overwritten by our overflow. If their values were examined using a debugger such as GDB, they would contain 0x43434343, namely the letter C which was mentioned above.
As mentioned in previous blog posts (here and here) modern operating systems have built-in defences against such stack based overflows. In addition, Address Space Layout Randomization (ASLR)(defined) protects against these overflows since the attacker should not be able to accurately predict the memory address to place within the EIP register when they trigger an overflow. In addition, the memory locations of the EBP and ESP registers would also be randomized.
My thanks to the following references which assisted in the creation of this explanation:
Stack based buffer overflow Exploitation Tutorial by Saif El-Sherei
Exploiting Software: How to Break Code (Greg Hoglund and Gary McGraw) Addison-Wesley, 2004
Some sample C code that illustrates the text/description given above would be the following:
/*Declare the necessary string library (string.h) for the function that we will call. Please ensure to use the correct placeholder brackets on each side of string.h, namely <> I can't insert these directly into this post due to how WordPress interprets code*/
int main(argc, char *argv)
char overflowString; //declare a 20 byte string
//Copy 80 letter “Cs” into the above string
return 0; /*Since our main function is declared as above it must return an integer value. We will return 0 for simplicity.*/