コンテンツにスキップ

advanced

Base-Executable Go Targets

go-logo

Got an uninstrumented or base-executable Go target? In this lesson, we'll walk through how to compile base-executable Go targets and fuzz them in Mayhem!

Estimated Time: 15 minutes

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

  1. Compile and fuzz a base-executable Go target with a reachable assertion defect.
  2. Compile and fuzz a base-executable Go target with an index-out-of-bounds defect.

Run through the lesson:

See prerequisites before beginning.

  1. Download the go-base-executable.tgz and build the go-base-executable Docker image, and push it to the specified Docker registry:

    docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/go-base-executable .
    docker push <DOCKERHUB_USERNAME>/go-base-executable
    
    docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/go-base-executable .
    docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/go-base-executable
    
  2. Execute a Mayhem run on the go-base-executable Docker image using either the Mayhem UI or Mayhem CLI with the following Mayhemfile:

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

You will need the following:

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

One Click Testing

Click on the following button and hit Start Run at the end of the Create New Run flow to get a quick start on testing a base-executable Go target! No need to configure anything, as the underlying Mayhemfile has already been configured for you!

Once the Mayhem run initiates, you should see a Run page similar to the following:

go-base-executable-run

Awesome! Now that you've seen Mayhem testing a base-executable Go target, let's now walk through how to compile and fuzz the go-base-executable target that you just executed a Mayhem run for!

Building and Testing a Base-Executable Go Target

File: go-base-executable.tgz

Download and extract the above go-base-executable.tgz and take a look at the following bugged mayhemit.go 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
package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "os"
)

func mayhemit(bytes []byte) int {
    content := string(bytes)
    if len(content) >= 3 {
        if string(content[0]) == "b" {
            if string(content[1]) == "u" {
                if string(content[2]) == "g" {
                    panic("found a bug!")
                }
            }
        }
    }
    return 0
}

func main() {
    if len(os.Args) != 2 {
        fmt.Printf("Usage: ./mayhemit <file>\n")
        os.Exit(1)
    }
    bytes, err := ioutil.ReadFile(os.Args[1])
    if err != nil {
        log.Fatal(err)
    }
    mayhemit(bytes)
}

Here we see that there are two functions of interest: main and mayhemit. The main function handles the file input to the program and invokes the mayhemit function on line 33 to check if the input test case reads "bug". If so, the program crashes via a reachable assertion error caused by the panic() function on line 16.

Let's now take a look at how this program will ultimately be compiled. The associated Dockerfile for the go-base-executable target shows the following:

1
2
3
4
5
6
7
FROM golang:1.13.3-buster as go-target
COPY mayhemit.go .
RUN go build -o mayhemit -a mayhemit.go

# Set to fuzz!
ENTRYPOINT []
CMD /go/mayhemit @@
  • Line 1: The golang:1.13.3-buster base image is imported to provide the necessary go dependencies.
  • Line 2: The mayhemit.go source code is copied over into the Docker container.
  • Line 3: The go build command is used to compile the mayhemit.go source files to the mayhemit executable.
  • Line 7: The /go/mayhemit @@ executable is set as the default executable for the resulting Docker container.

Then, make sure you're within the go-base-executable folder and use the following docker commands to build the resulting <DOCKERHUB_USERNAME>/go-base-executable Docker image and push it to the Docker Hub registry:

Then, make sure you're within the go-base-executable folder and use the following docker commands to build the resulting forallsecure/go-base-executable Docker image and push it to the Mayhem Docker Registry:

docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/go-base-executable .
docker push <DOCKERHUB_USERNAME>/go-base-executable
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/go-base-executable .
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/go-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.

Next, go to the Mayhem UI and search for the <DOCKERHUB_USERNAME>/go-base-executable Docker image. Confirm that your Mayhemfile looks similar to the following:

Next, go to the Mayhem UI and search for the forallsecure/go-base-executable Docker image. Confirm that your Mayhemfile looks similar to the following:

1
2
3
4
5
6
image: <DOCKERHUB_USERNAME>/go-base-executable:latest
duration: 90
project: mayhem-examples
target: go-base-executable
cmds:
  - cmd: /go/mayhemit @@
1
2
3
4
5
6
image: $MAYHEM_DOCKER_REGISTRY/go-base-executable:latest
duration: 90
project: mayhem-examples
target: go-base-executable
cmds:
  - cmd: /go/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:

go-base-executable-run

You should now see that Mayhem was able to find the underlying reachable assertion defect! Congratulations on compiling and testing your base-executable Go target!

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

Now that you know how to build and test an base-executable Go target, let's see if you can modify the source code to use an index out-of-bounds error instead of a reachable assertion defect!

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

Instructions:

  • Modify the mayhemit.go source code and add the following max length constraint and corresponding index out-of-bounds defect:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    func mayhemit(bytes []byte) int {
        content := string(bytes)
        if len(content) >= 3 && len(content) < 5 {
            if string(content[0]) == "b" {
                if string(content[1]) == "u" {
                    if string(content[2]) == "g" {
                        var x = content[10]
                        fmt.Println(x)
                    }
                }
            }
        }
        return 0
    }
    
  • Rebuild the Dockerfile using the docker build command and tag the resulting Docker image as <DOCKERHUB_USERNAME>/go-base-executable-mayhemit-out-of-bounds.

  • Push the <DOCKERHUB_USERNAME>/go-base-executable-mayhemit-out-of-bounds Docker image to the internal Mayhem Docker registry using the docker push command.
  • Fuzz the <DOCKERHUB_USERNAME>/go-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 go-base-executable-mayhemit-out-of-bounds.
  • Push the go-base-executable-mayhemit-out-of-bounds Docker image to the internal Mayhem Docker registry using the docker push command.
  • Test the go-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 Go Target

Solution

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

First things first, you needed to add the max length constraint len(content) < 5 and the erroneous call for content[10] so that when the mayhemit function is fuzzed, the input test case "bug" will trigger the index out-of-bounds error.

 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
37
38
39
40
package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "os"
)

func mayhemit(bytes []byte) int {
    content := string(bytes)
    if len(content) >= 3 && len(content) < 5 {
        if string(content[0]) == "b" {
            if string(content[1]) == "u" {
                if string(content[2]) == "g" {
                    var x = content[10]
                    fmt.Println(x)
                }
            }
        }
    }
    return 0
}

func divBy(val int) int {
    y := 1 / val
    return y
}

func main() {
    if len(os.Args) != 2 {
        fmt.Printf("Usage: ./mayhemit <file>\n")
        os.Exit(1)
    }
    bytes, err := ioutil.ReadFile(os.Args[1])
    if err != nil {
        log.Fatal(err)
    }
    mayhemit(bytes)
}

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

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

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

Next, you had to tag and push the <DOCKERHUB_USERNAME>/go-base-executable-mayhemit-out-of-bounds Docker image to the public Docker Hub registry.

Next, you had to tag and push the $MAYHEM_DOCKER_REGISTRY/go-base-executable-mayhemit-out-of-bounds Docker image to the private Mayhem Docker registry.

docker push <DOCKERHUB_USERNAME>/go-base-executable-mayhemit-out-of-bounds
docker push $MAYHEM_DOCKER_REGISTRY/go-base-executable-mayhemit-out-of-bounds

Note

Here we uploaded the go-base-executable-mayhemit-out-of-bounds Docker image to our tutorial.forallsecure.com Mayhem deployment, specifically at the private Mayhem 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 <DOCKERHUB_USERNAME>/go-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 go-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>/go-base-executable-mayhemit-out-of-bounds:latest
duration: 90
project: mayhem-examples
target: go-base-executable-mayhemit-out-of-bounds
cmds:
  - cmd: /go/mayhemit @@
1
2
3
4
5
6
image: $MAYHEM_DOCKER_REGISTRY/go-base-executable-mayhemit-out-of-bounds:latest
duration: 90
project: mayhem-examples
target: go-base-executable-mayhemit-out-of-bounds
cmds:
  - cmd: /go/mayhemit @@

Your final Run page should have looked like the following:

mayhemit-out-of-bounds

Congratulations! Mayhem found the index out-of-bounds defect that you added! You just built an base-executable Go target from scratch and added a bug that was detected in Mayhem!

✏️ Summary and Recap

In this lesson, you learned how to compile base-executable Go targets and fuzz them in Mayhem!


I learned how to...

1. Compile and test a base-executable Go target with a reachable assertion defect.
  • The source code should contain the following defect:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    func mayhemit(bytes []byte) int {
        content := string(bytes)
        if len(content) >= 3 {
            if string(content[0]) == "b" {
                if string(content[1]) == "u" {
                    if string(content[2]) == "g" {
                        panic("found a bug!")
                    }
                }
            }
        }
        return 0
    }
    

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

    1
    2
    3
    4
    5
    6
    7
    FROM golang:1.13.3-buster as go-target
    COPY mayhemit.go .
    RUN go build -o mayhemit -a mayhemit.go
    
    # Set to fuzz!
    ENTRYPOINT []
    CMD /go/mayhemit @@
    

    1
    2
    3
    4
    5
    6
    image: <DOCKERHUB_USERNAME>/go-base-executable:latest
    duration: 90
    project: mayhem-examples
    target: go-base-executable
    cmds:
      - cmd: /go/mayhemit @@
    
    1
    2
    3
    4
    5
    6
    image: $MAYHEM_DOCKER_REGISTRY/forallsecure/go-base-executable:latest
    duration: 90
    project: mayhem-examples
    target: go-base-executable
    cmds:
      - cmd: /go/mayhemit @@
    
2. Compile and fuzz a base-executable Go 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
    func mayhemit(bytes []byte) int {
        content := string(bytes)
        if len(content) >= 3 && len(content) < 5 {
            if string(content[0]) == "b" {
                if string(content[1]) == "u" {
                    if string(content[2]) == "g" {
                        var x = content[10]
                        fmt.Println(x)
                    }
                }
            }
        }
        return 0
    }
    

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

    1
    2
    3
    4
    5
    6
    7
    FROM golang:1.13.3-buster as go-target
    COPY mayhemit.go .
    RUN go build -o mayhemit -a mayhemit.go
    
    # Set to fuzz!
    ENTRYPOINT []
    CMD /go/mayhemit @@
    

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