If I were to ask you what the most common type of “hack” is, you’d probably guess something like SSL Injection, or Buffer Overflow, or something of that nature. You wouldn’t be entirely wrong, but there’s a much more general answer that covers all those things:
The most common attack is bad input
When it boils down to it, the most common attacks are based on the idea that the programmer goofed up when checking inputs. So long as the attacker is able to send in bad inputs without being repelled, he will find a way to compromise your system.
- SQL injections work because most people don’t check the commands they allow their websites to run. And, even when they do check, they often forget to check for hexadecimal encodings, which work out exactly the same but are harder to detect.
- Buffer Overflows work because so many programmers fail to employ safe string functions and stack/heap protection. Because they fail to regulate the size and type of inputs, they open their code to various exploits.
- Library injections work because programs are usually designed to load particular libraries on runtime, and it is possible to replace the original library with a maliciously altered library. Surprisingly few programs employ checksums to detect maliciously altered libraries.
All that is the bad news. The good news is that there are ways to
prevent mitigate these threats (I can’t say “prevent” with 100% certainty, but best practices would eliminate probably the most common 95% of attacks).
Buffer Overflows can be largely mitigated using stack protection alone. GCC employs stack protection by default, which causes the program to crash without executing any further code. This prevents the sort of buffer overflow in which we control the crash, overwriting the return pointers so that our malicious code is executed. Furthermore, if we properly use safe functions like fgets(), memcpy(), or strncpy(), we can protect ourselves against the initial crash.
SQL injections can be mitigated with parametrized inputs, which store user inputs to variables that can only hold data types, not executable SQL code.
Library injections can be mitigated using checksums on load. The basic idea here is to confirm that any functions you take from the library are correct, using a safe hashing algorithm like SHA-512. This check must be employed after the library has been locked (so no changes can be made) but before it has been loaded (so the program cannot execute any bad code, should it exist).
Basically, employing best practices that account for bad inputs can prevent some of the most common attacks against the integrity of your system.