How to Run a Web Application With Instrumentation and Fuzz It
To showcase the versatility of out of process fuzzing, we will start Webgoat using the docker image webgoat/goatandwolf. If you want, you can also start it locally, but some steps will be different.
docker run -it webgoat/goatandwolf
You should see the standard output of the webgoat application.
In case of Web Applications, CI Fuzz sends the fuzzing input in the form of HTTP requests. To gather information about program execution and detect vulnerabilities/bugs, it uses a Java agent, which inserts bytecode to the running application. This is called Instrumentation. Let's set this up.
In VS Code, click on the Code Intelligence icon in the sidebar, then go to Web Services, Add Web Service.
Give the web service any unique name.
Note: This UI element will only work if you created the fuzzing project in a directory that contains your application's source code (recommended). If this is not the case, you will have to add the instrumentation_includes option manually.
Here you can define which parts of the application should be instrumented by CI Fuzz. Instrumenting the code is a requirement for feedback-based fuzzing. Instrumentation allows our fuzzers to automatically increase the code coverage reached by its test cases through the feedback they get through instrumented code. But instrumentation also slows down the code. To limit this slowdown, you can specify which packages you want to be instrumented. By default, only your application package will be selected, and no external dependencies will be instrumented. If you want to enable instrumentation of external dependencies or disable it for parts of your application, this setting will allow you to do so.
Now find out the IP address on which your host can be reached from Webgoat's docker container:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b4def2bfe29 webgoat/goatandwolf "/bin/sh -c '/bin/ba…" About a minute ago Up About a minute 8080/tcp, 9090/tcp gallant_faraday
9be7f8b3f6c7 mongo "docker-entrypoint.s…" About an hour ago Up About an hour 127.0.0.1:27017->27017/tcp ci-mongodb
$ docker inspect 5b4def2bfe29 | grep Gateway
Stop your ci-daemon (with ctrl+c) and start it again, so that it listens on the docker network interface:
You can find the IP address of your docker interface with this command:
ip a |grep docker
In VS Code, set this IP as custom fuzzing server:
Now the VS Code extension has generated Java command line arguments that will result in our web application being instrumented by CI Fuzz Java Agent. Triple click it to select it and copy, or use the copy button on the right.
Now let's have a look at the Dockerfile:
We can see that Webgoat is started in the start.sh script. We will need to rebuild the image with a modified start script. Let's edit the Dockerfile and reuse the image we already have, so that we don't have to build the WebGoat jars and download the OpenJDK image:
COPY --chown=webgoat start.sh /home/webgoat
java -Duser .home=/home/webgoat -Dfile.encodeing-UTF-8 \
-jar home/webgoat/webgoat.jar --server.address=0.0.0.0
docker build . -t webgoat_instrumented
~/git/webgoat/docker$ file ~/bin/fuzzing_agent.jar
/home/user/bin/fuzzing_agent_deploy.jar: symbolic link to /opt/ci-fuzz-2.27.0/lib/code-intelligence/fuzzing_agent.jar
We can stop the old webgoat container, and start our instrumented version. Optionally, add the ports as arguments, as per docker/Readme.md. This will make fuzz test configuration easier later, as Webgoat will run on default origin (http://localhost:8080). Mount the directory containing the Java Agent jar file.
docker run -it -v /opt/ci-fuzz-2.27.0/lib/code-intelligence/:/cibin/ -p 80:8888 -p 8080:8080 -p 9090:9090 -e TZ=Europe/Amsterdam webgoat_instrumented
You should see the standard output of the WebGoat application, but this time with lines like these:
INFO: Instrumented org.owasp.webgoat.users.LessonTracker (took 2 ms, size +26%)
INFO: Got status 'OK' from fuzzing server
This means that the instrumentation is working and fuzzing server (ci-daemon) can be reached.
In the CI Fuzz extension, Web Services section, you can click "Close Wizard", if it's still open. You should see a green web service:
If you hover over it, it should say when was the last contact.
You can click on it and continue with Creating a Fuzz Test.