Add content

This commit is contained in:
Valentin Brandl 2019-10-28 11:46:07 +01:00
parent 509935c9cd
commit a6b265e80e
No known key found for this signature in database
GPG Key ID: 30D341DD34118D7D

View File

@ -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}