Skip to content

advanced

Base-Executable Ada Targets

ada-logo

Need to test an uninstrumented or base-executable Ada target? We'll walk you through how to test Ada targets using Mayhem!

Estimated Time: 15 minutes

By the end of this lesson, you will be able to:

  1. Build and test a base-executable Ada target with an improper input validation defect.
  2. Build and test a base-executable Ada target with an index out-of-bounds defect.

You will need the following:

  • Docker installed.
  • A valid Internet connection (for pulling Docker Hub base images)

One Click Testing

Click on the button below to start testing a base-executable Ada target! Click Next until you reach the final confirmation page and then hit Start Run!

You should see a Run page similar to the following:

ada-base-executable-run

Now that you've seen Mayhem testing a base-executable Ada target, let's walk through end-to-end how the Ada target was built!

Testing a Base-Executable Ada Target

Files: ada-base-executable.tgz

Download and extract the above ada-base-executable.tgz and take a look at the following bugged mayhemit.adb program:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Command_Line;
with Ada.Assertions;
with GNAT.Exception_Actions;

procedure Mayhemit is
  Length : Integer := 128;
  Input : String (1 .. Length);
  Fd : File_Type;
  Filename : aliased String := Ada.Command_Line.Argument(1);
  procedure FuzzTest (Input : String) is
    Zero : Integer := 0;
    One : Integer := 1;
    Answer : Integer := 0;
  begin
    if Input (Input'First .. Input'First) = "b" then
      if Input (Input'First + 1 .. Input'First + 1) = "u" then
        if Input (Input'First + 2 .. Input'First + 2) = "g" then
          raise Ada.Assertions.Assertion_Error;
          -- Answer := One / Zero;
        end if;
      end if;
    end if;
  end FuzzTest;
begin

  Open (File => Fd,
        Mode => In_File,
        Name => Filename);
  Get_Line (Fd, Input, Length);
  FuzzTest(Input);

exception
  when Occurence : others  =>
     GNAT.Exception_Actions.Core_Dump (Occurence);
end Mayhemit;

Here we see that the various modules have been imported at the top of the source code and that there are two procedures: Mayhemit and FuzzTest.

The Mayhemit procedure acts as the main entrypoint to the program and handles file input while the FuzzTest procedure checks to see if the input reads as "bug". If so, the program crashes with an improper input validation defect due to the assertion error.

Let's now take a look at how the ada-base-executable target will be built. Looking at the associated Dockerfile we can see the following:

1
2
3
4
5
6
7
FROM tomekw/ada-gnat
COPY mayhemit.adb .
RUN gnatmake -o /mayhemit mayhemit.adb

# Set to fuzz!
ENTRYPOINT []
CMD ["/mayhemit", "@@"]
  • Line 1: The tomekw/ada-gnat base image is imported to gather the necessary Ada dependencies.
  • Line 2: The mayhemit.adb source file is copied into the Docker container.
  • Line 3: The gnatmake compiler is used to compile the mayhemit.adb source code to the mayhemit executable.
  • Line 6: The /mayhemit @@ command is defined as the default executable for the resulting Docker image.

Next, we need to build and push the resulting Docker image to the Mayhem server using the docker build and docker push commands.

Next, we need to build and push the resulting Docker image to the Mayhem server using the docker build and docker push commands, where $DOCKER_REGISTRY represents the URL of the private Mayhem Docker registry.

docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/ada-base-executable .
docker push <DOCKERHUB_USERNAME>/ada-base-executable
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/ada-base-executable .
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/ada-base-executable

Info

You can use the mayhem login command to find your internal Mayhem Docker Registry URL and run the following command to set the DOCKER_REGISTRY environment variable, like so:

export DOCKER_REGISTRY=tutorial.forallsecure.com:5000
Here, we've provided an example Mayhem Docker registry URL, but you will need to set the DOCKER_REGISTRY environment variable for your specific Mayhem Docker Registry URL.

Upon successfully pushing the newly created Docker image to the public Docker Hub registry, create a new run via the Mayhem UI and search for the <DOCKERHUB_USERNAME>/ada-base-executable Docker image. Confirm that your Mayhemfile looks similar to the following:

Upon successfully pushing the newly created Docker image to the private Mayhem Docker Registry, create a new run via the Mayhem UI and search for the forallsecure/ada-base-executable Docker image. Confirm that your Mayhemfile looks similar to the following:

1
2
3
4
5
image: <DOCKERHUB_USERNAME>/ada-base-executable:latest
project: mayhem-examples
target: ada-base-executable
cmds:
  - cmd: /mayhemit @@
1
2
3
4
5
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/ada-base-executable:latest
project: mayhem-examples
target: ada-base-executable
cmds:
  - cmd: /mayhemit @@

Now just click Next until you reach the final confirmation page of the create new run flow and hit Start Run to execute your Mayhem run! You should see a Run page similar to the following:

ada-base-executable-run

Congratulations! You just tested a base-executable Ada target with Mayhem!

Real World Exercise: Building and Testing the mayhemit-out-of-bounds Base-Executable Ada Target

Now that you know how to build and test an Ada target with an improper input validation defect, let's see if you can modify the source code to use an index out-of-bounds defect instead.

Files: mayhemit-out-of-bounds-unsolved.zip

Instructions:

  • Modify the mayhemit.adb source code by initializing the Answer variable as an empty string and adding the index out-of-bounds defect:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    procedure Mayhemit is
    Length : Integer := 3;
    Input : String (1 .. Length);
    Fd : File_Type;
    Filename : aliased String := Ada.Command_Line.Argument(1);
    procedure FuzzTest (Input : String) is
      Zero : Integer := 0;
      One : Integer := 1;
      Answer : String := "";
    begin
      if Input (Input'First .. Input'First) = "b" then
        if Input (Input'First + 1 .. Input'First + 1) = "u" then
          if Input (Input'First + 2 .. Input'First + 2) = "g" then
            -- raise Ada.Assertions.Assertion_Error; also works.
            Answer := Input (Input'First + 10 .. Input'First + 10);
          end if;
        end if;
      end if;
    end FuzzTest;
    
  • Rebuild the Dockerfile using the docker build command and tag the resulting Docker image as <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds.

  • Push the <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds Docker image to the internal Mayhem Docker registry using the docker tag and docker push commands.

  • Fuzz the <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds Docker image using either the Mayhem UI or Mayhem CLI. Make sure to set the associated Mayhemfile accordingly.

  • Rebuild the Dockerfile using the docker build command and tag the resulting Docker image as $MAYHEM_DOCKER_REGISTRY/ada-base-executable-mayhemit-out-of-bounds.

  • Push the $MAYHEM_DOCKER_REGISTRY/ada-base-executable-mayhemit-out-of-bounds Docker image to the internal Mayhem Docker registry using the docker tag and docker push commands.

  • Test the $MAYHEM_DOCKER_REGISTRY/ada-base-executable-mayhemit-out-of-bounds Docker image using either the Mayhem UI or Mayhem CLI. Make sure to set the associated Mayhemfile accordingly.

🔍 Review It! Building and Testing the mayhemit-out-of-bounds Base-Executable Ada Target

Solution

Solution: mayhemit-out-of-bounds-solved.zip

First things first, you needed to set the Answer variable as a string type. Then, you needed to add the index out-of-bounds defect by setting the Answer variable to a string character whose index is out of bounds of what is expected by the max length specified on line 7.

This makes it so that when the FuzzTest procedure is fuzzed, the input test case "bug" will trigger the index out-of-bounds error because the max length is set to 3 while the Answer variable is set to an index of 11 (Input'First + 10).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Command_Line;
with Ada.Assertions;
with GNAT.Exception_Actions;

procedure Mayhemit is
  Length : Integer := 3;
  Input : String (1 .. Length);
  Fd : File_Type;
  Filename : aliased String := Ada.Command_Line.Argument(1);
  procedure FuzzTest (Input : String) is
    Zero : Integer := 0;
    One : Integer := 1;
    Answer : String := "";
  begin
    if Input (Input'First .. Input'First) = "b" then
      if Input (Input'First + 1 .. Input'First + 1) = "u" then
        if Input (Input'First + 2 .. Input'First + 2) = "g" then
          -- raise Ada.Assertions.Assertion_Error; also works.
          Answer := Input (Input'First + 10 .. Input'First + 10);
        end if;
      end if;
    end if;
  end FuzzTest;
begin

  Open (File => Fd,
        Mode => In_File,
        Name => Filename);
  Get_Line (Fd, Input, Length);
  FuzzTest(Input);

exception
  when Occurence : others  =>
    GNAT.Exception_Actions.Core_Dump (Occurence);
end Mayhemit;

Then, you needed to run the docker build command in the same directory as the Dockerfile and simultaneously tag the resulting Docker image as <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds:

Then, you needed to run the docker build command in the same directory as the Dockerfile and simultaneously tag the resulting Docker image as ada-base-executable-mayhemit-out-of-bounds:

docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds .
docker build -f Dockerfile -t ada-base-executable-mayhemit-out-of-bounds .

Next, you had to tag and push the <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds Docker image to the internal Mayhem Docker registry:

Next, you had to tag and push the ada-base-executable-mayhemit-out-of-bounds Docker image to the internal Mayhem Docker registry:

docker push <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds
docker push tutorial.forallsecure.com:5000/ada-base-executable-mayhemit-out-of-bounds

Note

Here we uploaded the ada-base-executable-mayhemit-out-of-bounds Docker image to our tutorial.forallsecure.com Mayhem deployment, specifically at the internal Docker registry located at port 5000. For your Docker image to have successfully uploaded, you would have had to adjust the URL for your Mayhem deployment Docker registry accordingly.

Alternatively, you could have also used the included Makefile to easily build and push the resulting Docker image by setting a MAYHEM_DOCKER_REGISTRY environment variable and running the following commands:

make build
make push

Lastly, you could have executed a Mayhem run on the uploaded ada-base-executable-mayhemit-out-of-bounds Docker image using either the Mayhem UI or Mayhem CLI. As long as your Mayhemfile looked similar to the following:

Lastly, you could have executed a Mayhem run on the uploaded ada-base-executable-mayhemit-out-of-bounds Docker image using either the Mayhem UI or Mayhem CLI. As long as your Mayhemfile looked similar to the following:

1
2
3
4
5
6
image: <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds
duration: 90
project: mayhem-examples
target: mayhemit-out-of-bounds
cmds:
  - cmd: /mayhemit @@
1
2
3
4
5
6
image: $MAYHEM_DOCKER_REGISTRY/ada-base-executable-mayhemit-out-of-bounds
duration: 90
project: mayhem-examples
target: mayhemit-out-of-bounds
cmds:
  - cmd: /mayhemit @@

Your final Run page should have looked like the following:

mayhemit-out-of-bounds-run

Congratulations! Mayhem found the index out-of-bounds defect that you added! You just built a base-executable Ada target from scratch and used Mayhem to detect the vulnerability that you added!

✏️ Summary and Recap

In this lesson, you learned how to fuzz base-executable Ada targets with Mayhem!


I learned how to...

1. Build and test a base-executable Ada target with an improper input validation defect.
  • The source code should contain the following defect:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    procedure Mayhemit is
    Length : Integer := 128;
    Input : String (1 .. Length);
    Fd : File_Type;
    Filename : aliased String := Ada.Command_Line.Argument(1);
    procedure FuzzTest (Input : String) is
      Zero : Integer := 0;
      One : Integer := 1;
      Answer : Integer := 0;
    begin
      if Input (Input'First .. Input'First) = "b" then
        if Input (Input'First + 1 .. Input'First + 1) = "u" then
          if Input (Input'First + 2 .. Input'First + 2) = "g" then
            raise Ada.Assertions.Assertion_Error;
            -- Answer := One / Zero;
          end if;
        end if;
      end if;
    end FuzzTest;
    

  • Then, to compile and fuzz the base-executable Ada target, use the following Dockerfile and Mayhemfile to build the Docker image containing the Ada program and fuzz it in Mayhem, respectively:

    1
    2
    3
    4
    5
    6
    7
    FROM tomekw/ada-gnat
    COPY mayhemit.adb .
    RUN gnatmake -o /mayhemit mayhemit.adb
    
    # Set to fuzz!
    ENTRYPOINT []
    CMD ["/mayhemit", "@@"]
    

    1
    2
    3
    4
    5
    image: <DOCKERHUB_USERNAME>/ada-base-executable:latest
    project: mayhem-examples
    target: ada-base-executable
    cmds:
      - cmd: /mayhemit @@
    
    1
    2
    3
    4
    5
    image: $MAYHEM_DOCKER_REGISTRY/forallsecure/ada-base-executable:latest
    project: mayhem-examples
    target: ada-base-executable
    cmds:
      - cmd: /mayhemit @@
    
2. Build and fuzz a base-executable Ada target with an index out-of-bounds defect.
  • The source code should contain the following defect:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    procedure Mayhemit is
    Length : Integer := 3;
    Input : String (1 .. Length);
    Fd : File_Type;
    Filename : aliased String := Ada.Command_Line.Argument(1);
    procedure FuzzTest (Input : String) is
        Zero : Integer := 0;
        One : Integer := 1;
        Answer : String := "";
    begin
        if Input (Input'First .. Input'First) = "b" then
          if Input (Input'First + 1 .. Input'First + 1) = "u" then
            if Input (Input'First + 2 .. Input'First + 2) = "g" then
              -- raise Ada.Assertions.Assertion_Error; also works.
              Answer := Input (Input'First + 10 .. Input'First + 10);
              end if;
          end if;
        end if;
    end FuzzTest;
    begin
    

  • Then, to compile and fuzz the base-executable Ada target, use the following Dockerfile and Mayhemfile to build the Docker image containing the Ada program and fuzz it in Mayhem, respectively:

    1
    2
    3
    4
    5
    6
    7
    FROM tomekw/ada-gnat
    COPY mayhemit.adb .
    RUN gnatmake -o /mayhemit mayhemit.adb
    
    # Set to fuzz!
    ENTRYPOINT []
    CMD ["/mayhemit", "@@"]
    

    1
    2
    3
    4
    5
    6
    image: <DOCKERHUB_USERNAME>/ada-base-executable-mayhemit-out-of-bounds
    duration: 90
    project: mayhem-examples
    target: ada-base-executable-mayhemit-out-of-bounds
    cmds:
      - cmd: /mayhemit @@
    
    1
    2
    3
    4
    5
    6
    image: $MAYHEM_DOCKER_REGISTRY/ada-base-executable-mayhemit-out-of-bounds:latest
    duration: 90
    project: mayhem-examples
    target: ada-base-executable-mayhemit-out-of-bounds
    cmds:
      - cmd: /mayhemit @@