This commit is contained in:
Valentin Brandl 2019-12-16 17:56:17 +01:00
parent 541a979646
commit 020a4542fb
No known key found for this signature in database
GPG Key ID: 30D341DD34118D7D
6 changed files with 393 additions and 159 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -27,6 +27,7 @@
%\usepackage[ngerman]{babel} %\usepackage[ngerman]{babel}
\usepackage[utf8]{inputenc} \usepackage[utf8]{inputenc}
\usepackage{hyperref} \usepackage{hyperref}
\usepackage{cleveref}
\usepackage{url} \usepackage{url}
%%fuer abkuerzungen begin %%fuer abkuerzungen begin
\usepackage[acronym,hyperfirst = false]{glossaries} \usepackage[acronym,hyperfirst = false]{glossaries}
@ -60,7 +61,12 @@ MatrNr. 3220018}
\maketitle \maketitle
\begin{abstract} \begin{abstract}
TODO
This paper tries to explain the details behind buffer overflows, explore the
problems stemming from those kinds of software vulnerabilities and discus
possible countermeasures with focus on their effectiveness, performance impact
and ease of use.
\end{abstract} \end{abstract}
\begin{IEEEkeywords} \begin{IEEEkeywords}
@ -74,20 +80,24 @@ Buffer Overflow, Software Security
When the first programming languages were designed, memory had to be managed When the first programming languages were designed, memory had to be managed
manually to make the best use of slow hardware. This opened the door for many manually to make the best use of slow hardware. This opened the door for many
kinds of programming errors. Memory can be deallocated more than once kinds of programming errors. Memory can be deallocated more than once
(double-free), the programm could read or write out of bounds of a buffer (double-free), invalid pointers can be dereferenced (\mintinline{C}{NULL}
(information leaks, \acp{bof}). Languages that are affected by this are e.g. C, pointer dereference; this is still a problem in many modern languages), the
C++ and Fortran. These languages are still used in critical parts of the worlds program could read or write out of bounds of a buffer (information leaks,
\acp{bof}). Languages that are affected by this are e.g.\ C, C++ and Fortran.
While most if not all of these problems are solved in modern programming
languages, these languages are still used in critical parts of the worlds
infrastructure, either because they allow to implement really performant infrastructure, either because they allow to implement really performant
programms, because they power legacy systems or for portability reasons. programs, offer deterministic runtime behaviour (e.g.\ no pauses due to garbage
collection), because they power legacy systems or for portability reasons.
Scientists and software engineers have proposed lots of solutions to this Scientists and software engineers have proposed lots of solutions to this
problem over the years and this paper aims to compare and give an overview about problem over the years and this paper aims to compare and give an overview about
those. those.
Reading out of bounds can result in an information leak and is less critical Reading out of bounds can result in an information leak and is less critical
than \acp{bof} in most cases, but there are exceptions, e.g.\ the Heartbleed bug than \acp{bof} in most cases, but there are exceptions, e.g.\ the Heartbleed
in OpenSSL which allowed dumping secret keys from memory. Out of bounds writes bug~\cite{Heardbleed2014} in OpenSSL which allowed dumping secret keys from
are almost always critical and result in code execution vulnerabilities or at memory. Out of bounds writes are almost always critical and result in code
least application crashes. execution vulnerabilities or at least application crashes.
In 2018, 14\% (2368 out of 16556)~\cite{Cve2018} of all software vulnerabilities In 2018, 14\% (2368 out of 16556)~\cite{Cve2018} of all software vulnerabilities
that have a CVE assigned, were overflow related. This shows that, even if this that have a CVE assigned, were overflow related. This shows that, even if this
@ -95,241 +105,439 @@ type of bug is very old and well known, it's still relevant today.
\section{Background}\label{ref:background} \section{Background}\label{ref:background}
% TODO: many references
\subsection{Technical Details} \subsection{Technical Details}
Exploitation of \ac{bof} vulnerabilities almost always works by overriding the Code execution via \ac{bof} vulnerabilities almost always works by overwriting
return address in the current stack frame, so when the \mintinline{ASM}{RET} the return address in the current stack frame (known as \enquote{stack
instruction is executed, an attacker controlled address is moved into the smashing})~\cite{Smashing2004}, so when the \mintinline{ASM}{RET} instruction is
instruction pointer register and the code pointed to by this address is executed, an attacker controlled address is moved into the instruction pointer
executed. Other ways include overriding addresses in the \ac{plt} of a binary so register and the code pointed to by this address is
that, if a linked function is called, an attacker controlled function is called executed~\cite{Detection2018}. Other ways include overwriting addresses in the
instead, or (in C++) overriding the vtable where the pointers to an object's \ac{plt} (the \ac{plt} contains addresses of dynamically linked library
methods are stored. functions) of a binary so that, if a linked function is called, an attacker
controlled function is called instead, or (in C++) overwriting the vtable where
the pointers to an object's methods are stored.
A simple vulnerable programm might look like this: A simple vulnerable C program might look like this:
\begin{figure}[h!]
\begin{minted}{c} \begin{minted}{c}
int main(int argc, char **argv) { void vuln(char *input) {
char buf[50]; char buf[50];
for (size_t i = 0; i < strlen(argv[1]); i++) { size_t len = strlen(input);
buf[i] = argv[1][i]; for (size_t i = 0; i < len; i++) {
buf[i] = input[i];
} }
}
int main(int argc, char **argv) {
vuln(argv[1]);
return 0; return 0;
} }
\end{minted} \end{minted}
\caption{Vulnerable C program}\label{lst:vuln}
A successful exploit would place the payload in the memory by supplying it as an
argument to the programm and eventually overwrite the return address by
providing an input $> 50$ and therefore writing out of bounds. When the
\mintinline{C}{return} instruction is executed, and jumps into the payload, the
attacker's code is executed. This works due to the way, how function calls on
CPUs work. The stack frame of the current function lies between the two pointers
\ac{bp} and \ac{sp} as shown in~\ref{fig:before}. When a function is called, the
value of the \ac{bp}, \ac{sp} and \ac{ip} is pushed to the stack
(Fig.~\ref{fig:call}) and the \ac{ip} is set to the address of the called
function. When the function returns, the old \ac{ip} is restored from the stack
and the execution continues from where the function was called. If an overflow
overwrites the old \ac{ip} (Fig.~\ref{fig:exploit}), the execution continues in
attacker controlled code.
\begin{figure}[h!]
\includegraphics[width=.3\textwidth]{./dot/before.pdf}
\caption{Stack layout before function call}\label{fig:before}
\end{figure}%
\begin{figure}[h!]
\includegraphics[width=.3\textwidth]{./dot/call.pdf}
\caption{Stack layout after function call}\label{fig:call}
\end{figure}%
\begin{figure}[h!]
\includegraphics[width=.3\textwidth]{./dot/exploit.pdf}
\caption{Stack layout after overflow}\label{fig:exploit}
\end{figure} \end{figure}
This is only one of several types and exploitation techniques but the general A successful stack \ac{bof} exploit would place the payload in the memory by
idea stays the same: ovewrite the return address or some kind of function supplying it as an argument to the program (or by placing it in an environment
pointer (e.g.\ in vtables or the \ac{plt}) and once that function is called, the variable, writing it to a file that the program reads, via network packet, ...)
execution flow is hijacked and the attacker can execute arbitiary code. and eventually overwrite the return address by providing an input with $> 50$
bytes and therefore writing out of bounds. When executing the
\mintinline{C}{return} instruction, and the jumps into the payload, the
attacker's code is executed. This works due to the way, how function calls on
CPUs work: The stack frame of the current function lies between the \ac{bp} and
\ac{sp} as shown in~\cref{fig:before}. When a function is called, the value
of the \ac{bp} and \ac{ip} is pushed to the stack (\cref{fig:call}) and the
\ac{ip} is set to the address of the called function. When the function returns,
the old \ac{ip} is restored from the stack and the execution continues from
where the function was called. If an overflow overwrites the old \ac{ip}
(\cref{fig:exploit}), the attacker controls where execution continues.
The most trivial kinds of exploits is known as a \mintinline{ASM}{NOP} sled. \begin{figure}[h!]
\begin{subfigure}[b]{.3\textwidth}
\includegraphics[width=\textwidth]{./dot/before.pdf}
\caption{Stack layout before function call}\label{fig:before}
\end{subfigure}\\
\begin{subfigure}[b]{.3\textwidth}
\includegraphics[width=\textwidth]{./dot/call.pdf}
\caption{Stack layout after function call}\label{fig:call}
\end{subfigure}\\
\begin{subfigure}[b]{.3\textwidth}
\includegraphics[width=\textwidth]{./dot/exploit.pdf}
\caption{Stack layout after overflow}\label{fig:exploit}
\end{subfigure}
\caption{Stack layouts during an \ac{bof} exploit}
\end{figure}%
This is only one of several types and exploitation techniques. Others include
\begin{itemize}
\item Heap-based \ac{bof}: In this case there is no way of overwriting the
return address but objects on the heap might contain function pointers
(e.g.\ for dynamic dispatch) which can be overwritten to execute the
attackers code, when executed~\cite{Detection2018}.
\item Integer overflow: Some calculation on fixed sized integers is used to
allocate memory. The calculation leads to an integer overflow and only a
small buffer is allocated~\cite{Detection2018}. Later a big integer into the
buffer is used and reads or writes outside the buffer. This kind of
vulnerability can also lead to other problems because at least in C, signed
integer overflow is undefined behaviour.
\end{itemize}
This paper won't explore other kinds of \ac{bof} in detail because the concept
is always the same: Unchecked indexing into memory allows the attacker to
overwrite some kind of return or call address, which allows hijacking of the
execution flow.
The most trivial kinds of payloads is known as a \mintinline{ASM}{NOP} sled.
Here the attacker appends as many \mintinline{ASM}{NOP} instructions before any Here the attacker appends as many \mintinline{ASM}{NOP} instructions before any
shellcode (e.g.\ to invoke \mintinline{shell}{/bin/sh}) and points the shell-code (e.g.\ to invoke \mintinline{shell}{/bin/sh}) and points the
overwritten \ac{ip} somewhere inside the \mintinline{ASM}{NOP}s. The execution overwritten \ac{ip} or function pointer somewhere inside the
\enquote{slides} through the \mintinline{ASM}{NOP}s until it reaches the \mintinline{ASM}{NOP}s. The execution \enquote{slides} (hence the name) through
shellcode. Most of the migration techniques described in this paper protect the \mintinline{ASM}{NOP}s until it reaches the shell-code. Most of the
against this kind of exploit but there are different and more complex ways of mitigation techniques described in this paper protect against this kind of
exploiting \acp{bof} that are not that easily migrated. exploit but there are different and more complex ways of exploiting \acp{bof}
that are not that easily mitigated.
\subsection{Implications}
\section{Concept and Methods}\label{ref:concept} \section{Concept and Methods}\label{ref:concept}
\subsection{Methods} \subsection{Research Methods}
This paper describes several techniques that have been proposed to fix the This paper describes several techniques that have been proposed to mitigate the
problems introduced by \acp{bof}. The performance impact, effectiveness (e.g.\ problems introduced by \acp{bof} and tries to answer the following questions:
did the technique actually prevent exploitation of \acp{bof}?) and how realistic
it is for developers to use the technique in real-world code (e.g.\ is
incremental introduction into an existing codebase possible). In the end, there
is a discussion about the current state.
\subsection{Runtime Bounds Checks} \begin{itemize}
\item What is the performance impact?
\item How effective is the technique? Did it actually prevent exploitation of
\acp{bof}?
\item How realistic is it for developers to use the technique in real-world
code? Can it be introduced incrementally?
\end{itemize}
The paper focuses on solutions for the C language, since it is still the second
most used language as of December 2019~\cite{Tiobe2019}. Some of the described
techniques are language agnostic but this is not a focus of this paper. In the
end, there is a discussion about the current state.
For the literature research, the paper~\citetitle{Detection2018} served as a
base. From there a snowball system search with combinations of the keywords
\enquote{buffer}, \enquote{overflow}, \enquote{detection}, \enquote{prevention}
and \enquote{dependent typing} was performed using
\url{https://scholar.google.com/}.
Results are evaluated and prioritized using the following criteria:
\begin{itemize}
\item Type of publication in the following order:
\begin{enumerate}
\item conference paper
\item unreleased paper
\item books
\item online sources
\end{enumerate}
\item Number of citations
\item Publisher
\item Author's reputation and institute
\item Overall quality (first by checking structure and abstract, then by
the actual content)
\end{itemize}
\subsection{\Ac{rbc}}
The easiest and maybe single most effective method to prevent \acp{bof} is to The easiest and maybe single most effective method to prevent \acp{bof} is to
check, if a write or read operation is out of bounds. This requires storing the 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 size of a buffer together with the pointer to the buffer (so called fat
or write in the buffer, if it is in bounds at runtime. Still almost any language pointers) and check for each read or write in the buffer, if it is in bounds at
that comes with a runtime, uses runtime checking. For this technique to be runtime. Still almost any language that comes with a runtime, uses runtime
effective effective in general, writes to a raw pointer must be disallowed. checking. For this technique to be effective effective in general, writes to a
Otherwise the security checks can be circumvented. raw pointer must be disallowed. Otherwise the security checks can be
circumvented. \Ac{rbc} introduces a runtime overhead for every indexed read or
write operation. This is a problem if a program runs on limited hardware or
might impact real-time properties.
\subsection{Prevent/Detect Overriding Return Address} Introducing \ac{rbc} into an existing codebase is not easy. Using fat pointers
in a few functions does not prevent other parts of the code to use raw pointers
into the same buffer. So for this to be effective, the whole codebase needs to
be changed to disallow raw pointers, which, depending on the size, might not be
feasible. Still, if done correctly and consequently, it is simply impossible to
exploit \acp{bof} for code execution. \Ac{dos} is still possible because the
program terminates gracefully when a out of bounds index is used.
Since most traditional \ac{bof} exploits work by overriding the return address \subsection{Prevent/Detect Overwriting Return Address}
Since most traditional \ac{bof} exploits work by overwriting the return address
in the current stack frame, preventing or at least detecting this, can be quite in the current stack frame, preventing or at least detecting this, can be quite
effective without much overhead at runtime. \citeauthor{Rad2001} describe a effective without much overhead at runtime. \citeauthor{Rad2001} describe a
technique that stores a redudnant copy of the return address in a secure memory technique that stores a redundant copy of the return address in a secure memory
area that is guarded by read-only memory, so it cannot be overwritten by 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 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 \mintinline{ASM}{RET} in the current stack frame and only, if it matches, the \mintinline{ASM}{RET}
instruction is actually executed~\cite{Rad2001}. While this is effective against instruction is actually executed~\cite{Rad2001}. While this is effective against
\ac{rop} based exploits, it does not protect against vtable overrides. stack based \acp{bof}, in the described form, it does not protect against vtable
overwrites. An extension could be made to also protect the \ac{plt} and vtables
but custom constructs using function pointers would still be vulnerable. Since
this technique is a compiler extension, no modification of the codebase is
required to enable it, and while it does not prevent all kinds of \ac{bof},
mitigates all stack based \acp{bof} with only minimal overhead when calling and
returning from a function.
An older technique from 1998 proposes to put a canary word between the data of a An older technique from 1998 proposes to put a canary word (named after the
stack frame and the return address~\cite{Stackguard1998}. When returning, the canaries that were used in mines to detect low oxygen levels) between the data
canary is checked, if it is still intact and if not, a \ac{bof} occurred. This of a stack frame and the return address~\cite{Stackguard1998}\cite{AtkDef2016}.
technique is used in major operating systems %TODO When returning, the canary is checked, if it is still intact and if not, a
but can be defeted, if there \ac{bof} occurred. This technique is implemented by major
is an information leak that leaks the cannary to the attacker. The attacker is compilers~\cite{Gcc2003} but can be defeated, if there is an information leak
then able to construct a payload, that keeps the canary intact. that leaks the canary to the attacker. The attacker is then able to construct a
payload, that keeps the canary intact. This mitigation has a minimal
performance impact~\cite{Gcc2003} and offers a good level of protection. It is a
compiler extension so no modification of the code base is needed.
\subsection{Restricting Language Features to a Secure Subset} % \subsection{Restricting Language Features to a Secure Subset}
\subsection{Static Analysis} % \subsection{Static Analysis}
\subsection{Type System Solutions} \subsection{Type System Solutions}
\citeauthor{Dep2007} propose an extension to the C type system that extends it \citeauthor{Dep2007} 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 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 can have the buffer size associated to it~\cite{Dep2007}. This prevents indexing
with out-of-bounds values. This extension is a superset of C so any valid C code into a buffer with out-of-bounds values. This extension is a superset of C so
can be compiled using the extension and the codebase is improved incrementally. any valid C code can be compiled using the extension and the codebase is
If the type extension is advanced enough, the additional information might form improved incrementally. If the type extension is advanced enough, the
the base for a formal verification. additional information might form the base for a formal verification. In some
cases, the type extensions can even be inferred~\cite{Dep2007}.
This technique prevents all kinds of overflows, if used, but requires changes to
the codebase and is only effective where these changes are applied. Since it is
a compile-time solution, it does affect the compile-time but has no negative
effect on the runtime.
\subsection{Address Space Layout Randomization} \subsection{Address Space Layout Randomization}
\Ac{aslr} aims to prevent exploitatoin of \acp{bof} by placing code at random \Ac{aslr} aims to prevent exploitation of \acp{bof} by placing code at random
locations in memory. That way, it is not trivial to set the return address to locations in memory~\cite{AtkDef2016}. That way, it is not trivial to set the
point to the payload in memory. This is effective against generic exploits but return address to point to the payload in memory. This is effective against
it is still posible to exploit \ac{bof} vulnerabilities in combination with every kind of \ac{bof} vulnerability but it is still possible to exploit
information leaks or other techniques like heap spraying. Also on 32 bit \ac{bof} vulnerabilities in combination with information leaks or other
systems, the address space is small enough to try a brute-force attempt until techniques like heap spraying. Also on 32 bit systems, the address space is
the payload in memory is hit. small enough to try a brute-force attempt until the payload in memory is
hit~\cite{Effectiveness2014}.
This is another technique that works without modification of the code base. Also
there is no runtime overhead because nothing changed except the location of the
program.
\subsection{w\^{}x Memory} \subsection{w\^{}x Memory}
w\^{}x (also known as \ac{nx}) makes memory either writable or executable. That w\^{}x (also known as \ac{nx} or \ac{dep}) makes memory either writable or
way, an attacker cannot place arbitiary payloads in memory. There are still executable~\cite{AtkDef2016}. That way, an attacker cannot place arbitrary
techniques to exploit this by reusing existing executable code. The ret-to-libc payloads in memory. There are still techniques to exploit this by reusing
exploiting technique uses existing calls to the libc with attacker controlled existing executable code. The ret-to-libc exploiting technique uses existing
parameters, e.g.\ if the programm uses the \mintinline{shell}{system} command, calls to the libc with attacker controlled parameters, e.g.\ if the program uses
the attacker can plant \mintinline{shell}{/bin/sh} as parameter on the stack, the \mintinline{shell}{system} command, the attacker can plant
followed by the address of \mintinline{shell}{system} and get a shell on the \mintinline{shell}{/bin/sh} as parameter on the stack, followed by the address
system. \ac{rop} (a superset of ret-to-libc exploits) uses so called \ac{rop} of \mintinline{shell}{system} and get a shell on the system. \ac{rop} (a
gadgets, combinations of memory modifying instructions followed by the superset of ret-to-libc exploits) uses so called \ac{rop} gadgets, combinations
\mintinline{ASM}{RET} instruction to build instruction chains, that execute the of memory modifying instructions followed by the \mintinline{ASM}{RET}
desired shellcode. This is done by placing the desired return addresses in the instruction to build instruction chains, that execute the desired shell-code.
right order on the stack and reuses the existing code to circumvent the w\^{}x This is done by placing the desired return addresses in the right order on the
protection. These combinations of memory modification followed by stack and reuses the existing code to circumvent the w\^{}x protection. These
\mintinline{ASM}{RET} instructions are called \ac{rop} chains and are turing combinations of memory modification followed by \mintinline{ASM}{RET}
complete~\cite{Rop2007}, so in theory it is possible to implement any imaginable instructions are called \ac{rop} chains and are Turing complete~\cite{Rop2007},
payload, as long as the exploited program contains enough gadgets and the so in theory it is possible to implement any imaginable payload, as long as the
overflowing buffer has enough space. exploited program contains enough gadgets and the overflowing buffer has enough
space.
\section{Discussion}\label{ref:discussion} \section{Discussion}\label{ref:discussion}
\subsection{Ineffective or Inefficient} \subsection{Effectiveness}
\subsubsection{\ac{aslr}} \subsubsection{\ac{aslr}}
\Ac{aslr} has been really effective and wildly used in production. It is \Ac{aslr} has been proven effective and is wildly used in production. It is
included in most major operating systems~\cite{FBSDaslr}. Some even use kernel included in most major operating systems~\cite{FBSDaslr}. Some even use kernel
\ac{aslr}~\cite{Linuxaslr}. Since this mechanism is active at runtime, it does \ac{aslr}~\cite{Linuxaslr}. Since this mechanism is active at runtime, it does
not require any changes in the code itself, the programm only has to be compiled not require any changes in the code itself, the program only has to be compiled
as a \ac{pie}. On 32-bit CPUs, only 16-bit of the address are randomized. These as a \ac{pie}. On 32-bit CPUs, only 16-bit of the address are randomized. These
16-bit can be brute forced in a few minutes or seconds~\cite{AslrEffective2004}. 16-bit can be brute forced in a few minutes or seconds~\cite{AslrEffective2004}.
There is no runtime overhead since the only change is the position of the
program in memory. Since there is no additional work except maybe recompilation,
this technique can and should be used on modern systems.
\subsubsection{w\^{}x} \subsubsection{w\^{}x}
With the rise of \ac{rop} techniques, w\^{}x protection has been shown to be With the rise of \ac{rop} techniques, w\^{}x protection has been shown to be
ineffective. It makes vulnerabilities harder to exploit but does not prevent ineffective. It makes vulnerabilities harder to exploit by preventing the most
anything. naive types of payloads but it doesn't actually prevent exploits from happening.
\Ac{nx} does not prevent any exploits but makes it harder for an attacker that
does not know the system, the program is running on (e.g.\ a network service).
It has no runtime overhead and is a compile-time option so it does not hurt to
enable \ac{nx}.
\subsubsection{Runtime Bounds Checks} \subsubsection{Runtime Bounds Checks}
Checking for overflows at runtime is very effective but can have a huge Checking for overflows at runtime is very effective but can have a huge
performance impact so it is not feasible in every case. It also comes with other performance impact so it is not feasible in every case. It also comes with other
footguns. There might be integer overflows when calculating the bounts which footguns. There might be integer overflows when calculating the bounds which
might introduce other problems. might introduce other problems.
Methods that have been shown to be ineffective (e.g.\ can be circumvented
easily) or inefficient (to much runtime overhead)\ldots
\subsection{State of the Art} \subsection{State of the Art}
What techniques are currently used? Operating systems started to compile C code to \ac{pie} by
default~\cite{ArchPie2017} and \ac{aslr} is enabled, too. Same goes for \ac{nx}
and stack canaries~\cite{ArchPie2017}. The combination of these mitigations
makes it hard to write general exploits for modern operating systems.
\subsection{Outlook} To check the current state, the latest release of the \ac{gcc} (9.2) and the
latest commit of the LLVM-project (\mintinline[breaklines]{shell}{181ab91efc9})
are compiled using the default configuration. The experiments are performed on a
64-bit Debian 9.11 system running on version 4.19.0 of the Linux kernel. The
following commands are used for compilation:
\begin{figure}[h!]
\begin{subfigure}[b]{.3\textwidth}
\begin{minted}{shell}
mkdir objdir \
&& cd objdir \
&& ../configure \
--build=x86_64-linux-gnu \
--host=x86_64-linux-gnu \
--target=x86_64-linux-gnu \
--disable-multilib \
&& make -j8
\end{minted}
\caption{\ac{gcc} compilation script}\label{lst:gcc}
\end{subfigure}
\\
\begin{subfigure}[b]{.3\textwidth}
\begin{minted}{shell}
mkdir build \
&& cd build \
&& cmake -DLLVM_ENABLE_PROJECTS=clang \
-DCMAKE_BUILD_TYPE=Release \
-G "Unix Makefiles" ../llvm
&& make -j8
\end{minted}
\caption{clang compilation script}
\end{subfigure}
\end{figure}
The \mintinline{shell}{build}, \mintinline{shell}{host} and
\mintinline{shell}{target} parameters in~\ref{lst:gcc} only describe the target
platform for the compiler and \mintinline{shell}{disable-multilib} disables
32-bit support. The \mintinline{sh}{-j8} flag only tells make to use all 8
available cores for compilation.
The fresh builds of \ac{gcc} and clang compile the code from~\cref{lst:vuln} to
check which mitigations are enabled by default. Using
\mintinline[breaklines]{shell}{gcc -o vuln.gcc vuln.c} and
\mintinline[breaklines]{shell}{clang -o vuln.clang vuln.c} to compile the source
code, the \mintinline{shell}{checksec.sh} tool~\cite{Checksec2019} shows which
mitigations are active in the new binary:
\begin{table}[h!]
\begin{center}
\begin{tabular}{lll}
\toprule
Mitigation & Active in \ac{gcc}? & Active in clang? \\
\toprule
Stack Canary & No & No \\
\midrule
\ac{nx} & Yes & Yes \\
\midrule
\ac{pie} & No & No \\
\bottomrule
\end{tabular}
\caption{Enabled mitigations in a default \ac{gcc} and clang
build}\label{tab:mitigations}
\end{center}
\end{table}
Surprisingly enough, two of the most popular C compilers enable only one of the
described compile-time mitigations by default. Maintainer of operating system
packages of the compiler might choose a more secure configuration for the
compiler as shown in~\cite{ArchPie2017} but still, compiler vendors might want
to choose better defaults, too.
So far, all described mitigations don't change anything about the existence of
\acp{bof} but just try to prevent the exploitation for code execution. The
vulnerable programs will still terminate if the stack canary is overwritten, a
call into \ac{nx} memory occurs or execution continues inside garbage data due
to \ac{aslr}. The underlying problem persists, only the worst results are
mitigated. \Ac{dos} is still a problem in safety critical systems (e.g.\ cars,
planes, medical devices) or in any area with real-time requirements.
Language extensions to fix the problem of \acp{bof} as described
in~\cite{Dep2007} require lots of discipline to use them everywhere. They are
only useful if the whole codebase uses the new features. Introducing them in an
existing codebase is quite unrealistic since it requires lots of modifications.
On the other hand, this actually prevents \acp{bof} from happening and not just
from being exploited, so it looks like an interesting concept for safety
critical software.
\section{Conclusion}\label{ref:conclusion} \section{Conclusion}\label{ref:conclusion}
While there are many techniques, that protect against different types of While there are many techniques, that protect against different types of
\acp{bof}, none of them is effctive in every situation. Maybe we've come to a \acp{bof}, none of them is effective in every situation but in combination they
offer good protection against code execution attacks. Maybe we've come to a
point where we have to stop using memory unsafe languages where it is not 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 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 problem space as C, C++ or Fortran but without the issues coming from these
from these languages. If it is feasible to use a garbage collector, Go might languages. If it is feasible to use a garbage collector, languages like Go, Java
work just fine. If real-time properties are required, Rust could be the way to or even scripting languages like Python might work just fine. If real-time
go, without any language runtime and with deterministic memory management. For properties are required, Rust could be the way to go, without any language
any other problem, almost any other memory safe language is better than using runtime and with deterministic memory management. For any other problem, almost
unsafe C. any other memory safe language is better than using unsafe C.
\section{Sources (Dummy Section for Deadline)} % \section{Sources (Dummy Section for Deadline)}
\begin{itemize} % \begin{itemize}
\item RAD:\ A Compile-Time Solution to Buffer Overflow Attacks~\cite{Rad2001} % \item RAD:\ A Compile-Time Solution to Buffer Overflow Attacks~\cite{Rad2001}
(might not protect against e.g.\ vtable overrides, \ac{plt} address changes, % (might not protect against e.g.\ vtable overwrites, \ac{plt} address
\dots) % changes, \dots)
\item Dependent types for low-level programming~\cite{Dep2007} % \item Dependent types for low-level programming~\cite{Dep2007}
\item StackGuard: Automatic Adaptive Detection and Prevention of % \item StackGuard: Automatic Adaptive Detection and Prevention of
Buffer-Overflow Attachs~\cite{Stackguard1998} (ineffective in combination % Buffer-Overflow Attachs~\cite{Stackguard1998} (ineffective in combination
with information leaks) % with information leaks)
\item Type-Assisted Dynamic Buffer Overflow Detection~\cite{TypeAssisted2002} % \item Type-Assisted Dynamic Buffer Overflow Detection~\cite{TypeAssisted2002}
\item On the Effectiveness of NX, SSP, RenewSSP, and \ac{aslr} against Stack % \item On the Effectiveness of NX, SSP, RenewSSP, and \ac{aslr} against Stack
Buffer Overflows~\cite{Effectiveness2014} % Buffer Overflows~\cite{Effectiveness2014}
\item What Do We Know About Buffer Overflow Detection?: A Survey on Techniques % \item What Do We Know About Buffer Overflow Detection?: A Survey on Techniques
to Detect A Persistent Vulnerability~\cite{Detection2018} % to Detect A Persistent Vulnerability~\cite{Detection2018}
\item Survey of Attacks and Defenses on Stack-based Buffer Overflow % \item Survey of Attacks and Defenses on Stack-based Buffer Overflow
Vulnerability~\cite{AtkDef2016} % Vulnerability~\cite{AtkDef2016}
\item Beyond stack smashing: recent advances in exploiting buffer % \item Beyond stack smashing: recent advances in exploiting buffer
overruns~\cite{Smashing2004} % overruns~\cite{Smashing2004}
\item Runtime countermeasures for code injection attacks against C and C++ % \item Runtime countermeasures for code injection attacks against C and C++
programs~\cite{Counter2012} % programs~\cite{Counter2012}
\end{itemize} % \end{itemize}
\printbibliography{} \printbibliography{}

View File

@ -52,3 +52,13 @@
short = DOS, short = DOS,
long = denial of service long = denial of service
} }
\DeclareAcronym{gcc}{
short = GCC,
long = GNU compiler collection
}
\DeclareAcronym{dep}{
short = DEP,
long = data execution prevention
}

View File

@ -73,7 +73,7 @@ year = {2001}
@ARTICLE{Smashing2004, @ARTICLE{Smashing2004,
author={{Pincus}, J. and {Baker}, B.}, author={{Pincus}, J. and {Baker}, B.},
journal={{IEEE Security \& Privacy}}, journal={{IEEE Security and Privacy (SP)}},
title={{Beyond stack smashing: recent advances in exploiting buffer title={{Beyond stack smashing: recent advances in exploiting buffer
overruns}}, overruns}},
year={2004}, year={2004},
@ -126,6 +126,22 @@ year={2007}
title = {{7.1.1-4: enable SSP and PIE by default}} title = {{7.1.1-4: enable SSP and PIE by default}}
} }
@online{Heardbleed2014,
url = {http://heartbleed.com/},
urlDate = {2019-12-15},
year = {2014},
title = {{The Heartbleed Bug}},
author = {{Codenomicon}},
}
@online{Checksec2019,
url = {https://github.com/slimm609/checksec.sh},
urlDate = {2019-12-16},
year = {2019},
title = {{Checksec.sh}},
author = {{Klein}, Tobias}
}
@online{Tiobe2019, @online{Tiobe2019,
author = {{TIOBE}}, author = {{TIOBE}},
title = {{TIOBE Index for December 2019}}, title = {{TIOBE Index for December 2019}},