more
This commit is contained in:
@@ -1,23 +1,101 @@
|
||||
\subsection{Full Korg Soundness and Completeness Proofs}%
|
||||
\label{sub:korg_proofs}
|
||||
|
||||
\begin{definition}[\ba]
|
||||
A \ba is a tuple \( B = (Q, \Sigma, \delta, Q_0, F) \) where:
|
||||
\begin{itemize}
|
||||
\item \( Q \) is a finite set of states,
|
||||
\item \( \Sigma \) is a finite alphabet,
|
||||
\item \( \delta \subseteq Q \times \Sigma \times Q \) is a transition relation,
|
||||
\item \( Q_0 \subseteq Q \) is a set of initial states,
|
||||
\item \( F \subseteq Q \) is a set of accepting states.
|
||||
\end{itemize}
|
||||
A run of a \ba is an infinite sequence of states \( q_0, q_1, q_2, \ldots \) such that \( q_0 \in Q_0 \) and \( (q_i, a, q_{i+1}) \in \delta \) for some \( a \in \Sigma \) at each step \( i \). The run is considered accepting if it visits states in \( F \) infinitely often.
|
||||
\end{definition}
|
||||
|
||||
\begin{definition}[Process]
|
||||
A \emph{Process} is a tuple \( P = \langle AP, I, O, S, s_0, T, L \rangle \), where:
|
||||
\begin{itemize}
|
||||
\item \( AP \) is a finite set of atomic propositions,
|
||||
\item \( I \) is a set of inputs,
|
||||
\item \( O \) is a set of output, such that \( I \cap O = \emptyset \),
|
||||
\item \( S \) is a finite set of states,
|
||||
\item \( s_0 \in S \) is the initial state,
|
||||
\item \( T \subseteq S \times (I \cup O) \times S \) is the transition relation,
|
||||
\item \( L: S \to 2^{AP} \) is a labeling function mapping each state to a subset of atomic propositions.
|
||||
\end{itemize}
|
||||
A transition \( (s, x, s') \in T \) is called an \emph{input transition} if \( x \in I \) and an \emph{output transition} if \( x \in O \).
|
||||
\end{definition}
|
||||
|
||||
\setcounter{theorem}{0}
|
||||
\begin{theorem}
|
||||
A process, as defined in Hippel et al., always directly corresponds to a Büchi automata.
|
||||
A process, as defined in Hippel et al., always directly corresponds to a \ba.
|
||||
\end{theorem}
|
||||
|
||||
\begin{proof}
|
||||
\jg{highly standard equivalence argument}
|
||||
|
||||
Given a \ba \( B = (Q, \Sigma, \delta, Q_0, F) \), we construct a corresponding Process \( P = \langle AP, I, O, S, s_0, T, L \rangle \) as follows:
|
||||
|
||||
\begin{itemize}
|
||||
\item {Atomic Propositions: \( AP = \{ \text{accept} \} \), a singleton set containing a special proposition indicating acceptance.
|
||||
\item Inputs and Outputs: \( I = \Sigma \) and \( O = \emptyset \).
|
||||
\item States: \( S = Q \) and \( s_0 \in Q_0 \).
|
||||
\item Transition Relation: \( T = \delta \).
|
||||
\item Labeling Function: \( L: S \to 2^{AP} \) defined by
|
||||
\[ L(s) = \begin{cases} \{ \text{accept} \} & \text{if } s \in F, \\ \emptyset & \text{otherwise}. \end{cases} \]
|
||||
\end{itemize}
|
||||
|
||||
In this mapping, the states and transitions of the BA are preserved in the Process, and the accepting states \( F \) are identified via the labeling function \( L \).
|
||||
|
||||
Conversely, given a Process \( P = \langle AP, I, O, S, s_0, T, L \rangle \) with an acceptance condition defined by a distinguished proposition \( p \in AP \), we define a \ba \( B = (Q, \Sigma, \delta, Q_0, F) \) as follows:
|
||||
|
||||
\begin{itemize}
|
||||
\item States: \( Q = S \) and \( Q_0 = \{ s_0 \} \).
|
||||
\item Alphabet: \( \Sigma = I \cup O \).
|
||||
\item Transition Relation: \( \delta = T \).
|
||||
\item Accepting States: \( F = \{ s \in S \mid p \in L(s) \} \).
|
||||
\end{itemize}
|
||||
|
||||
Here, the accepting states in the BA correspond to those states in the Process that are labeled with the distinguished proposition \( p \).
|
||||
|
||||
In both structures, a run is an infinite sequence of states connected by transitions:
|
||||
|
||||
\begin{itemize}
|
||||
\item In the \ba: \( q_0, q_1, q_2, \ldots \) with \( q_0 \in Q_0 \) and \( (q_i, a_i, q_{i+1}) \in \delta \) for some \( a_i \in \Sigma \).
|
||||
\item In the Process: \( s_0, s_1, s_2, \ldots \) with \( s_0 = s_0 \) and \( (s_i, x_i, s_{i+1}) \in T \) for some \( x_i \in I \cup O \).
|
||||
\end{itemize}
|
||||
|
||||
An accepting run in the \ba visits states in \( F \) infinitely often. Similarly, an accepting run in the Process visits states labeled with \( p \) infinitely often. Since \( F = \{ s \in S \mid p \in L(s) \} \), the acceptance conditions are preserved under the mappings.
|
||||
|
||||
\end{proof}
|
||||
|
||||
\begin{definition}[Threat Model]
|
||||
A threat model is a tuple \( (P, (Q_i)_{i=0}^m, \phi) \) where:
|
||||
\begin{itemize}
|
||||
\item \( P, Q_0, \ldots, Q_m \) are processes.
|
||||
\item Each process \( Q_i \) has no atomic propositions (i.e., its set of atomic propositions is empty).
|
||||
\item \( \varphi \) is an LTL formula such that \( P \parallel Q_0 \parallel \cdots \parallel Q_m \models \phi \).
|
||||
\item The system \( P \parallel Q_0 \parallel \cdots \parallel Q_m \) satisfies the formula \( \phi \) in a non-trivial manner, meaning that \( P \parallel Q_0 \parallel \cdots \parallel Q_m \) has at least one infinite run.
|
||||
\end{itemize}
|
||||
\end{definition}
|
||||
|
||||
\begin{theorem}
|
||||
Checking whether there exists an attacker under a given threat model, the R-$\exists$ASP problem as proposed in Hippel et al., is equivalent to B\"uchi Automata language inclusion (which is in turn solved by the \spin model checker).
|
||||
\end{theorem}
|
||||
|
||||
\begin{proof}
|
||||
\jg{arguing the equivalence of buchi automata intersection and process composition}
|
||||
|
||||
For a given threat model \( (P, (Q_i)_{i=0}^m, \phi) \), checking $\exists ASP$ is equivalent to checking
|
||||
\[
|
||||
R = MC(P \mid \mid \text{Daisy}(Q_0) \mid \mid \ldots \mid \mid \text{Daisy}(Q_m), \phi)
|
||||
\]
|
||||
Where $MC$ is a model checker, and Daisy($Q_i$) is for intents of this proof, equivalent to a process. Therefore, via the previous theorem we can construct \ba \( BA_{P}, BA_{\text{Daisy}(Q_0)}, \ldots, BA_{\text{Daisy}(Q_m)} \) from the processes \( P, \text{Daisy}(Q_0), \ldots ,\text{Daisy}(Q_m) \). Then, we check
|
||||
\[
|
||||
\text{\spin}(BA_{P} \mid \mid BA_{\text{Daisy}(Q_0)} \mid \mid \ldots \mid \mid BA_{\text{Daisy}(Q_m)}, \phi)
|
||||
\]
|
||||
Or equivalently, translating $\phi$ to the equivalent \ba $BA_{\phi}$ via \cite{Holzmann_1997}, we equivalently check
|
||||
\[
|
||||
\left(BA_{P} \mid \mid BA_{\text{Daisy}(Q_0)} \mid \mid \ldots \mid \mid BA_{\text{Daisy}(Q_m)}\right) \subseteq BA_{\phi}
|
||||
\]
|
||||
\end{proof}
|
||||
|
||||
\begin{theorem}
|
||||
@@ -25,8 +103,7 @@ Checking whether there exists an attacker for a given threat model, the R-$\exis
|
||||
\end{theorem}
|
||||
|
||||
\begin{proof}
|
||||
\jg{cite lower bounds for natural proof systems}
|
||||
|
||||
By the previous argument the $\exists$ASP problem corresponds to \ba language inclusion, which is well-known to be PSPACE-complete \cite{Kozen_1977}.
|
||||
\end{proof}
|
||||
|
||||
\subsection{Preventing Korg Livelocks}%
|
||||
@@ -74,3 +151,157 @@ BREAK:
|
||||
\end{figure}
|
||||
|
||||
|
||||
\subsection{Attacker Model Gadget Examples}%
|
||||
\label{sub:Attacker Model Gadget Examples}
|
||||
|
||||
\begin{figure}[h]
|
||||
\begin{lstlisting}[caption={Example dropping attacker model gadget with drop limit of 3, targetting channel "cn"}, label={lst:korg_drop}]
|
||||
chan cn = [8] of { int, int, int };
|
||||
|
||||
active proctype attacker_drop() {
|
||||
int b_0, b_1, b_2;
|
||||
byte lim = 3; // drop limit
|
||||
MAIN:
|
||||
do
|
||||
:: cn ? [b_0, b_1, b_2] -> atomic {
|
||||
if
|
||||
:: lim == 0 -> goto BREAK;
|
||||
:: else ->
|
||||
cn ? b_0, b_1, b_2; // consume message on the channel
|
||||
lim = lim - 1;
|
||||
goto MAIN;
|
||||
fi
|
||||
}
|
||||
od
|
||||
BREAK:
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h]
|
||||
\begin{lstlisting}[caption={Example replay attacker model gadget with the selected replay limit as 3, targetting channel "cn"}, label={lst:korg_replay}]
|
||||
chan cn = [8] of { int, int, int };
|
||||
|
||||
// local memory for the gadget
|
||||
chan gadget_mem = [3] of { int, int, int };
|
||||
|
||||
active proctype attacker_replay() {
|
||||
int b_0, b_1, b_2;
|
||||
int i = 3;
|
||||
CONSUME:
|
||||
do
|
||||
// read messages until the limit is passed
|
||||
:: cn ? [b_0, b_1, b_2] -> atomic {
|
||||
cn ? <b_0, b_1, b_2> -> gadget_mem ! b_0, b_1, b_2;
|
||||
i--;
|
||||
if
|
||||
:: i == 0 -> goto REPLAY;
|
||||
:: i != 0 -> goto CONSUME;
|
||||
fi
|
||||
}
|
||||
od
|
||||
REPLAY:
|
||||
do
|
||||
:: atomic {
|
||||
// nondeterministically select a random value from the storage buffer
|
||||
int am;
|
||||
select(am : 0 .. len(gadget_mem)-1);
|
||||
do
|
||||
:: am != 0 ->
|
||||
am = am-1;
|
||||
gadget_mem ? b_0, b_1, b_2 -> gadget_mem ! b_0, b_1, b_2;
|
||||
:: am == 0 ->
|
||||
gadget_mem ? b_0, b_1, b_2 -> cn ! b_0, b_1, b_2;
|
||||
break;
|
||||
od
|
||||
}
|
||||
// doesn't need to use all messages on the channel
|
||||
:: atomic {gadget_mem ? b_0, b_1, b_2; }
|
||||
// once mem has no more messages, we're done
|
||||
:: empty(gadget_mem) -> goto BREAK;
|
||||
od
|
||||
BREAK:
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h]
|
||||
\begin{lstlisting}[caption={Example reordering attacker model gadget with the selected replay limit as 3, targetting channel "cn"}, label={lst:korg_reordering}]
|
||||
chan cn = [8] of { int, int, int };
|
||||
|
||||
chan gadget_mem = [3] of { int, int, int };
|
||||
active proctype attacker_reordering() priority 255 {
|
||||
byte b_0, b_1, b_2, blocker;
|
||||
int i = 3;
|
||||
INIT:
|
||||
do
|
||||
// arbitrarily choose a message to start consuming on
|
||||
:: {
|
||||
blocker = len(cn);
|
||||
do
|
||||
:: b != len(c) -> goto INIT;
|
||||
od
|
||||
}
|
||||
:: goto CONSUME;
|
||||
od
|
||||
CONSUME:
|
||||
do
|
||||
// consume messages with high priority
|
||||
:: c ? [b_0] -> atomic {
|
||||
c ? b_0 -> gadget_mem ! b_0;
|
||||
i--;
|
||||
if
|
||||
:: i == 0 -> goto REPLAY;
|
||||
:: i != 0 -> goto CONSUME;
|
||||
fi
|
||||
}
|
||||
od
|
||||
REPLAY:
|
||||
do
|
||||
// replay messages back onto the channel, also with priority
|
||||
:: atomic {
|
||||
int am;
|
||||
select(am : 0 .. len(gadget_mem)-1);
|
||||
do
|
||||
:: am != 0 ->
|
||||
am = am-1;
|
||||
gadget_mem ? b_0 -> attacker_mem_0 ! b_0;
|
||||
:: am == 0 ->
|
||||
gadget_mem ? b_0 -> c ! b_0;
|
||||
break;
|
||||
od
|
||||
}
|
||||
:: atomic { empty(gadget_mem) -> goto BREAK; }
|
||||
od
|
||||
BREAK:
|
||||
}
|
||||
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h]
|
||||
\begin{lstlisting}[caption={Example I/O file targetting channel "cn"}, label={lst:io-file}]
|
||||
cn:
|
||||
I:
|
||||
O:1-1-1, 1-2-3, 3-4-5
|
||||
\end{lstlisting}
|
||||
|
||||
\begin{lstlisting}[caption={Example gadget synthesized from an I/O file targetting the channel "cn"}, label={lst:io-file-synth}]
|
||||
chan cn = [8] of { int, int, int };
|
||||
|
||||
active proctype daisy() {
|
||||
INIT:
|
||||
do
|
||||
:: cn ! 1,1,1;
|
||||
:: cn ! 1,2,3;
|
||||
:: cn ! 3,4,5;
|
||||
:: goto RECOVERY;
|
||||
od
|
||||
RECOVERY:
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
\korg supports three general attacker models: an attacker that can drop, replay, or rearrange messages on a channel. Additionally, \korg supports user-defined attacker that insert arbitrary messages onto a channel. In this section we discuss the various details that go into each attacker model.
|
||||
\korg supports three general attacker models: an attacker that can drop, replay, or reordering messages on a channel. Additionally, \korg supports user-defined attacker that insert arbitrary messages onto a channel. In this section we discuss the various details that go into each attacker model.
|
||||
|
||||
\subsection{Dropping Attacker Model}%
|
||||
\label{sub:Dropping Attacker}
|
||||
@@ -7,29 +7,7 @@ The first and most simple general attacker model \korg supports is an attacker t
|
||||
|
||||
The dropper attacker model gadget \korg synthesizes works as follows. The gadget will nondeterministically choose to observe a message on a channel. Then, if the drop limit variable is not zero, it will consume the message. An example is shown in Figure \ref{lst:korg_drop}.
|
||||
|
||||
\begin{figure}[h]
|
||||
\begin{lstlisting}[caption={Example dropping attacker model gadget with drop limit of 3, targetting channel "cn"}, label={lst:korg_drop}]
|
||||
chan cn = [8] of { int, int, int };
|
||||
|
||||
active proctype attacker_drop() {
|
||||
int b_0, b_1, b_2;
|
||||
byte lim = 3; // drop limit
|
||||
MAIN:
|
||||
do
|
||||
:: cn ? [b_0, b_1, b_2] -> atomic {
|
||||
if
|
||||
:: lim == 0 -> goto BREAK;
|
||||
:: else ->
|
||||
cn ? b_0, b_1, b_2; // consume message on the channel
|
||||
lim = lim - 1;
|
||||
goto MAIN;
|
||||
fi
|
||||
}
|
||||
od
|
||||
BREAK:
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Replaying Attacker Model}%
|
||||
\label{sub:Replay Attacker}
|
||||
@@ -37,138 +15,17 @@ The second attacker model \korg supports is an attacker that can observe and \te
|
||||
|
||||
The dropper attacker model gadget \korg synthesizes works as follows. The gadget has two states, \textsc{Consume} and \textsc{Replay}. The gadget starts in the \textsc{Consume} state and nondeterministically reads (but not consumes) messages on the target channel, sending them into a local storage buffer. Once the gadget read the number of messages on the channel equivalent to the defined replay limit, its state changes to \textsc{Replay}. In the \textsc{Replay} state, the gadget nondeterministically selects messages from its storage buffer to replay onto the channel until out of messages. An example is shown in Figure \ref{lst:korg_replay}.
|
||||
|
||||
\begin{figure}[h]
|
||||
\begin{lstlisting}[caption={Example replay attacker model gadget with the selected replay limit as 3, targetting channel "cn"}, label={lst:korg_replay}]
|
||||
chan cn = [8] of { int, int, int };
|
||||
|
||||
// local memory for the gadget
|
||||
chan gadget_mem = [3] of { int, int, int };
|
||||
\subsection{Reordering Attacker Model}%
|
||||
\label{sub:reordering Attacker}
|
||||
Lastly, \korg supports an attacker model such that an attacker can \textit{reorder} messages on a channel. Like the drop and replay attacker models, the user can specify a "reordering limit" that caps the number of messages that can be reorderingd by the attacker on the specified channel.
|
||||
|
||||
active proctype attacker_replay() {
|
||||
int b_0, b_1, b_2;
|
||||
int i = 3;
|
||||
CONSUME:
|
||||
do
|
||||
// read messages until the limit is passed
|
||||
:: cn ? [b_0, b_1, b_2] -> atomic {
|
||||
cn ? <b_0, b_1, b_2> -> gadget_mem ! b_0, b_1, b_2;
|
||||
i--;
|
||||
if
|
||||
:: i == 0 -> goto REPLAY;
|
||||
:: i != 0 -> goto CONSUME;
|
||||
fi
|
||||
}
|
||||
od
|
||||
REPLAY:
|
||||
do
|
||||
:: atomic {
|
||||
// nondeterministically select a random value from the storage buffer
|
||||
int am;
|
||||
select(am : 0 .. len(gadget_mem)-1);
|
||||
do
|
||||
:: am != 0 ->
|
||||
am = am-1;
|
||||
gadget_mem ? b_0, b_1, b_2 -> gadget_mem ! b_0, b_1, b_2;
|
||||
:: am == 0 ->
|
||||
gadget_mem ? b_0, b_1, b_2 -> cn ! b_0, b_1, b_2;
|
||||
break;
|
||||
od
|
||||
}
|
||||
// doesn't need to use all messages on the channel
|
||||
:: atomic {gadget_mem ? b_0, b_1, b_2; }
|
||||
// once mem has no more messages, we're done
|
||||
:: empty(gadget_mem) -> goto BREAK;
|
||||
od
|
||||
BREAK:
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
The reordering attacker model gadget \korg synthesizes works as follows. The gadget has three states, \textsc{Init}, \textsc{Consume}, and \textsc{Replay}. The gadget begins in the \textsc{Init} state, where it arbitrarily chooses a message to start consuming by transitioning to the \textsc{Consume} state. When in the \textsc{Consume} state, the gadget consumes all messages that appear on the channel, filling up a local buffer, until hitting the defined reordering limit. Once this limit is hit, the gadget transitions into the \textsc{Replay} state. In the \textsc{Replay} state, the gadget nondeterministically selects messages from its storage buffer to replay onto the channel until out of messages. An example is shown in Figure \ref{lst:korg_reordering}.
|
||||
|
||||
\subsection{Rearranging Attacker Model}%
|
||||
\label{sub:Rearrange Attacker}
|
||||
Lastly, \korg supports an attacker model such that an attacker can \textit{rearrange} messages on a channel. Like the drop and replay attacker models, the user can specify a "rearrange limit" that caps the number of messages that can be rearranged by the attacker on the specified channel.
|
||||
|
||||
The rearrange attacker model gadget \korg synthesizes works as follows. The gadget has three states, \textsc{Init}, \textsc{Consume}, and \textsc{Replay}. The gadget begins in the \textsc{Init} state, where it arbitrarily chooses a message to start consuming by transitioning to the \textsc{Consume} state. When in the \textsc{Consume} state, the gadget consumes all messages that appear on the channel, filling up a local buffer, until hitting the defined rearrange limit. Once this limit is hit, the gadget transitions into the \textsc{Replay} state. In the \textsc{Replay} state, the gadget nondeterministically selects messages from its storage buffer to replay onto the channel until out of messages. An example is shown in Figure \ref{lst:korg_rearrange}.
|
||||
|
||||
\begin{figure}[h]
|
||||
\begin{lstlisting}[caption={Example rearrange attacker model gadget with the selected replay limit as 3, targetting channel "cn"}, label={lst:korg_rearrange}]
|
||||
chan cn = [8] of { int, int, int };
|
||||
|
||||
chan gadget_mem = [3] of { int, int, int };
|
||||
active proctype attacker_rearrange() priority 255 {
|
||||
byte b_0, b_1, b_2, blocker;
|
||||
int i = 3;
|
||||
INIT:
|
||||
do
|
||||
// arbitrarily choose a message to start consuming on
|
||||
:: {
|
||||
blocker = len(cn);
|
||||
do
|
||||
:: b != len(c) -> goto INIT;
|
||||
od
|
||||
}
|
||||
:: goto CONSUME;
|
||||
od
|
||||
CONSUME:
|
||||
do
|
||||
// consume messages with high priority
|
||||
:: c ? [b_0] -> atomic {
|
||||
c ? b_0 -> gadget_mem ! b_0;
|
||||
i--;
|
||||
if
|
||||
:: i == 0 -> goto REPLAY;
|
||||
:: i != 0 -> goto CONSUME;
|
||||
fi
|
||||
}
|
||||
od
|
||||
REPLAY:
|
||||
do
|
||||
// replay messages back onto the channel, also with priority
|
||||
:: atomic {
|
||||
int am;
|
||||
select(am : 0 .. len(gadget_mem)-1);
|
||||
do
|
||||
:: am != 0 ->
|
||||
am = am-1;
|
||||
gadget_mem ? b_0 -> attacker_mem_0 ! b_0;
|
||||
:: am == 0 ->
|
||||
gadget_mem ? b_0 -> c ! b_0;
|
||||
break;
|
||||
od
|
||||
}
|
||||
:: atomic { empty(gadget_mem) -> goto BREAK; }
|
||||
od
|
||||
BREAK:
|
||||
}
|
||||
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\subsection{Custom Attacker Models}%
|
||||
\label{sub:Custom Attacker Models}
|
||||
While the drop, replay, and rearrange attacker models as previously described have complex gadgets that \korg synthesizes with respect to a user-specified channel, \korg also supports the synthesis of gadgets with respect to user-defined inputs and outputs. The user defines an \textit{IO-file} denoting the specific input and output messages the attacker is capable of sending, and \korg generates a gadget capable of synthesizing attacks with respect to the user's specification. An example I/O file is given in Figure \ref{lst:io-file}, and the generated gadget is given in \ref{lst:io-file-synth}.
|
||||
While the drop, replay, and reordering attacker models as previously described have complex gadgets that \korg synthesizes with respect to a user-specified channel, \korg also supports the synthesis of gadgets with respect to user-defined inputs and outputs. The user defines an \textit{IO-file} denoting the specific input and output messages the attacker is capable of sending, and \korg generates a gadget capable of synthesizing attacks with respect to the user's specification. An example I/O file is given in Figure \ref{lst:io-file}, and the generated gadget is given in \ref{lst:io-file-synth}.
|
||||
|
||||
\begin{figure}[h]
|
||||
\begin{lstlisting}[caption={Example I/O file targetting channel "cn"}, label={lst:io-file}]
|
||||
cn:
|
||||
I:
|
||||
O:1-1-1, 1-2-3, 3-4-5
|
||||
\end{lstlisting}
|
||||
|
||||
\begin{lstlisting}[caption={Example gadget synthesized from an I/O file targetting the channel "cn"}, label={lst:io-file-synth}]
|
||||
chan cn = [8] of { int, int, int };
|
||||
|
||||
active proctype daisy() {
|
||||
INIT:
|
||||
do
|
||||
:: cn ! 1,1,1;
|
||||
:: cn ! 1,2,3;
|
||||
:: cn ! 3,4,5;
|
||||
:: goto RECOVERY;
|
||||
od
|
||||
RECOVERY:
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
|
||||
|
||||
@@ -1,8 +1,40 @@
|
||||
\subsection{SCTP}%
|
||||
\label{sub:SCTP}
|
||||
\subsection{Raft}%
|
||||
\label{sub:Raft}
|
||||
Raft is a consensus algorithm designed to replicate a state machine across distributed peers, and sees broad usage in distributed databases, key-value stores, distributed file systems, distributed load-balancers, and container orchestration. Historically, verification efforts of Raft using both constructive, mechanized proving techniques \cite{Woos_Wilcox_Anton_Tatlock_Ernst_Anderson_2016, Wilcox_Woos_Panchekha_Tatlock_Wang_Ernst_Anderson, Ongaro} and automated verification \cite{Ongaro} have only reasoned about the protocol under certain assumptions about the stability of the communication channels. However, no previous approach to Raft verification has reasoned about an on-channel attacker \textit{external} to the protocol itself. Uniquely, \korg enables us to study Raft under insecure communication channels.
|
||||
|
||||
\subsection{TCP}%
|
||||
\label{sub:TCP}
|
||||
|
||||
\subsection{DCCP}%
|
||||
\label{sub:DCCP}
|
||||
TCP (Transmission Control Protocol) is a transport-layer protocol designed to establish reliable, ordered communications between two peers. TCP is ubiquitous in today's internet, and therefore has seen ample formal verification efforts \cite{Cluzel_Georgiou_Moy_Zeller_2021, Smith_1997, Pacheco2022}, including using \promela and \spin \cite{Pacheco2022}. A previous version of \korg has been applied TCP in \cite{Pacheco2022, Hippel2022};
|
||||
in particular, we study our \korg extensions using the \promela models from Pacheco et al., which includes a "gold" model whose underlying state machine is derived via an NLP-based algorithm applied to the SCTP RFC \cite{rfc9260} and a "canonical" model hand-written by domain experts \cite{Pacheco2022}. Additionally, we borrow the four LTL properties used in \cite{Pacheco2022}, as detailed below:
|
||||
\[
|
||||
\begin{aligned}
|
||||
\phi_1 &= \text{\parbox[t]{20em}{No half-open connections.}} \\
|
||||
\phi_2 &= \text{\parbox[t]{20em}{Passive/active establishment eventually succeeds.}} \\
|
||||
\phi_3 &= \text{\parbox[t]{20em}{Peers don't get stuck.}} \\
|
||||
\phi_4 &= \text{\parbox[t]{20em}{\texttt{SYN\_RECEIVED} is eventually followed by \texttt{ESTABLISHED}, \texttt{FIN\_WAIT\_1}, or \texttt{CLOSED}.}}
|
||||
\end{aligned}
|
||||
\]
|
||||
|
||||
Evaluating the canonical TCP model using \korg led us to identify edge-cases in the connection establishment routine that weren't accounted for, leading us to construct a "revised" TCP model accounting for these missing edge cases. The resulting breakdown of attacks discovered is shown in Figure \ref{res:tcp-table}.
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\begin{scriptsize}
|
||||
\begin{tabular}{|@{}c@{}|@{}c@{}|@{}c@{}|@{}c@{}|@{}c@{}|@{}c@{}|@{}c@{}|@{}c@{}|@{}c@{}|@{}c@{}|}
|
||||
\hline
|
||||
& \multicolumn{3}{c|}{\footnotesize \raisebox{-0.15ex}{Drop Attacker} } & \multicolumn{3}{c|}{\footnotesize \raisebox{-0.15ex}{Replay Attacker}} & \multicolumn{3}{c|}{\footnotesize \raisebox{-0.15ex}{Reorder Attacker}} \\
|
||||
\hline
|
||||
& \: Gold \: & \: Expert \: & \: Revised \: & \: Gold \: & \: Expert \: & \: Revised \: & \: Gold \: & \: Expert \: & \: Revised \: \\
|
||||
\hline
|
||||
$\phi_1$ & \rule{0pt}{8pt} & & & & & & & & \\
|
||||
$\phi_2$ & \rule{0pt}{8pt} & x & x & & x & x & & x & \\
|
||||
$\phi_3$ & \rule{0pt}{8pt} & & & & & & & & \\
|
||||
$\phi_4$ & \rule{0pt}{8pt} x & & & & & & x & & \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{scriptsize}
|
||||
|
||||
\label{res:tcp-table}
|
||||
\caption{Automatically discovered attacks against the gold, canonical (labeled "expert"), and revised TCP models for $\phi_1$ through $\phi_4$. "x" indicates an attack was discovered, and no "x" indicates \korg proved the absence of an attack via an exhaustive search. Full attack traces are available in the artifact.}
|
||||
\end{figure}
|
||||
|
||||
@@ -6,12 +6,6 @@ In this section we discuss the details behind the design, formal guarantees, imp
|
||||
At the highest level, \korg sits on a user-defined channel in a program written in \promela, the modeling language of the \spin model checker. The user selects an attacker model of choice and correctness properties of choice. \korg then invokes the \spin, which exhaustively searches for attacks with respect to the chosen model and properties.
|
||||
A high-level overview of the \korg pipeline is given in the Figure \ref{fig:korg_workflow}.
|
||||
|
||||
%from a formal model written in \promela.
|
||||
|
||||
%user-defined (or derived) \promela models.
|
||||
|
||||
%TODO: diagram. Promela model, channel selection, gadget selection/definition get put into Korg. Korg spits out another promela model, which is put into Spin along with a property. Then, we get some attacks.
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\includegraphics[width=0.5\textwidth]{assets/diagram3.png}
|
||||
@@ -24,7 +18,6 @@ A high-level overview of the \korg pipeline is given in the Figure \ref{fig:korg
|
||||
|
||||
\newcommand{\comp}{\mid\mid}
|
||||
\newcommand{\ioint}{\mathcal{C}}
|
||||
\newcommand{\ba}{B\"uchi Automata}
|
||||
|
||||
Fundamentally, the theoretical framework that \korg implements proposed by Hippel et al. reasons about \textit{communicating processes}; similarly, \korg is best understood as a synthesizer for attackers that sit \textit{between} communicating processes.
|
||||
|
||||
@@ -82,27 +75,65 @@ Since \korg uses \spin as its underlying model checker, we can effectively concl
|
||||
|
||||
We implemented \korg on top of the \spin, a popular and robust model checker for reasoning about distributed and concurrent systems. Intuitively, models written in \promela, the modeling language of \spin, are communicating state machines whose messages are passed over defined \textit{channels}. Channels in \promela can either be unbuffered \textit{synchronous} channels, or buffered \textit{asynchronous} channels. \korg generates attacks \textit{with respect} to these defined channels.
|
||||
|
||||
\begin{figure}[h]
|
||||
\begin{lstlisting}[caption={Example \promela model of peers communicating over a channel}, label={lst:spin-model}]
|
||||
// channel of buffer size 0
|
||||
chan msg_channel = [0] of { int }
|
||||
|
||||
active proctype Peer1() {
|
||||
msg_channel ! 1
|
||||
msg_channel ! 1;
|
||||
}
|
||||
|
||||
active proctype Peer2() {
|
||||
int received_msg
|
||||
msg_channel ? received_msg
|
||||
int received_msg;
|
||||
msg_channel ? received_msg;
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
|
||||
Following the gadgetry framework as described in Hippel et al., \korg is designed to parse user-chosen channels and generate gadgets for sending, receiving, and manipulating messages on them. \korg has built-in gadgets that are designed to emulate various real-world attacker models, as further described in Section \ref{sec:usage_attacker_models}. Additionally, users can explicitly define which messages a generated gadget can send and receive. Once one or multiple gadgets are generated, \korg invokes \spin to check if a given property of interest remains satisfied in the presence of the attacker gadgets.
|
||||
|
||||
\subsection{Usage}%
|
||||
\label{sub:Usage}
|
||||
|
||||
To use \korg, the user inputs a \promela model, a correctness property specified in LTL, a channel from the given \promela model, and an attacker model of choice. \korg will then generate an attacker model gadget corresponding to the selected attacker model with respect to the chosen channel. The attacker model gadget is then appended onto the given \promela model and evaluated against the LTL property with \spin. \korg will then either produce an attack trace demonstrating the precise actions the attacker took to violate the LTL property, or demonstrate the absence of an attack via an exhaustive state-space search.
|
||||
To use \korg, the user first authors a \promela model and a correctness property in LTL. Take the following producer-consumer model, as shown in Listing \ref{lst:prod-consume}.
|
||||
|
||||
Precise details of how to use the \korg implementation are provided in the anonymous repository: (link)
|
||||
\begin{lstlisting}[caption={Example \promela model with four producers and one consumer.}, label={lst:prod-consume}]
|
||||
chan msgs = [4] of { bit };
|
||||
int count = 0;
|
||||
|
||||
active [1] proctype Producer() {
|
||||
do :: atomic { count++; msgs ! 1; } od
|
||||
}
|
||||
|
||||
active [4] proctype Consumer() {
|
||||
do :: atomic { msgs ? 1 -> count--; } od
|
||||
}
|
||||
|
||||
ltl always_positive { always (count >= 0) }
|
||||
\end{lstlisting}
|
||||
|
||||
Next, the user selects a \textit{channel} to generate an attacker on, and an attacker model of choice (see Section \ref{sec:usage_attacker_models} for more details). For example, we select \texttt{msgs} as our channel of choice, \texttt{replay} as our attacker model of choice, and assume the producer-consumer model is in the file \texttt{pc.pml}. Then, we run \korg via command line.
|
||||
|
||||
\begin{lstlisting}[label={lst:korg-shell}]
|
||||
$ ./korg --model=pc.pml --attacker=replay --channel=msgs --eval
|
||||
\end{lstlisting}
|
||||
\korg will then modify the \texttt{pc.pml} file to include the \texttt{replay} attacker gadget, and model-check it with \spin. Then, \korg will find and output the simple attack trace where a producer message is replayed, causing a consumer to consume an extra time. The (simplified) attack trace is shown below.
|
||||
\begin{lstlisting}[label={trace}]
|
||||
(Producer) ko.pml:5 Send 1 -> queue 1 (msgs)
|
||||
(Atk) ko.pml:22 [Recv] 1 <- queue 1 (msgs)
|
||||
(Atk) ko.pml:23 Send 1 -> queue 2 (a_mem)
|
||||
(Atk) ko.pml:47 Recv 1 <- queue 2 (a_mem)
|
||||
(Atk) ko.pml:47 Send 1 -> queue 1 (msgs)
|
||||
(Consumer) ko.pml:9 Recv 1 <- queue 1 (msgs)
|
||||
(Consumer) ko.pml:9 Recv 1 <- queue 1 (msgs)
|
||||
|
||||
spin: _spin_nvr.tmp:3, assertion violated
|
||||
spin: text of failed assertion: assert(!(!((count>=0))))
|
||||
Never claim moves to line 3 [assert(!(!((count>=0))))]
|
||||
\end{lstlisting}
|
||||
|
||||
Additional examples and usage information are provided in the anonymous repository link: (link)
|
||||
|
||||
|
||||
%the user inputs a \promela model, a correctness property specified in LTL, a channel from the given \promela model, and an attacker model of choice. \korg will then generate an attacker model gadget corresponding to the selected attacker model with respect to the chosen channel. The attacker model gadget is then appended onto the given \promela model and evaluated against the LTL property with \spin. \korg will then either produce an attack trace demonstrating the precise actions the attacker took to violate the LTL property, or demonstrate the absence of an attack via an exhaustive state-space search.
|
||||
|
||||
% Precise details of how to use the \korg implementation are provided in the anonymous repository: (link)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Distributed protocols are the foundation for the modern internet, and therefore ensuring their correctness and security is paramount. To this end, formal methods, the use of mathematically rigorous techniques for reasoning about software, has been increasingly employed to analyze and study distributed protocols. Historically, formal methods has been employed for reasoning about concurrency and distributed algorithms \cite{Lamport_1994, Holzmann_1997, Clarke_Wang}, and in recent years formal methods have been employed at scale to reason about the security of cryptographic protocols and primitives \cite{Basin_Cremers_Dreier_Sasse_2022, Blanchet_Smyth_Cheval_Sylvestre, Kobeissi_Nicolas_Tiwari, Blanchet_Jacomme, Basin_Linker_Sasse}.
|
||||
This myriad of formal methods tooling applicable to secure protocols has enabled reasoning about security-relevant properties involving secrecy, authentication, indistinguishability in addition to concurrency, safety, and liveness. However, no previous formal methods tooling offered an effective solution for rigorously studying an attacker that controls communication channels. That is, how do you reason about an attacker that can arbitrarily drop, rearrange, replay, or insert messages onto a communication channel?
|
||||
This myriad of formal methods tooling applicable to secure protocols has enabled reasoning about security-relevant properties involving secrecy, authentication, indistinguishability in addition to concurrency, safety, and liveness. However, no previous formal methods tooling offered an effective solution for rigorously studying an attacker that controls communication channels. That is, how do you reason about an attacker that can arbitrarily drop, reorder, replay, or insert messages onto a communication channel?
|
||||
|
||||
To fill this gap, we introduce \korg, a tool for synthesizing attacks on distributed protocols that implements the theoretical framework proposed in Hippel et al. \cite{Hippel2022}. In particular, \korg targets the communication channels between the protocol endpoints, and synthesizes attacks to violate arbitrary linear temporal logic (LTL) specifications. \korg either synthesizes attack, or proves the absence of such via an exhaustive state-space search. \korg is sound and complete, meaning if there exists an attack \korg will find it, and \korg will never have false positives. \korg supports pre-defined attacker models, including attackers that can replay, rearrange, or drop messages on channels, as well as custom user-defined attacker models. Although \korg best lends itself for reasoning about denial of service attacks, it can target any specification expressable in LTL. We present a variety of case studies illustrating the employability and usefulness of \korg.
|
||||
To fill this gap, we introduce \korg, a tool for synthesizing attacks on distributed protocols that implements the theoretical framework proposed in Hippel et al. \cite{Hippel2022}. In particular, \korg targets the communication channels between the protocol endpoints, and synthesizes attacks to violate arbitrary linear temporal logic (LTL) specifications. \korg either synthesizes attack, or proves the absence of such via an exhaustive state-space search. \korg is sound and complete, meaning if there exists an attack \korg will find it, and \korg will never have false positives. \korg supports pre-defined attacker models, including attackers that can replay, reorder, or drop messages on channels, as well as custom user-defined attacker models. Although \korg best lends itself for reasoning about denial of service attacks, it can target any specification expressable in LTL. We present a variety of case studies illustrating the employability and usefulness of \korg.
|
||||
|
||||
Reference in New Issue
Block a user