Which architecture and operating system properties allow a buffer overflow attack?

2

Buffer overflow attacks occur when, when writing to a memory space, a program overflows the buffer boundaries and writes to an area of adjacent memory.

I would like to know what features, from the point of view of architecture and the operating system, allow this type of attack?

    
asked by anonymous 07.02.2014 / 15:15

2 answers

2

It's a rather broad question, but come on.

The biggest risk is to use a low-level programming language, type C, because in it you are required to use pointers to manipulate strings and buffers. Sooner or later the programmer makes a mistake and opens a loophole.

Using a higher level language reduces risk. Of course the language compiler or interpreter itself may have bugs, because it is probably written in C, but as a rule this type of code goes through more scrutiny, and the risk is concentrated in a smaller area.

If C is required, it is best to use a library for strings, for example the venerable QMail used a library of the author. Again, the library may have bugs but you focus the risk on a relatively small code instead of spreading it across the code of each program.

The operating system can greatly help mitigate buffer overflow risks with style features:

  • Randomization of the memory layout of each process: Prevents the same elements from always occupying the same address in virtual memory. The script kiddie attacks assume a fixed address.

  • Bit NX (requires CPU support): Prevents code in the stack from being executable, which makes some buffer overflow attack modes unfeasible

The compiler can collaborate by detecting some types of buffer overflow by checking the stack. I think every modern compiler has already incorporated the ideas of "StackGuard", a fork of the GCC popular in the 1990s.

The C library (libc) collaborates by checking for errors like double free (), which are not buffer overflows but are also attack vectors.

In both the compiler and the libc there are even stronger protections, but they cause performance cracking, so the developer can opt for them if the trade is advantageous. Often you inherit bad C-code, you can not rewrite it and the way to defend yourself is.

In short, every modern operating system has protections at several levels, and the situation is much better than in the 1990s. But the best prophylaxis is certainly to avoid unnecessarily low-level language.

    
07.02.2014 / 15:29
1

When compiling a program in C the characteristic of what each byte of memory is lost. The size of each array is simply removed by performance and it is not possible to determine where each object begins and ends in memory. That way wherever the program writes, it's assumed that it's right.

The operating system does not maintain such granular control of memory to the point of being able to detect buffers for its own sake. The virtual memory of each process is divided into pages (usually 4 KiB or 32 KiB). Each page can be readable, writable, or executable. The program code, for example, is readable and executable, but can not be modified. So the system will know if you try to write on a page that does not exist or can not be modified and will signal the process (which will usually abort in a crash).

That is, the system error margin is one page. And if the adjacent page is allocated and writable, nothing will happen. Since most attacks rely on writing data to a writable memory, the system will do nothing to protect it.

At this level, a technique that can be useful is to mark pages that you do not plan to write as read-only . But this is a pretty flawed protection as it will crash in case of attack.

What you should do is try to protect yourself from these attacks in your own program. It is not the role of the operating system.

If you are programming in a high level language, without using pointers, then you are most likely safe. For many languages it is impossible to write a code that is susceptible to this attack.

But if you are in a lower language (like C, where the motto is trust the programmer, he knows what he does ), all care is short. In such cases it is never possible to be completely certain that the code is free of attack opportunities. A good solution is to use Address Sanitizer . Enable GCC or Clang with the -fsanitize=address option.

    
07.02.2014 / 15:52