Sharon Brizinov 5 лет назад
Родитель
Сommit
1844ce080d

+ 38 - 0
README.md

@@ -127,6 +127,44 @@ use the GIT version you will need the program Doxygen for generating the HTML
 documentation. You can generate the documentation by invoking doxygen from the 
 command line in the opener main directory.
 
+
+Fuzzing:
+--------------
+Fuzzing is an automated testing method that directs varying input data to a program in 
+order to monitor output. It is a way to test for overall reliability as well as identify 
+potential security bugs.
+
+The fuzzer we are using is AFL, a fuzzer that uses runtime guided techniques to create input for the tested program. From a high-level prespective AFL works as follows:
+- Forks the fuzzed process
+- Genereates a new test case based on a predefined input
+- Feeds the fuzzed process with the test case through STDIN
+- Monitors the execution and registers which paths are reachable
+
+To start fuzzing this project with AFL you'll need to compile it with AFL. First make sure you have AFL prepared:
+```
+sudo apt install build-essential
+wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz
+tar xzf afl-latest.tgz
+cd afl*
+make && sudo make install
+echo "AFL is ready at: $(which afl-fuzz)"
+
+```
+
+Then, compile it with AFL:
+1. Change to the ``OpENer/bin/posix`` directory
+2. Compile OpENer with AFL ``./setup_posix_fuzz_afl.sh`` 
+3. Run ``make``
+
+Finally, generate some test cases and start AFL:
+```
+# Generate inputs
+mkdir inputs
+echo 630000000000000000000000000000000000000000000000 | xxd -r -p > ./inputs/req_list_identity
+afl-fuzz -i inputs -o findings ./src/ports/POSIX/OpENer eth1
+```
+![Alt text](fuzz/fuzz.png "AFL Fuzzing")
+
 Porting OpENer:
 ---------------
 For porting OpENer to new platforms please see the porting section in the 

+ 2 - 0
bin/posix/setup_posix_fuzz_afl.sh

@@ -0,0 +1,2 @@
+cmake -DCMAKE_C_COMPILER=afl-clang-fast -DUSE_FUZZ_AFL=ON -DOpENer_PLATFORM:STRING="POSIX" -DCMAKE_BUILD_TYPE:STRING="" -DBUILD_SHARED_LIBS:BOOL=OFF ../../source
+


+ 9 - 0
source/src/enet_encap/encap.c

@@ -749,6 +749,15 @@ EipInt16 CreateEncapsulationStructure(const EipUint8 *receive_buffer,
  */
 SessionStatus CheckRegisteredSessions(
   const EncapsulationData *const receive_data) {
+
+/* Skip the check when fuzzing
+    in order to increase our code coverage 
+    we are simply bypassing all the session checks
+*/
+#ifdef FUZZING_AFL
+  return kSessionStatusValid;
+#endif
+
   if( (0 < receive_data->session_handle) && (receive_data->session_handle <=
                                              OPENER_NUMBER_OF_SUPPORTED_SESSIONS) )
   {

+ 8 - 0
source/src/ports/POSIX/CMakeLists.txt

@@ -12,6 +12,14 @@ if(OpENer_RT)
   add_definitions(-DOPENER_RT_THREAD_SIZE=${OpENer_RT_Additional_Stacksize})
 endif(OpENer_RT)
 
+#######################################
+# AFL Fuzzing                         #
+#######################################
+option(USE_FUZZ_AFL "Fuzz mode" OFF)
+if(USE_FUZZ_AFL)
+  add_definitions( -DFUZZING_AFL )
+endif(USE_FUZZ_AFL)
+
 #######################################
 # Add common includes                 #
 #######################################

+ 37 - 0
source/src/ports/POSIX/main.c

@@ -6,6 +6,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <unistd.h>
 #include <sys/capability.h>
 
 #ifdef OPENER_RT
@@ -50,6 +51,12 @@ static void LeaveStack(int signal);
  */
 static void *executeEventLoop(void *pthread_arg);
 
+/******************************************************************************/
+/** @brief Fuzz TCP packets handling flow with AFL.
+ *
+ */
+static void *fuzzHandlePacketFlow(void);
+
 /*****************************************************************************/
 /** @brief Flag indicating if the stack should end its execution
  */
@@ -127,6 +134,12 @@ int main(int argc,
    */
   GetHostName(&g_tcpip.hostname);
 
+  /* Fuzzing UDP/TCP handle packet flow */
+#ifdef FUZZING_AFL
+  fuzzHandlePacketFlow();
+  return EXIT_SUCCESS;
+#endif 
+
   /* The CIP objects are now created and initialized with their default values.
    *  After that any NV data values are loaded to change the attribute contents
    *  to the stored configuration.
@@ -277,3 +290,27 @@ static void *executeEventLoop(void *pthread_arg) {
 
   return &pthread_dummy_ret;
 }
+
+static void fuzzHandlePacketFlow(void) {
+  int socket_fd = 0;   // Fake socket fd
+  uint8_t buff[512];   // Input buffer
+  struct sockaddr_in from_address = { 0 }; // Fake socket address
+  int remaining_bytes = 0; // Fake reamining bytes
+  ENIPMessage outgoing_message;
+
+  /* AFL persistent mode */
+  while(__AFL_LOOP(100000)) {
+    /* Read input from STDIN and enter the handle receive flow */
+    memset(buff, 0, 512);
+    ssize_t received_size = read(STDIN_FILENO, buff, 512);
+    EipUint8 *receive_buffer = &buff[0];
+
+    InitializeENIPMessage(&outgoing_message);
+
+    // Fuzz UDP
+    //EipStatus need_to_send = HandleReceivedExplictUdpData(socket_fd, &from_address, receive_buffer, received_size, &remaining_bytes, true, &outgoing_message);
+
+    // Fuzz TCP
+    EipStatus need_to_send = HandleReceivedExplictTcpData(socket_fd, receive_buffer, received_size, &remaining_bytes, &from_address, &outgoing_message);
+  }
+}