context/rnd restructure: add weakness mitigation
This commit is contained in:
parent
5fb007ba40
commit
5ec6c7245e
5 changed files with 449 additions and 264 deletions
|
@ -36,6 +36,16 @@
|
|||
first = {\glsentrylong{compiler}}
|
||||
}
|
||||
|
||||
\newglossaryentry{GCC}{
|
||||
name = GCC,
|
||||
long = {GNU Compiler Collection},
|
||||
description = {%
|
||||
GCC is an integrated distribution of compilers for several major programming languages.
|
||||
These languages currently include C, C++, Objective-C, Objective-C++, Java, Fortran, Ada, and Go.
|
||||
},
|
||||
first = {\glsentrylong{GCC}}
|
||||
}
|
||||
|
||||
\newglossaryentry{addrspace}{
|
||||
name = address space,
|
||||
long = bound address range in memory,
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
% // vim: set ft=tex:
|
||||
\chapter{Introduction}
|
||||
\label{context::introduction}
|
||||
|
||||
|
||||
This thesis studies the feasibility of using compile-time code analysis, as found in \gls{Rust}'s \gls{compiler}, for ensuring memory-safety within an \gls{os} kernel.
|
||||
This study could be applied to all \glspl{app}, but the focus is on the implementation of \glspl{os} which is the \gls{app} that is responsible for managing the system's resources and provide abstractions for all other \glspl{app}.
|
||||
For this the \gls{os} is the only \gls{app} that required unrestricted access to these resources, with the responsibility of managing them safely according to the rules that are either hard-coded or set up by the \gls{sysadmin}.
|
||||
|
||||
The increasing number of vulnerabilities based on memory-safety issues in \glspl{app}, as presented in \cref{context::common-mem-safety-mistakes::cwe::statistics}, is a major motivator for working on this topic.
|
||||
The increasing number of vulnerabilities based on memory-safety issues in \glspl{app}, as presented in \cref{context::weaknesses-mem-safety::cwe::statistics}, is a major motivator for working on this topic.
|
||||
|
||||
\section{Motivational Hypothesis}
|
||||
% Primary Research Questions
|
||||
|
@ -26,7 +24,7 @@ These implementations are subject to evaluation in \cref{rnd::existing-os-dev-wi
|
|||
The final results will be of qualitative nature, captured by analyzing the existing and a self-developed \gls{Rust}-implementations of popular memory management techniques.
|
||||
In addition to the sole analysis of \gls{Rust}-implementations, comparisons will be made, discerning the level of memory safety guarantees gained over similarly intending implementations in \gls{C}.
|
||||
|
||||
\section{Assessing Memory-Safety}
|
||||
\section{What is Memory-Safety?}
|
||||
\label{context::introduction::memory-safety}
|
||||
Memory-safety is a term that is only vaguely defined in general, thus a definition is given for the context of this thesis.
|
||||
For a thorough understanding of the issues discussed further in this document, it might be helpful to review the basics of how memory is used in current computer systems.
|
||||
|
@ -94,16 +92,75 @@ Higher focus on safety and testing in education, enforced internal company guide
|
|||
For this thesis such constraints are out of scope, and the focus is on examining technical methods that detect and indicate mistakes as early as possible.
|
||||
|
||||
\subsection{Technical Aspect}
|
||||
The problem on the technical side is that the \gls{compiler} is not able to detect all errors that are in the source code and the human was able to produce an executable program.
|
||||
\label{context::introduction::technical-aspect}
|
||||
As established in the \nameref{context::introduction::human-aspect}, it can not be prevented for individuals to type erroneous code into their code editors, thus a technical solution must be found.
|
||||
The problem on the technical side is that the \gls{compiler} is not able to detect all errors that are in the source code and humans are able to produce an executable program from problematic source code.
|
||||
The resulting executable program might merely serve its purpose, and can contain severe technical mistakes that are not considered an error by the \gls{compiler}.
|
||||
This is especially likely using low-abstraction languages like \gls{C} and \gls{C++} for \gls{os} development, where technical mistakes and intended behavior are very difficult to distinguish.
|
||||
The goal of this thesis is to find out if the \gls{Rust} \gls{compiler} is able to mitigate this specific problem.
|
||||
|
||||
The ultimate goal beyond this project must be to prevent any kind of vulnerable or erroneous software from being distributed to production systems.
|
||||
This project's contribution towards that goal is to evaluate if \gls{Rust}'s \gls{compiler} is able to guarantee safe memory-management in the \gls{os}.
|
||||
|
||||
\subsection{Time Aspect}
|
||||
\label{context::introduction::memory-safety::time-aspect}
|
||||
Tests are important for the functionality and safety of a \gls{app}.
|
||||
In addition to the presence and quality of tests, their timing in the software life cycle plays an important role.
|
||||
It is desirable to place software tests as early as possible in the software life cycle and detect mistakes then, rather than compromising production-systems that hold sensitive data and offer important services.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\smartdiagramset{
|
||||
back arrow disabled=true,
|
||||
module minimum width=5cm,
|
||||
text width=4cm,
|
||||
additions={
|
||||
additional item offset=1cm,
|
||||
additional item width=4cm,
|
||||
additional item border color=gray,
|
||||
additional item text width=4cm,
|
||||
additional arrow tip=to,
|
||||
additional arrow line width=2pt,
|
||||
additional arrow color=black,
|
||||
},
|
||||
}
|
||||
\smartdiagramadd[flow diagram]{
|
||||
Design,
|
||||
Programming,
|
||||
Compilation,
|
||||
Distribution,
|
||||
Execution
|
||||
}{%
|
||||
right of module2/When vulnerabilities are created,
|
||||
right of module3/When they should be detected,
|
||||
right of module5/When they create real problems
|
||||
}
|
||||
\smartdiagramconnect{to-}{module2/additional-module1}
|
||||
\smartdiagramconnect{to-}{module3/additional-module2}
|
||||
\smartdiagramconnect{to-}{module5/additional-module3}
|
||||
\caption{Simple Software Life Cycle}
|
||||
\label{fig:simple-software-lifecycle}
|
||||
\end{figure}
|
||||
A simple software life cycle model is visualized in \cref{fig:simple-software-lifecycle}.
|
||||
|
||||
Assuming that there is a software design, even a flawless one, the next step is to translate this flawless design into flawless source code.
|
||||
The is a manual translation step from one representation into another, leaving much room for mistakes.
|
||||
The next component in the chain is the \gls{compiler} which processes the source code by translating it to the next representation, machine code.
|
||||
This is the step that where source code analysis can be technically enforced.
|
||||
Ideally, as previously explained, the \gls{compiler} should be able to detect the programmers mistakes, especially the ones that have a negative impact on memory-safety.
|
||||
Advanced programmers can profit too, as everybody makes mistakes from time to time, depending on the level of focus, which is not a constant.
|
||||
|
||||
When programmers talk about tests, they typically mean little functions they have to write to test the actual functions of their programs.
|
||||
This kind of testing requires the execution of the program after its compilation, and is likely to neglect severe technical mistakes.
|
||||
The method of testing the source code directly has much more potential, because relations between source code objects can be analyzed.
|
||||
Various \textit{static code analyzer} tools have become popular for such analysis.
|
||||
However, these are always optional and the developer cannot be forced to use them.
|
||||
Much different is the situation when the analysis is part of the \gls{compiler}, which is the case in \gls{Rust}.
|
||||
|
||||
\chapter{OS Development: Concepts, Conventions, Risks}
|
||||
\label{context::os-dev-concepts}
|
||||
In order to protect the memory of each executed program according to \cref{context::introduction::memory-safety::def}, the \gls{os} must be designed developed, and tested carefully.
|
||||
This chapter explains concepts used in \gls{os} development and points out memory-safety critical operations in necessary detail.
|
||||
This is done in preparation for the next \cref{context::common-mem-safety-mistakes}, which explains weaknesses that result from memory management mistakes that were made in the attempt to implement the following concepts.
|
||||
This is done in preparation for the next \cref{context::weaknesses-mem-safety}, which explains weaknesses that result from memory management mistakes that were made in the attempt to implement the following concepts.
|
||||
|
||||
Since the \gls{os} manages the system's hardware directly, many of the implementation and design choices depend on hardware design and architecture.
|
||||
To bound the extent of this document, the explanations are limited to one contemporary architecture, \gls{amd64}, and further narrowed down by focusing on the operation in 64-Bit Long Mode\cite[p.~18]{AMD64Vol2}.
|
||||
|
@ -121,9 +178,7 @@ The \gls{os} then provides an \gls{api} through which \glspl{app} can request ac
|
|||
Higher-level \glspl{proglang} allow the \gls{app} developers to develop and run different programs comfortably, concurrently and presumably safely on any hardware which is supported by the \gls{os}.
|
||||
\Cref{fig:system-abstraction-layers} shows a top-down model of the abstractions layers in the system.
|
||||
|
||||
\usetikzlibrary{shapes.geometric, arrows}
|
||||
\begin{figure}[ht]
|
||||
\usetikzlibrary{chains,arrows.meta,decorations.pathmorphing,quotes}
|
||||
\begin{tikzpicture}
|
||||
[start chain=main going below, every on chain/.append style={align=center, text width=35ex, minimum height=7ex, fill=blue!20}, >={LaTeX[]}, node distance=7ex]
|
||||
% \node[on chain] {\gls{os} Abstraction Layers};
|
||||
|
@ -556,7 +611,7 @@ In this picture, the \gls{stack} grows upwards.
|
|||
|
||||
\subsubsection{Safety Concerns}
|
||||
To achieve memory-safe \gls{stack} management in the \gls{os}, each procedure must only be able to access its own particular \gls{stack} and possible references via its arguments.
|
||||
This is not the case in a regular \gls{C} program, where the called procedure is able to modify the previous \gls{sf}, which is demonstrated in \cnameref{context::common-mem-safety-mistakes::manifestations::ret-addr-manipulation}.
|
||||
This is not the case in a regular \gls{C} program, where the called procedure is able to modify the previous \gls{sf}, which is demonstrated in \cnameref{rnd::weakness-mitig-eval::stack-protection}.
|
||||
|
||||
Additionally, the \glspl{stack} must be prevented from growing into other memory zones like the \gls{heap}.
|
||||
Since \Gls{stack} management is memory-safety critical for \gls{os} developers when implementing memory management for multitasking within the \gls{os}, it is one of the main subjects in \cnameref{rnd}, \cref{rnd::existing-os-dev-with-rust,rnd::imezzos-preemptive-multitasking}.
|
||||
|
@ -897,33 +952,35 @@ The function that handles the interrupt must then use the instruction \textit{ir
|
|||
|
||||
For a full context-switch, the other registers that are part of the context need to be handled by the \gls{os}'s interrupt function.
|
||||
|
||||
\chapter{Common Memory-Safety Mistakes}
|
||||
\label{context::common-mem-safety-mistakes}
|
||||
\chapter{Weaknesses That Affect Memory-Safety}
|
||||
\label{context::weaknesses-mem-safety}
|
||||
The previous \cref{context::introduction,context::os-dev-concepts} describe the concepts of memory management on \gls{amd64} and how mistakes might come into existence.
|
||||
This chapter describes the related software weaknesses which are too commonly found.
|
||||
The underlying weakness classes are explained alongside real-world and exemplary manifestations in \gls{C}.
|
||||
The latter are ported and compared to functionally equivalent versions written with \gls{Rust} in \cref{rnd::porting-c-vulns},
|
||||
The latter are ported and compared to functionally equivalent versions written with \gls{Rust} in \cref{rnd::weakness-mitig-eval::porting-c-vulns},
|
||||
|
||||
\section{\glsentrylong{CWE}}
|
||||
\label{context::common-mem-safety-mistakes::cwe}
|
||||
%\section{\glsentrylong{CWE}}
|
||||
%\label{context::weaknesses-mem-safety::cwe}
|
||||
Ongoing effort of collecting, analyzing and classifying vulnerabilities and their underlying weaknesses has been expended by the \textit{The MITRE Corporation} in form of the \gls{CWE}.
|
||||
It has grown to a large relational database of typed weaknesses.
|
||||
The following information is provided for enumerations of the type weakness class:
|
||||
\begin{itemize}
|
||||
\item Description
|
||||
\item Applicable Platforms
|
||||
\item Common Consequences
|
||||
\item Likelihood of Exploit
|
||||
\item Demonstrative Examples
|
||||
\item Potential Mitigations
|
||||
\item Relationships
|
||||
\end{itemize}
|
||||
\begin{markdown}
|
||||
1. Description
|
||||
1. Applicable Platforms
|
||||
1. Common Consequences
|
||||
1. Likelihood of Exploit
|
||||
1. Demonstrative Examples
|
||||
1. Potential Mitigations
|
||||
1. Relationships
|
||||
\end{markdown}
|
||||
|
||||
The relevant weaknesses for this thesis are children of the umbrella weakness \citetitle{MITRE-CWE-633}.
|
||||
Their information about demonstrative examples and potential mitigations are relevant for this thesis.
|
||||
This and the following \cref{context::weakness-mitigation} present this information for \gls{CWE-633} and selected children.
|
||||
|
||||
% TODO test the autocite command with footnotes
|
||||
\subsection{\glsentrylong{CWE-119}}
|
||||
\label{context::common-mem-safety-mistakes::cwe::119}
|
||||
\section{\glsentrylong{CWE-119}}
|
||||
\label{context::weaknesses-mem-safety::cwe::119}
|
||||
One of its children weaknesses, \gls{CWE-119}, is particularly interesting.
|
||||
Manifestations of this weakness are a direct violation of the memory-safety defined in \cref{context::introduction::memory-safety::def} must have occurred, which "can cause read or write operations to be performed on memory locations that may be associated with other variables, data structures, or internal program data.
|
||||
As a result, an attacker may be able to execute arbitrary code, alter the intended control flow, read sensitive information, or cause the system to crash"\cite{MITRE-CWE-119}.
|
||||
|
@ -936,8 +993,8 @@ There are languages that provide memory management support and still allow direc
|
|||
\gls{Rust} is one of these languages, although it requires the developer to explicitly acknowledge all direct memory access operations with the \textit{unsafe} keyword.
|
||||
More information on \gls{Rust} follows in \cref{context::rust}.
|
||||
|
||||
\subsection{Statistics}
|
||||
\label{context::common-mem-safety-mistakes::cwe::statistics}
|
||||
\section{Statistics}
|
||||
\label{context::weaknesses-mem-safety::cwe::statistics}
|
||||
One of the main reasons for me to work on this topic is the increasing number of vulnerabilities based on memory-safety issues.
|
||||
|
||||
This section is intended to express the weakness's severity in real-world software based on available statistics.
|
||||
|
@ -986,7 +1043,7 @@ In \cref{tab:vulnerability-buffer-error-by-history}, the column \textit{relative
|
|||
With 16.34 percent of all vulnerabilities known by 2016, and an average of 12.92 percent over ten years, \autocite{MITRE-CWE-119} makes up a significant part of real-world weaknesses.
|
||||
|
||||
\subsection{Vulnerable APIs in Linux and C/C++}
|
||||
\label{context::common-mem-safety-mistakes::vuln-apis-linux-c}
|
||||
\label{context::weaknesses-mem-safety::vuln-apis-linux-c}
|
||||
\glspl{api} are a ubiquitous for programmers to access all kinds of functionality, serving as interfaces to network services, providing existing algorithms in form of libraries and frameworks, or interfacing with the local \gls{os}.
|
||||
It is inherently dangerous to expose any sort of functionality through an \gls{api}, as it might contain bugs that will be spread widely with rising popularity.
|
||||
Every \gls{os} needs to provide an \gls{api} for it's core functionality to be useful and extendable.
|
||||
|
@ -1003,40 +1060,64 @@ The difficulty is to perform these transfers only under safe circumstances, whic
|
|||
It is necessary to investigate some of the weakness manifestations in detail in order to analyze if these might be prevented by using \gls{Rust}.
|
||||
|
||||
\section{Manifestations}
|
||||
\label{context::common-mem-safety-mistakes::manifestations}
|
||||
\label{context::weaknesses-mem-safety::manifestations}
|
||||
This section contains real-world manifestations and \textit{re}constructed experiments of memory-safety related weaknesses.
|
||||
% TODO
|
||||
It requires common understanding of the \gls{C} language and knowledge from the previous chapters.
|
||||
|
||||
\subsection{CWE-119 Examples}
|
||||
These examples are officially listed under the \autocite{MITRE-CWE-119} website.
|
||||
\subsection{Official CWE Examples}
|
||||
The following examples are officially listed under various children of \citetitle{MITRE-CWE-633}\cite{MITRE-CWE-633}.
|
||||
The code and descriptions are copied literally and are used as references throughout the document.
|
||||
The numbering in the example names aren't contiguous because only a subset was selected, and the naming is supposed to match the \gls{CWE} website.
|
||||
References to the respective \gls{Rust} version are generally found in \cpnameref{rnd::weakness-mitig-eval::porting-c-vulns}, and referenced under each specific example for easier navigation.
|
||||
|
||||
\subsubsection{Example 1}
|
||||
This example takes an IP address from a user, verifies that it is well formed and then looks up the hostname and copies it into a buffer.
|
||||
\subsubsection{CWE-119}
|
||||
\glsentrylong{CWE-119}
|
||||
|
||||
\paragraph{Example 1}
|
||||
The following code asks the user to enter their last name and then attempts to store the value entered in the last\_name array.
|
||||
|
||||
\begin{listing}[htb]
|
||||
\begin{minted}[autogobble,linenos,breaklines=true]{c}
|
||||
void host_lookup(char *user_supplied_addr){
|
||||
struct hostent *hp;
|
||||
in_addr_t *addr;
|
||||
char hostname[64];
|
||||
in_addr_t inet_addr(const char *cp);
|
||||
|
||||
/*routine that ensures user_supplied_addr is in the right format for conversion */
|
||||
validate_addr_form(user_supplied_addr);
|
||||
addr = inet_addr(user_supplied_addr);
|
||||
hp = gethostbyaddr( addr, sizeof(struct in_addr), AF_INET);
|
||||
strcpy(hostname, hp->h_name);
|
||||
}
|
||||
...
|
||||
char last_name[20];
|
||||
printf ("Enter your last name: ");
|
||||
scanf ("%s", last_name);
|
||||
...
|
||||
\end{minted}
|
||||
\caption{Bad Code}
|
||||
%\label{code::context::examples::func-callee-c}
|
||||
\caption{CWE-120: Example 1 Bad Code C}
|
||||
\label{code::CWE-120::Example1BadCCode}
|
||||
\end{listing}
|
||||
\FloatBarrier
|
||||
|
||||
This function allocates a buffer of 64 bytes to store the hostname, however there is no guarantee that the hostname will not be larger than 64 bytes. If an attacker specifies an address which resolves to a very large hostname, then we may overwrite sensitive data or even relinquish control flow to the attacker.
|
||||
The problem with the code above is that it does not restrict or limit the size of the name entered by the user. If the user enters "Very\_very\_long\_last\_name" which is 24 characters long, then a buffer overflow will occur since the array can only hold 20 characters total.
|
||||
|
||||
Note that this example also contains an unchecked return value (CWE-252) that can lead to a NULL pointer dereference (CWE-476).
|
||||
% \paragraph{Example 1}
|
||||
% This example takes an IP address from a user, verifies that it is well formed and then looks up the hostname and copies it into a buffer.
|
||||
%
|
||||
% \begin{listing}[htb]
|
||||
% \begin{minted}[autogobble,linenos,breaklines=true]{c}
|
||||
% void host_lookup(char *user_supplied_addr){
|
||||
% struct hostent *hp;
|
||||
% in_addr_t *addr;
|
||||
% char hostname[64];
|
||||
% in_addr_t inet_addr(const char *cp);
|
||||
%
|
||||
% /*routine that ensures user_supplied_addr is in the right format for conversion */
|
||||
% validate_addr_form(user_supplied_addr);
|
||||
% addr = inet_addr(user_supplied_addr);
|
||||
% hp = gethostbyaddr( addr, sizeof(struct in_addr), AF_INET);
|
||||
% strcpy(hostname, hp->h_name);
|
||||
% }
|
||||
% \end{minted}
|
||||
% \caption{CWE-119: Example 1 Bad Code C}
|
||||
% \label{code::CWE-119::Example1BadCCode}
|
||||
% \end{listing}
|
||||
%
|
||||
% This function allocates a buffer of 64 bytes to store the hostname, however there is no guarantee that the hostname will not be larger than 64 bytes. If an attacker specifies an address which resolves to a very large hostname, then we may overwrite sensitive data or even relinquish control flow to the attacker.
|
||||
%
|
||||
% Note that this example also contains an unchecked return value (CWE-252) that can lead to a NULL pointer dereference (CWE-476).
|
||||
|
||||
\subsubsection{Example 2}
|
||||
\paragraph{Example 2}
|
||||
This example applies an encoding procedure to an input string and stores it into a buffer.
|
||||
|
||||
\begin{listing}[htb]
|
||||
|
@ -1063,12 +1144,13 @@ This example applies an encoding procedure to an input string and stores it into
|
|||
return dst_buf;
|
||||
}
|
||||
\end{minted}
|
||||
\caption{Bad Code}
|
||||
%\label{code::context::examples::func-callee-c}
|
||||
\caption{CWE-119: Example 2 Bad Code C}
|
||||
\label{code::CWE-119::Example2BadCodeC}
|
||||
\end{listing}
|
||||
\FloatBarrier
|
||||
The programmer attempts to encode the ampersand character in the user-controlled string, however the length of the string is validated before the encoding procedure is applied. Furthermore, the programmer assumes encoding expansion will only expand a given character by a factor of 4, while the encoding of the ampersand expands by 5. As a result, when the encoding procedure expands the string it is possible to overflow the destination buffer if the attacker provides a string of many ampersands.
|
||||
|
||||
\subsubsection{Example 3}
|
||||
\paragraph{Example 3}
|
||||
The following example asks a user for an offset into an array to select an item.
|
||||
|
||||
\begin{listing}[htb]
|
||||
|
@ -1079,12 +1161,13 @@ The following example asks a user for an offset into an array to select an item.
|
|||
printf("You selected %s\n", items[index-1]);
|
||||
}
|
||||
\end{minted}
|
||||
\caption{Bad Code}
|
||||
%\label{code::context::examples::func-callee-c}
|
||||
\caption{CWE-119: Example 3 Bad Code C}
|
||||
\label{code::CWE-119::Example3BadCodeC}
|
||||
\end{listing}
|
||||
\FloatBarrier
|
||||
The programmer allows the user to specify which element in the list to select, however an attacker can provide an out-of-bounds offset, resulting in a buffer over-read (CWE-126).
|
||||
|
||||
\subsubsection{Example 4}
|
||||
\paragraph{Example 4}
|
||||
In the following code, the method retrieves a value from an array at a specific array index location that is given as an input parameter to the method
|
||||
\begin{listing}[htb]
|
||||
\begin{minted}[autogobble,linenos,breaklines=true]{c}
|
||||
|
@ -1109,9 +1192,11 @@ In the following code, the method retrieves a value from an array at a specific
|
|||
return value;
|
||||
}
|
||||
\end{minted}
|
||||
\caption{Bad Code}
|
||||
%\label{code::context::examples::func-callee-c}
|
||||
\caption{CWE-119: Example 4 Bad Code C}
|
||||
\label{code::CWE-119::Example4BadCodeC}
|
||||
\end{listing}
|
||||
\FloatBarrier
|
||||
|
||||
However, this method only verifies that the given array index is less than the maximum length of the array but does not check for the minimum value (CWE-839). This will allow a negative value to be accepted as the input array index, which will result in a out of bounds read (CWE-125) and may allow access to sensitive memory. The input array index should be checked to verify that is within the maximum and minimum range required for the array (CWE-129). In this example the if statement should be modified to include a minimum range check, as shown below.
|
||||
|
||||
\begin{listing}[htb]
|
||||
|
@ -1124,94 +1209,65 @@ However, this method only verifies that the given array index is less than the m
|
|||
|
||||
...
|
||||
\end{minted}
|
||||
\caption{Good Code}
|
||||
%\label{code::context::examples::func-callee-c}
|
||||
\caption{CWE-119: Example 4 Good Code C}
|
||||
\label{code::CWE-119::Example4GoodCodeC}
|
||||
\end{listing}
|
||||
|
||||
\subsection{Return Address Manipulation}
|
||||
\label{context::common-mem-safety-mistakes::manifestations::ret-addr-manipulation}
|
||||
\Cref{code::context::examples::sf-modification-simple} is a little example program in \gls{C}, which manipulates the return function address stored on the \gls{stack}.
|
||||
This is done by simple and legal pointer arithmetic.
|
||||
It abuses the address of the first local variable to create references into the \gls{sf} below on the \gls{stack}.
|
||||
Since the first variable is in the beginning of the \gls{sf} of the called function, it can be used to guess the position of the return address on the \gls{stack}.
|
||||
Depending on the \gls{compiler} settings, the return address is stored either one or two stack entries in front of the first local variable for a function with no arguments.
|
||||
In a brute-force manner the program simply overwrites both entries with the address of \mintinline{c}{simple_printer}.
|
||||
By writing a different function address at these entries, the \mintinline{c}{ret} instruction will jump there, since the original return address has been overwritten.
|
||||
|
||||
\begin{figure}[ht!]
|
||||
\begin{subfigure}[T]{0.60\textwidth}
|
||||
\centering
|
||||
\begin{minted}[linenos,breaklines]{c}
|
||||
void modifier(void) {
|
||||
uint64_t *p;
|
||||
*(&p + 1) =
|
||||
(uint64_t *)simple_printer;
|
||||
*(&p + 2) =
|
||||
(uint64_t *)simple_printer;
|
||||
}
|
||||
\end{minted}
|
||||
\subcaption{C code}
|
||||
\end{subfigure}
|
||||
\begin{subfigure}[T]{0.39\textwidth}
|
||||
\centering
|
||||
\begin{minted}[linenos,breaklines]{objdump}
|
||||
movabs rax,0x400690
|
||||
mov QWORD PTR [rsp],rax
|
||||
mov QWORD PTR [rsp+0x8],rax
|
||||
ret
|
||||
\end{minted}
|
||||
\subcaption{ASM code}
|
||||
\end{subfigure}
|
||||
\caption{Stack-Frame Modification}
|
||||
\label{code::context::examples::sf-modification-simple}
|
||||
\end{figure}
|
||||
|
||||
\Cref{TODO-callstack-manipulation} is an attempt to visualize what happens in memory and with the \gls{stack} and the \gls{cpu}'s RIP {64-Bit Instruction Pointer} register.
|
||||
|
||||
\begin{figure}
|
||||
\includegraphics[width=\textwidth]{gfx/TODO-callstack-manipulation}
|
||||
\caption{TODO-callstack-manipulation}
|
||||
\label{TODO-callstack-manipulation}
|
||||
\end{figure}
|
||||
\FloatBarrier
|
||||
|
||||
\subsection{Uninitialized Pointers}
|
||||
|
||||
\begin{lstlisting}[language=C,
|
||||
directivestyle={\color{black}}
|
||||
emph={int,char,double,float,unsigned},
|
||||
emphstyle={\color{blue}}
|
||||
]
|
||||
char *src = "hello" ; // character string constant
|
||||
char *dst; // unallocated
|
||||
strcpy(dst, src); // segfault and die
|
||||
\end{lstlisting}
|
||||
\subsubsection{CWE-122: Heap-based Buffer Overflow}
|
||||
|
||||
\subsection{Null-Pointers}
|
||||
\paragraph{Example 1}
|
||||
|
||||
\begin{lstlisting}[language=C,
|
||||
directivestyle={\color{black}}
|
||||
emph={int,char,double,float,unsigned},
|
||||
emphstyle={\color{blue}}
|
||||
]
|
||||
char *ptr;
|
||||
int ret;
|
||||
if (ret = init_ptr(ptr)) {
|
||||
return ret;
|
||||
While buffer overflow examples can be rather complex, it is possible to have very simple, yet still exploitable, heap-based buffer overflows:
|
||||
\begin{listing}[htb]
|
||||
\begin{minted}[autogobble,linenos,breaklines=true]{c}
|
||||
#define BUFSIZE 256
|
||||
int main(int argc, char **argv) {
|
||||
char *buf;
|
||||
buf = (char *)malloc(sizeof(char)*BUFSIZE);
|
||||
strcpy(buf, argv[1]);
|
||||
}
|
||||
\end{minted}
|
||||
\caption{CWE-120: Example 1 Bad Code C}
|
||||
\label{code::CWE-122::Example1BadodeC}
|
||||
\end{listing}
|
||||
\FloatBarrier
|
||||
The buffer is allocated heap memory with a fixed size, but there is no guarantee the string in argv[1] will not exceed this size and cause an overflow.
|
||||
|
||||
\subsubsection{CWE-134: Use of Externally-Controlled Format String}
|
||||
|
||||
\paragraph{Example 1}
|
||||
The following program prints a string provided as an argument.
|
||||
\begin{listing}[htb]
|
||||
\begin{minted}[autogobble,linenos,breaklines=true]{c}
|
||||
#include <stdio.h>
|
||||
|
||||
void printWrapper(char *string) {
|
||||
printf(string);
|
||||
}
|
||||
|
||||
if (ptr == NULL) {
|
||||
// gracefully handles the NP
|
||||
} else {
|
||||
// may assume that the ptr address is not NULL
|
||||
int main(int argc, char **argv) {
|
||||
char buf[5012];
|
||||
memcpy(buf, argv[1], 5012);
|
||||
printWrapper(argv[1]);
|
||||
return (0);
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{minted}
|
||||
\caption{CWE-134: Example 1 Bad Code C}
|
||||
\label{code::CWE-134::Example1BadodeC}
|
||||
\end{listing}
|
||||
\FloatBarrier
|
||||
The example is exploitable, because of the call to printf() in the printWrapper() function. Note: The stack buffer was added to make exploitation more simple.
|
||||
|
||||
\subsection{Heartbleet}
|
||||
% TODO: paper about hearbleet with Rust
|
||||
|
||||
\subsection{The Stack Clash}
|
||||
\label{context::common-mem-safety-mistakes::manifestations::stack-clash}
|
||||
\label{context::weaknesses-mem-safety::manifestations::stack-clash}
|
||||
A recent high severity vulnerability named \textit{Stack Clash}\cite{TheStackClash}, is briefly described as \textit{"a vulnerability in the memory management of several operating systems. It affects Linux, OpenBSD, NetBSD, FreeBSD and Solaris, on i386 and amd64. It can be exploited by attackers to corrupt memory and execute arbitrary code."}
|
||||
The \gls{LX} specific vulnerability is listed as CVE-2017-1000364\footnote{\url{http://www.cvedetails.com/cve/CVE-2017-1000364/}}, where \textit{"an issue was discovered in the size of the stack guard page on Linux, specifically a 4k stack guard page is not sufficiently large and can be "jumped" over (the stack guard page is bypassed)"}.
|
||||
The vulnerability is assigned to the \citetitle{MITRE-CWE-119}\autocite{MITRE-CWE-119} presented in \cref{context::common-mem-safety-mistakes::cwe::119}.
|
||||
The vulnerability is assigned to the \citetitle{MITRE-CWE-119}\autocite{MITRE-CWE-119} presented in \cref{context::weaknesses-mem-safety::cwe::119}.
|
||||
|
||||
\subsubsection{Affecting Multiple OSs}
|
||||
The vulnerability is extremely interesting for several reasons.
|
||||
|
@ -1242,65 +1298,95 @@ This effectively overlaps the stack and the heap and makes it possible to use ac
|
|||
The best case scenario is mere memory corruption and the crash of the application.
|
||||
In the worst case there's possible execution of arbitrary code, which can be by used by an attacker to gain control of the application and possibly the whole system.
|
||||
|
||||
\subsubsection{Solutions}
|
||||
\subsubsection{Proposed Solutions}
|
||||
The researchers at \textit{qualys} suggest two solutions\cite[III]{TheStackClash}.
|
||||
|
||||
The first proposed solution is to increase the guard page to 1MB or larger within the \gls{os}.
|
||||
This doesn't guarantee absolute protection as it still be possible to have a large enough stack growth that surpasses the 1MB guard.
|
||||
|
||||
The second solution doesn't involve the \gls{os} at all.
|
||||
The suggestion is to compile all \glspl{app} on the system with the GCC \gls{compiler} option \mintinline{markdown}{`-fstack-check`}.
|
||||
The second solution doesn't involve the \gls{os} but is about the userspace programs.
|
||||
The suggestion is to compile all \glspl{app} on the system with the \gls{GCC}\cite{GCC540} with the \code{-fstack-check} option.
|
||||
This allegedly "prevents the stack-pointer from moving into another memory region without accessing the stack guard-page (it writes one word to every 4KB page allocated on the stack)."
|
||||
This features seems interesting to investigate further, as stack protection is also something procedures within the \gls{os} could make use of.
|
||||
Besides the mention of this option, there is no explanation of what the exact technical outcome is.
|
||||
This is further investigated in \cref{rnd::weakness-mitig-eval::stack-protection}, as stack protection is also something procedures within the \gls{os} could make use of.
|
||||
|
||||
\chapter{Weakness Mitigation}
|
||||
\chapter{Weakness Mitigation And Prevention Strategies}
|
||||
\label{context::weakness-mitigation}
|
||||
This chapter explains what can be done to mitigate and prevent software weaknesses, focusing on actions that can be taken by the developer.
|
||||
The first step is to leverage the \gls{CWE}'s database with its suggestions.
|
||||
With that information and the knowledge from previous chapters, it is then concluded that the choice of \gls{proglang} is significant for memory-safety in \gls{os} and \glspl{app}.
|
||||
|
||||
\section{Detecting Memory-Safety Violations ASAP}
|
||||
\label{context::safe-os-dev::detecting-safety-violations-asap}
|
||||
Given that it can not be prevented for individuals to type erroneous code into their code editors.
|
||||
\section{CWE-119 Mitigation Suggestions}
|
||||
\label{context::weakness-mitigation::cwe-119-suggestions}
|
||||
The \gls{CWE-119} lists mitigation attempts for these software life cycle phases: Requirements, Architecture and Design, Implementation, and Operation.
|
||||
|
||||
Ideally, the \gls{compiler} should be able to detect the programmers technical mistakes, especially the ones that have a negative impact on memory-safety.
|
||||
For the requirements phase, \gls{CWE-119} suggests to "use a language that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid".
|
||||
Such languages "perform their own memory management are not subject to buffer overflows".
|
||||
|
||||
Advanced programmers can profit too, as everybody makes mistakes from time to time, depending on the level of focus which is not a constant.
|
||||
This is followed by various other suggestions, of which the most relevant ones have been extracted into the following list.
|
||||
This list serves as additional test criteria against \gls{Rust}, evaluated in \cref{rnd}.
|
||||
|
||||
The human aspect suggests that systems needs to be designed to be testable, and then tested thoroughly in order to mitigate the risks of erroneous software being executed by the end-user.
|
||||
\begin{itemize}
|
||||
\item{Architecture and Design - Use Libraries or Frameworks
|
||||
Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.
|
||||
|
||||
In addition to the presence and quality of tests, their timing in the software life cycle plays an important role.
|
||||
The earliest tests can be as soon as the process of software development itself, and the latest ones can be at the time of execution on the production system of the end-user.
|
||||
It is desirable to place tests as early as possible in the software life cycle, to prevent them from compromising running systems that hold sensitive data and offer important services.
|
||||
These libraries provide safer versions of overflow-prone string-handling functions: Safe C String Library (SafeStr)
|
||||
}
|
||||
\item{Build and Compilation - Hardened Compilation
|
||||
|
||||
This suggests that since the \gls{os} is lower in the hierarchy of system components at runtime, testing of the \gls{os} must happen regardless of specific \glspl{app} and development time.
|
||||
Especially testing the \gls{os}'s internal states which can not be directly mutated via the \gls{api} exposed to the \glspl{app}.
|
||||
To explain this from the \gls{app} perspective, testing the \gls{os} at runtime states is not plausible , because the \gls{app} can not freely mutate the system's state.
|
||||
Even if it could, testing all possible permutations of system state in every possible \gls{app} would be highly redundant and nonetheless leaves the risk for untested edge cases that happen only under specific system circumstances, possibly influenced by other components on the system as described in the beginning of \cref{context::introduction::memory-safety}.
|
||||
The \gls{app} developer is forced to trust the underlying \gls{os}.
|
||||
This puts high importance on the safety of the \gls{os} design and implementation.
|
||||
Run or compile the software using features or extensions that automatically provide a protection mechanism that mitigates or eliminates buffer overflows.
|
||||
|
||||
\section{Software Tests}
|
||||
% TODO: describe that tests are mostly semantics as opposed to static checks being mostly syntactical and technical
|
||||
% TODO: Are they necessary in addition to static checks to cover the well-known use-cases and edge-cases.
|
||||
% TODO: example?
|
||||
Examples: FORTIFY\_SOURCE GCC flag, StackGuard
|
||||
}
|
||||
\item{Implementation -
|
||||
|
||||
\section{The Effects Of Programming Languages on Memory-Safety}
|
||||
There are dozens of \glspl{proglang} used by humans to write \glspl{app}, but only a few are used to write \glspl{os}.
|
||||
\cref{context::safe-os-dev::detecting-safety-violations-asap} explained that programming languages have direct impact on the memory-safety.
|
||||
This section gives an example of how severe this impact is and explains the requirements on a \gls{os} language.
|
||||
Careful Buffer Handling:
|
||||
\begin{itemize}
|
||||
\item Double check that your buffer is as large as you specify.
|
||||
\item When using functions that accept a number of bytes to copy, such as strncpy(), be aware that if the destination buffer size is equal to the source buffer size, it may not NULL-terminate the string.
|
||||
\item Check buffer boundaries if accessing the buffer in a loop and make sure you are not in danger of writing past the allocated space.
|
||||
\item If necessary, truncate all input strings to a reasonable length before passing them to the copy and concatenation functions.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Abstraction Tradeoffs: Safety vs. Functionality}
|
||||
\label{context::introduction::memory-safety::abstr-safety-function}
|
||||
Use Functions That Support Bounds:
|
||||
\begin{itemize}
|
||||
\item Replace unbounded copy functions with analogous functions that support length arguments, such as strcpy with strncpy.
|
||||
\item Create these if they are not available.
|
||||
\end{itemize}
|
||||
}
|
||||
\item{Operation - Address Randomization
|
||||
|
||||
Run or compile the software using features or extensions that randomly arrange the positions of a program's executable and libraries in memory. Because this makes the addresses unpredictable, it can prevent an attacker from reliably jumping to exploitable code.
|
||||
|
||||
Examples: Address Space Layout Randomization (ASLR), Position-Independent Executables (PIE)
|
||||
}
|
||||
\end{itemize}
|
||||
|
||||
\chapter{OS Development: Choice of Programming Language}
|
||||
\label{context::os-dev-lang-choice}
|
||||
There are dozens of \glspl{proglang} to write \glspl{app}, but only a few are viable for writing \glspl{os}.
|
||||
|
||||
\section{Abstraction Trade Offs: Safety vs. Functionality}
|
||||
\label{context::os-dev-lang-choice::abstraction-safety-functionality}
|
||||
In computer systems, safety and functionality are counter-proportional towards each other, because with increased functionality also grows complexity, and error cases become more difficult to find.
|
||||
Applying this analogy to software development, during which the errors are created in the first place, might be misleading.
|
||||
Applying this analogy to \glspl{proglang} might be misleading at first.
|
||||
It might seem that the more abstraction is provided by a language, the higher the available functionality is.
|
||||
In fact, the opposite is the case.
|
||||
Abstraction can be used to impose limits on what the programmer can instruct the system to do.
|
||||
By defining an abstraction layer in form of a programming language, the language defines which of the underlying functionality will be exposed through it.
|
||||
, the language can introduce obligated rules that make the written program easier to analyze in an automated fashion, before it gets compiled into the underlying representation.
|
||||
|
||||
\section{Safety In Language Compilers And Static Analyzers}
|
||||
Abstraction can be used to impose limits on what the programmer can instruct the system to do, which can reduce functionality and increase safety.
|
||||
By defining an abstraction layer in form of a \gls{proglang}, the language defines which of the underlying functionality will be exposed through it.
|
||||
The \gls{proglang} can be designed with obligated rules, that make the written source code easier to analyze in an automated fashion before it gets compiled to the underlying representation.
|
||||
|
||||
\chapter{Mitigation Attempts}
|
||||
\section{Improving \glsentrytext{C}}
|
||||
\section{Requirements}
|
||||
\label{context::os-dev-lang-choice::requirements}
|
||||
Criteria for the choice of \gls{proglang} are much different for an \gls{os} than for other types of \glspl{app}
|
||||
The following are requirements can be identified
|
||||
|
||||
\begin{itemize}
|
||||
\item{TODO: see CWE suggestions}
|
||||
\end{itemize}
|
||||
|
||||
\section{Why not \glsentrytext{C}?}
|
||||
With the growing number of vulnerabilities, various solutions have been proposed to increase the safety of C, either with static code analysis or via \gls{compiler}-generated checks imposed at runtime. (TODO: reference).
|
||||
|
||||
Static analysis are not very effective on a language that has not been designed to be safety-analyzed. TODO? reference?
|
||||
|
@ -1309,78 +1395,32 @@ For this reason there have been attempts to define subsets of the \gls{C} langua
|
|||
Safety checks that are performed at runtime introduce a high degree of overhead, which makes it a nonviable option in the domain of \gls{os} development, where many code paths must be very fast to ensure the operation of high speed I/O devices\cite{Balasubramanian2017} or tasks with \gls{realtime} requirements. (TODO: explain realtime requirements)
|
||||
This has been forcing \gls{os} developers to prioritize performance over safety. (TODO: reference)
|
||||
|
||||
Details about the challenge of writing code that does memory management safely, and related vulnerabilities are given further along in \cref{context::common-mem-safety-mistakes}.
|
||||
|
||||
\section{Choice of Programming Language}
|
||||
Criteria for the choice of programming language are much different from choosing a language for other types of \glspl{app}.
|
||||
|
||||
This is a list of what is required for implementing an \glspl{os}
|
||||
|
||||
\begin{itemize}
|
||||
\item{Raw access to \gls{cpu} instructions}
|
||||
\item{Deterministic temporal behavior}
|
||||
\end{itemize}
|
||||
|
||||
% TODO: put in some scientific background about static checks
|
||||
% * affine types
|
||||
|
||||
\chapter{Memory-Safety Analysis Techniques}
|
||||
As per the previous \cref{context::common-mem-safety-mistakes} there is general awareness of the problems, and there has been ongoing effort to develop and improve techniques that assist the programmer to detect and avoid such mistakes first- or secondhand.
|
||||
|
||||
\section{Static vs. Dynamic Analysis}
|
||||
% TODO: explain first-/secondhand -> static/dynamic -> compile-time/runtime -> offline/online
|
||||
% TODO: Explain static and dynamic checks
|
||||
|
||||
|
||||
\section{Requirements}
|
||||
* TODO: which knowledge is required to analyze access to memory?
|
||||
|
||||
\section{Limitations}
|
||||
* TODO: deadlock example
|
||||
|
||||
\chapter{Introduction To Rust}
|
||||
\label{context::rust}
|
||||
Described by the maintainers, it is a "systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.", (www.rust-lang.org)
|
||||
|
||||
\section{Compiler Architecture}
|
||||
- TODO: Tokens? AST? LLVM? (http://embed.rs/articles/2016/arm-inline-assembly-rust/)
|
||||
- TODO: BSYS SS17 GITHUB IO Rust Memory Layout - 4
|
||||
|
||||
\subsection{Static Analyser}
|
||||
%TODO: mention electrolyte, formal verification for Rust
|
||||
|
||||
\section{Language Features}
|
||||
- TODO: How does static typing help with preventing programming errors
|
||||
- TODO: How does the Rust's static analysis work, theoretically and practically
|
||||
- TODO: How can memory be dynamically allocated and still safety checked?
|
||||
|
||||
\subsection{Ownership And Borrows}
|
||||
- TODO: Who owns global 'static variables?
|
||||
|
||||
|
||||
\subsection{Lifetimes}
|
||||
- TODO: Where are global 'static variables allocated?
|
||||
|
||||
\subsection{Type Safety}
|
||||
- TODO: how does casting work?
|
||||
- TODO: demonstrate raw pointers
|
||||
- TODO: what's the equivalent of void*?
|
||||
|
||||
\subsection{Inner- and Outer Mutability}
|
||||
- TODO: describe Rc, Arc, and {Ref,}Cell
|
||||
|
||||
- https://nercury.github.io/rust/guide/2015/01/19/ownership.html
|
||||
|
||||
\subsection{Zero-Cost Abstraction}
|
||||
|
||||
\section{Language Extension}
|
||||
\subsection{Syntax Extension}
|
||||
\subsubsection{Macros}
|
||||
\subsubsection{Annotations}
|
||||
\subsection{Compiler Plugins}
|
||||
|
||||
\section{Idioms And Patterns}
|
||||
|
||||
\subsection{The Newtype Pattern}
|
||||
https://aturon.github.io/features/types/newtype.html
|
||||
\begin{markdown}
|
||||
# Flow of Reasoning
|
||||
* How to mitigate distributed weaknesses
|
||||
- Don't distribute vulnerable software
|
||||
- Produce less vulnerabilities
|
||||
OR
|
||||
- Detect vulnerabilities
|
||||
* How to prevent vulnerabilities distribution?
|
||||
- Human to make less mistakes; NOT VIABLE, see human aspect.
|
||||
- Detect them before the \gls{app} is installed; see time aspect
|
||||
* How to detect vulnerabilities
|
||||
- Write runtime tests for the program
|
||||
- Analyze the source code
|
||||
* Runtime Tests
|
||||
- Runs on every execution, thus wastes \gls{cpu} resources
|
||||
- Program needs to handle it
|
||||
-> Slow and too late in the software life cycle!
|
||||
* Source Code Analysis
|
||||
- Difficult for low-level code, would require hardware knowledge
|
||||
- Compilers are source code analysers by nature
|
||||
- Additional tools can help, but this takes more effort
|
||||
-> chose a compiler with high analysis standards
|
||||
* Choice of Compiler: Language Dependent
|
||||
- C: Safe C, Cyclone, etc.: define sub language that is analyzable. MEH
|
||||
- Rust: designed to be analyzable. WIN!
|
||||
* Rust
|
||||
- Can the analyzes be extended to suite OS dev?
|
||||
\end{markdown}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
% TLB needs to be reset on Task Change
|
||||
% ISR-Stack-Frame needs to be updated on context-switch
|
||||
|
||||
|
||||
\section{Software Fault Isolation}
|
||||
% TODO: content from \cite{Balasubramanian2017}
|
||||
|
||||
|
@ -19,20 +18,138 @@
|
|||
% TODO * Tasks can't access unallocated (physical) memory
|
||||
% TODO * Tasks can't access other tasks memory
|
||||
|
||||
\chapter{An Introduction To Rust}
|
||||
\label{context::rust}
|
||||
Described by the maintainers, it is a "systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.", (www.rust-lang.org)
|
||||
|
||||
\chapter{Porting \glsentrytext{C} Vulnerabilities}
|
||||
\label{rnd::porting-c-vulns}
|
||||
In this chapter, the weakness manifestations given in \cref{context::common-mem-safety-mistakes::manifestations} are rewritten in \gls{Rust} to examine if these are mitigated just by porting them.
|
||||
\section{Compiler Architecture}
|
||||
- TODO: Tokens? AST? LLVM? (http://embed.rs/articles/2016/arm-inline-assembly-rust/)
|
||||
|
||||
- TODO: BSYS SS17 GITHUB IO Rust Memory Layout - 4
|
||||
|
||||
\subsection{Static Analyser}
|
||||
- TODO: mention electrolyte, formal verification for Rust
|
||||
|
||||
\section{Language Features}
|
||||
- TODO: How does static typing help with preventing programming errors
|
||||
|
||||
- TODO: How does the Rust's static analysis work, theoretically and practically
|
||||
|
||||
- TODO: How can memory be dynamically allocated and still safety checked?
|
||||
|
||||
\subsection{Ownership And Borrows}
|
||||
- TODO: Who owns global 'static variables?
|
||||
|
||||
|
||||
\subsection{Lifetimes}
|
||||
- TODO: Where are global 'static variables allocated?
|
||||
|
||||
\subsection{Type Safety}
|
||||
- TODO: demonstrate casts
|
||||
|
||||
- TODO: demonstrate raw pointers
|
||||
|
||||
- TODO: discuss the equivalents of void*?
|
||||
|
||||
\subsection{Inner- and Outer Mutability}
|
||||
- TODO: describe Rc, Arc, and {Ref,}Cell
|
||||
|
||||
- https://nercury.github.io/rust/guide/2015/01/19/ownership.html
|
||||
|
||||
\subsection{Zero-Cost Abstraction}
|
||||
\section{Language Extension}
|
||||
\subsection{Syntax Extension}
|
||||
\subsubsection{Macros}
|
||||
\subsubsection{Annotations}
|
||||
\subsection{Compiler Plugins}
|
||||
|
||||
\section{Idioms And Patterns}
|
||||
|
||||
\subsection{The Newtype Pattern}
|
||||
https://aturon.github.io/features/types/newtype.html
|
||||
|
||||
\section{Limitations}
|
||||
* TODO: deadlock example
|
||||
* TODO: cyclic reference memory leak example
|
||||
|
||||
\chapter{Weakness Mitigation Evaluation}
|
||||
\label{rnd::weakness-mitig-eval}
|
||||
|
||||
\section{CWE Mitigation Suggestions Evaluation}
|
||||
\label{rnd::weakness-mitig-eval::cwe-mitig-suggestion-eval}
|
||||
|
||||
\section{Porting \glsentrytext{C} Vulnerabilities}
|
||||
\label{rnd::weakness-mitig-eval::porting-c-vulns}
|
||||
|
||||
In this chapter, the weakness manifestations given in \cref{context::weaknesses-mem-safety::manifestations} are rewritten in \gls{Rust} to examine if these are mitigated just by porting them.
|
||||
This is done incrementally by first porting the vulnerability to unsafe Rust, followed by a rewrite to drop all unsafe code but keeping the intended functionality.
|
||||
% TODO official CWE-119 examples
|
||||
|
||||
\section{Stack Protection}
|
||||
\label{rnd::weakness-mitig-eval::stack-protection}
|
||||
The goal of this chapter is to learn about \gls{Rust}'s stack protection mechanisms.
|
||||
|
||||
\subsection{Return Address Manipulation Experiments}
|
||||
\label{rnd::weakness-mitig-eval::stack-protection::ret-addr-experiments}
|
||||
The following manifestations are minimal constructions, supposedly to easy to understand.
|
||||
They should allow to get a grasp of what vulnerabilities might look like, and at the same time display weaknesses of the \gls{C} language.
|
||||
|
||||
\Cref{code::context::examples::sf-modification-simple} is a little example program in \gls{C}, which manipulates the return function address stored on the \gls{stack}.
|
||||
This is done by simple and legal pointer arithmetic.
|
||||
It abuses the address of the first local variable to create references into the \gls{sf} below on the \gls{stack}.
|
||||
Since the first variable is in the beginning of the \gls{sf} of the called function, it can be used to guess the position of the return address on the \gls{stack}.
|
||||
Depending on the \gls{compiler} settings, the return address is stored either one or two stack entries in front of the first local variable for a function with no arguments.
|
||||
In a brute-force manner the program simply overwrites both entries with the address of \code{simple_printer}.
|
||||
By writing a different function address at these entries, the \code{ret} instruction will jump there, since the original return address has been overwritten.
|
||||
|
||||
\begin{figure}[ht!]
|
||||
\begin{subfigure}[T]{0.60\textwidth}
|
||||
\centering
|
||||
\begin{minted}[linenos,breaklines]{c}
|
||||
void modifier(void) {
|
||||
uint64_t *p;
|
||||
*(&p + 1) =
|
||||
(uint64_t *)simple_printer;
|
||||
*(&p + 2) =
|
||||
(uint64_t *)simple_printer;
|
||||
}
|
||||
\end{minted}
|
||||
\subcaption{C code}
|
||||
\end{subfigure}
|
||||
\begin{subfigure}[T]{0.39\textwidth}
|
||||
\centering
|
||||
\begin{minted}[linenos,breaklines]{objdump}
|
||||
movabs rax,0x400690
|
||||
mov QWORD PTR [rsp],rax
|
||||
mov QWORD PTR [rsp+0x8],rax
|
||||
ret
|
||||
\end{minted}
|
||||
\subcaption{ASM code}
|
||||
\end{subfigure}
|
||||
\caption{Stack-Frame Modification in C}
|
||||
\label{code::context::examples::sf-modification-simple}
|
||||
\end{figure}
|
||||
|
||||
\Cref{TODO-callstack-manipulation} is an attempt to visualize what happens in memory and with the \gls{stack} and the \gls{cpu}'s RIP {64-Bit Instruction Pointer} register.
|
||||
|
||||
\begin{figure}
|
||||
\includegraphics[width=\textwidth]{gfx/TODO-callstack-manipulation}
|
||||
\caption{TODO-callstack-manipulation}
|
||||
\label{TODO-callstack-manipulation}
|
||||
\end{figure}
|
||||
\FloatBarrier
|
||||
|
||||
\subsection{Rust and the Stack Clash}
|
||||
\label{rnd::weakness-mitig-eval::stack-protection::rust-stack-clash}
|
||||
This subsection determines if \gls{Rust} can solve the issue described in \cpnameref{context::weaknesses-mem-safety::manifestations::stack-clash} from userspace and \gls{os} perspectives.
|
||||
|
||||
% TODO https://github.com/rust-lang/rust/issues/16012
|
||||
|
||||
\chapter{\glsentrytext{LX} Modules Written In \glsentrytext{Rust}}
|
||||
The numerous \gls{LX} vulnerabilities are a great motivator for using \gls{Rust} for \gls{LX} drivers.
|
||||
This chapter presents the attempt to use \gls{Rust} for a simple buffer that is presented to userspace as a character device.
|
||||
|
||||
\chapter{Stack Protection}
|
||||
The goal of this chapter is to learn about \gls{Rust}'s stack protection mechanisms, and determine if it can help with the issue described in \cnameref{context::common-mem-safety-mistakes::manifestations::stack-clash}.
|
||||
|
||||
% TODO stack frame manipulation example
|
||||
|
||||
- TODO: explain the difficulty to use the Kernel's C Macros, which are required to expose a character device
|
||||
|
||||
\chapter{Existing \glsentrytext{os}-Development Projects Based On Rust}
|
||||
\label{rnd::existing-os-dev-with-rust}
|
||||
|
|
|
@ -3,11 +3,14 @@ Any changes to this file will be lost if it is regenerated by Mendeley.
|
|||
|
||||
BibTeX export options can be customized via Options -> BibTeX in Mendeley Desktop
|
||||
|
||||
@misc{TheStackClash,
|
||||
author = {Advisory, Qualys Security},
|
||||
file = {:home/steveej/src/steveej/msc-thesis/docs/stack-clash.txt:txt},
|
||||
title = {{The Stack Clash}},
|
||||
url = {https://www.qualys.com/2017/06/19/stack-clash/stack-clash.txt}
|
||||
@article{GCC540,
|
||||
abstract = {This manual documents how to use the GNU compilers, as well as their features and incom- patibilities, and how to report bugs. It corresponds to the compilers (GCC) version 5.4.0. The internals of the GNU compilers, including how to port them to new targets and some information about how to write front ends for new languages, are documented in a separate manual. See Section Introduction in GNU Compiler Collection (GCC) Internals.},
|
||||
author = {Stallman, Richard M},
|
||||
file = {:home/steveej/src/steveej/msc-thesis/docs/gcc-5.4.0.pdf:pdf},
|
||||
isbn = {188211437X},
|
||||
journal = {Development},
|
||||
title = {{Using the GNU Compiler Collection}},
|
||||
url = {https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc.pdf}
|
||||
}
|
||||
@article{Lattner2005,
|
||||
abstract = {The LLVM Compiler Infrastructure (http://llvm.cs. uiuc.edu) is a$\backslash$nrobust system that is well suited for a wide variety of research$\backslash$nand development work. This brief paper introduces the LLVM system$\backslash$nand provides pointers to more extensive documentation, complementing$\backslash$nthe tutorial presented at LCPC.},
|
||||
|
@ -182,6 +185,12 @@ title = {{Code-pointer integrity}},
|
|||
url = {https://www.usenix.org/conference/osdi14/technical-sessions/presentation/kuznetsov{\%}5Cnhttps://www.usenix.org/system/files/conference/osdi14/osdi14-paper-kuznetsov.pdf?utm{\_}source=dlvr.it{\&}utm{\_}medium=tumblr},
|
||||
year = {2014}
|
||||
}
|
||||
@misc{TheStackClash,
|
||||
author = {Advisory, Qualys Security},
|
||||
file = {:home/steveej/src/steveej/msc-thesis/docs/stack-clash.txt:txt},
|
||||
title = {{The Stack Clash}},
|
||||
url = {https://www.qualys.com/2017/06/19/stack-clash/stack-clash.txt}
|
||||
}
|
||||
@article{Caballero2012,
|
||||
abstract = {Use-after-free vulnerabilities are rapidly growing in popularity, especially for exploiting web browsers. Use-after-free (and double-free) vulnerabilities are caused by a program operating on a dangling pointer. In this work we propose early detection, a novel runtime approach for finding and diagnosing use-after-free and double-free vulnerabilities. While previous work focuses on the creation of the vulnerability (i.e., the use of a dangling pointer), early detection shifts the focus to the creation of the dangling pointer(s) at the root of the vulnerability. Early detection increases the effectiveness of testing by identifying unsafe dangling pointers in executions where they are created but not used. It also accelerates vulnerability analysis and minimizes the risk of incomplete fixes, by automatically collecting information about all dangling pointers involved in the vulnerability. We implement our early detection technique in a tool called Undangle. We evaluate Undangle for vulnerability analysis on 8 real-world vulnerabilities. The analysis uncovers that two separate vulnerabilities in Firefox had a common root cause and that their patches did not completely fix the underlying bug. We also evaluate Undangle for testing on the Firefox web browser identifying a potential vulnerability.},
|
||||
author = {Caballero, Juan and Grieco, Gustavo and Marron, Mark and Nappa, Antonio},
|
||||
|
|
|
@ -43,8 +43,14 @@
|
|||
\usetikzlibrary{chains,shapes.arrows, arrows, positioning,decorations.pathreplacing,bending}
|
||||
\usetikzlibrary{calc}
|
||||
\usetikzlibrary{matrix,shapes,arrows,positioning}
|
||||
\usetikzlibrary{shapes.geometric, arrows}
|
||||
\usetikzlibrary{chains,arrows.meta,decorations.pathmorphing,quotes}
|
||||
\usepackage{smartdiagram}
|
||||
\usesmartdiagramlibrary{additions}
|
||||
\usepackage{color}
|
||||
\usepackage[definitionLists,hashEnumerators,smartEllipses,hybrid]{markdown}
|
||||
%\usepackage[fencedCode,inlineFootnotes,citations,definitionLists,hashEnumerators,smartEllipses,hybrid]{markdown}
|
||||
|
||||
|
||||
\tikzset{/minted/basename/.initial=minted}
|
||||
\appto\theFancyVerbLine{\tikzmark{\pgfkeysvalueof{/minted/basename}\arabic{FancyVerbLine}}}
|
||||
|
@ -128,6 +134,9 @@
|
|||
\newcommand{\cnameref}[1]{\cref{#1} \textit{(\nameref{#1})}}
|
||||
\newcommand{\Cnameref}[1]{\Cref{#1} \textit{(\nameref{#1})}}
|
||||
|
||||
\newcommand{\cpnameref}[1]{\cref{#1} \textit{(\nameref{#1}, \cpageref{#1})}}
|
||||
\newcommand{\Cpnameref}[1]{\Cref{#1} \textit{(\nameref{#1}, \cpageref{#1})}}
|
||||
|
||||
\newcommand{\cnamepref}[1]{\cref{#1} \textit{(\nameref{#1}, \cpageref{#1})}}
|
||||
\newcommand{\Cnamepref}[1]{\Cref{#1} \textit{(\nameref{#1}, \cpageref{#1})}}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue