From a6b265e80e2aedbad929ce0b77a995d6c6308ffb Mon Sep 17 00:00:00 2001 From: Valentin Brandl Date: Mon, 28 Oct 2019 11:46:07 +0100 Subject: [PATCH] Add content --- work/01paper.tex | 57 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/work/01paper.tex b/work/01paper.tex index f94f91c..fbd454b 100644 --- a/work/01paper.tex +++ b/work/01paper.tex @@ -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}