Add content
This commit is contained in:
parent
509935c9cd
commit
a6b265e80e
@ -72,26 +72,58 @@ Heartbleed bug in OpenSSL which allowed dumping secret keys from memory. Out of
|
||||
bounds writes are almost always critical and result in code execution
|
||||
vulnerabilities or at least application crashes.
|
||||
|
||||
% Ever since the first programming languages were designed, security has been a
|
||||
% concern of software developers. With more advanced programming languages, that
|
||||
% did automatic memory management, some classes of errors were fixed. But
|
||||
% languages with unsafe, manual memory management are still in use and power
|
||||
% critical parts of the worlds infrastructure.
|
||||
|
||||
|
||||
\section{Main Part, TODO}\label{ref:main} %TODO!!!!
|
||||
|
||||
\subsection{Background}\label{ref:background}
|
||||
|
||||
text
|
||||
Exploitation of buffer overflow vulnerabilities almost always works by
|
||||
overriding the return address in the current stack frame, so when the `ret`
|
||||
instruction is executed, an attacker controlled address is moved into the
|
||||
instruction pointer register and the code pointed to by this address is
|
||||
executed. Other ways include overriding addresses in the PLT of a binary so
|
||||
that, if a linked function is called, an attacker controlled function is called
|
||||
instead, or (in C++) overriding the vtable where the pointers to an object's
|
||||
methods are stored.
|
||||
|
||||
\subsection{Concept and Methods}\label{ref:concept}
|
||||
|
||||
\subsubsection{Runtime Bounds Checks}
|
||||
|
||||
The easiest and maybe single most effective method to prevent buffer overflows
|
||||
is to check, if a write or read operation is out of bounds. This requires
|
||||
storing the size of a buffer together with the pointer to the buffer and check
|
||||
for each read or write in the buffer, if it is in bounds at runtime.
|
||||
|
||||
\subsubsection{Prevent Overriding Return Address}
|
||||
|
||||
Since most traditional buffer overflow exploits work by overriding the return
|
||||
address in the current stack frame, preventing or at least detecting this, can
|
||||
be quite effective without much overhead at runtime. Chiueh et al describe a
|
||||
technique that stores a redudnant copy of the return address in a secure memory
|
||||
area that is guarded by read-only memory, so it cannot be overwritten by
|
||||
overflows. When returning, the copy of the return address is compared to the one
|
||||
in the current stack frame and only, if it matches, the ret instruction is
|
||||
actually executed\cite{Rad2001}. While this is effective against return oriented
|
||||
programming based exploits, it does not protect against vtable overrides.
|
||||
|
||||
An older technique from 1998 proposes to put a canary word between the data of a
|
||||
stack frame and the return address\cite{Stackguard1998}. When returning, the
|
||||
canary is checked, if it is still intact and if not, a buffer overflow occurred.
|
||||
This technique is used in major operating systems %TODO
|
||||
but can be defeted, if there is an information leak that leaks the cannary to
|
||||
the attacker. The attacker is then able to construct a payload, that keeps the
|
||||
canary intact.
|
||||
|
||||
\subsubsection{Restricting Language Features to a Secure Subset}
|
||||
\subsubsection{Static Analysis}
|
||||
\subsubsection{Type System Solutions}
|
||||
|
||||
Condit et al propose an extension to the C type system that extends it with
|
||||
dependent types. These types have an associated value, e.g. a pointer type can
|
||||
have the buffer size associated to it. This prevents indexing into a buffer with
|
||||
out of bounds values.
|
||||
|
||||
\subsubsection{ASLR}
|
||||
|
||||
ASLR aims to prevent exploitatoin of buffer overflows by placing code at random
|
||||
@ -127,7 +159,16 @@ text
|
||||
|
||||
\section{Conclusion and Outlook}\label{ref:conclusion}
|
||||
|
||||
text
|
||||
While there are many techniques, that protect against different types of buffer
|
||||
overflows, none of them is effctive in every situation. Maybe we've come to a
|
||||
point where we have to stop using memory unsafe languages where it is not
|
||||
inevitable. There are many modern programming languages, that aim for the same
|
||||
problem space as C, C++ or Fortran but without the issues comming/stemming %TODO
|
||||
from these languages. If it is feasible to use a garbage collector, Go might
|
||||
work just fine. If real-time properties are required, Rust could be the way to
|
||||
go, without any language runtime and with deterministic memory management. For
|
||||
any other problem, almost any other memory safe language is better than using
|
||||
unsafe C.
|
||||
|
||||
\section{Sources}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user