From cb402197786a8eb35713a2d4a3f6ef0afbf90dd7 Mon Sep 17 00:00:00 2001 From: Anton Sankov Date: Sun, 8 Jan 2023 02:07:42 +0200 Subject: [PATCH 1/3] Day 17: Fuzzing Advanced --- 2023/day17.md | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) diff --git a/2023/day17.md b/2023/day17.md index e69de29..cf7f191 100644 --- a/2023/day17.md +++ b/2023/day17.md @@ -0,0 +1,242 @@ +# Fuzzing Advanced + +Yesterday we learned what fuzzing is and how to write fuzz tests (unit tests with fuzzy inputs). +However, fuzz testing goes beyond just unit testing. +We can use this methodology to test our web application by fuzzing the requests sent to our server. + +Today, we will take a practical approach to fuzzy testing a web server. + +Different tools can help us do this. + +Such tools are [Burp Intruder](https://portswigger.net/burp/documentation/desktop/tools/intruder) and [SmartBear](https://smartbear.com/). +However, there are proprietary tools that require a paid license to use them. + +That is why for our demonstration today we are going to use a simple open-source CLI written in Go that was inspired by Burp Intruder and provides similar functionality. +It is called [httpfuzz](https://github.com/JonCooperWorks/httpfuzz). + + +## Getting started + +This tool is quite simple. +We provide it a template for our requests (in which we have defined placeholders for the fuzzy data), a wordlist (the fuzzy data) and `httpfuzz` will render the requests and send them to our server. + +First, we need to define a template for our requests. +Create a file named `request.txt` with the following content: + +```text +POST / HTTP/1.1 +Content-Type: application/json +User-Agent: PostmanRuntime/7.26.3 +Accept: */* +Cache-Control: no-cache +Host: localhost:8000 +Accept-Encoding: gzip, deflate +Connection: close +Content-Length: 35 + +{ + "name": "`S9`", +} +``` + +This is a valid HTTP `POST` request to the `/` route with JSON body. +The "\`" symbol in the body defines a placeholder that will be substituted with the data we provide. + +`httpfuzz` can also fuzz the headers, path, and URL params. + +Next, we need to provide a wordlist of inputs that will be placed in the request. +Create a file named `data.txt` with the following content: + +```text +SOME_NAME +Mozilla/5.0 (Linux; Android 7.0; SM-G930VC Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.83 Mobile Safari/537.36 +``` + +In this file, we defined two inputs that will be substituted inside the body. +In a real-world scenario, you should put much more data here for proper fuzz testing. + +Now that we have our template and our inputs, let's run the tool. +Unfortunately, this tool is not distributed as a binary, so we will have to build it from source. +Clone the repo and run: + +```shell +go build -o httpfuzz cmd/httpfuzz.go +``` + +(requires to have a recent version of Go installed on your machine). + +Now that we have the binary let's run it: + +```shell +./httpfuzz \ + --wordlist data.txt \ + --seed-request request.txt \ + --target-header User-Agent \ + --target-param fuzz \ + --delay-ms 50 \ + --skip-cert-verify \ + --proxy-url http://localhost:8080 \ +``` + +- `httpfuzz` is the binary we are invoking. +- `--wordlist data.txt` is the file with inputs we provided. +- `--seed-request requests.txt` is the request template. +- `--target-header User-Agent` tells `httpfuzz` to use the provided inputs in the place of the `User-Agent` header. +- `--target-param fuzz` tells `httpfuzz` to use the provided inputs as values for the `fuzz` URL parameter. +- `--delay-ms 50` tells `httpfuzz` to wait 50 ms between the requests. +- `--skip-cert-verify` tells `httpfuzz` to not do any TLS verification. +- `--proxy-url http://localhost:8080` tells `httpfuzz` where our HTTP server is. + +We have 2 inputs and 3 places to place them (in the body, the `User-Agent` header, and the `fuzz` parameter). +This means that `httpfuzz` will generate 6 requests and send them to our server. + +Let's run it and see what happens. +I wrote a simple web server that logs all requests so that we can see what is coming into our server: + +```shell +$ ./httpfuzz \ + --wordlist data.txt \ + --seed-request request.txt \ + --target-header User-Agent \ + --target-param fuzz \ + --delay-ms 50 \ + --skip-cert-verify \ + --proxy-url http://localhost:8080 \ + +httpfuzz: httpfuzz.go:164: Sending 6 requests +``` + +and the server logs: + +```text +----- +Got request to http://localhost:8000/ +User-Agent header = [SOME_NAME] +Name = S9 +----- +Got request to http://localhost:8000/?fuzz=SOME_NAME +User-Agent header = [PostmanRuntime/7.26.3] +Name = S9 +----- +Got request to http://localhost:8000/ +User-Agent header = [PostmanRuntime/7.26.3] +Name = SOME_NAME +----- +Got request to http://localhost:8000/ +User-Agent header = [Mozilla/5.0 (Linux; Android 7.0; SM-G930VC Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.83 Mobile Safari/537.36] +Name = S9 +----- +Got request to http://localhost:8000/?fuzz=Mozilla%2F5.0+%28Linux%3B+Android+7.0%3B+SM-G930VC+Build%2FNRD90M%3B+wv%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Version%2F4.083+Mobile+Safari%2F537.36 +User-Agent header = [PostmanRuntime/7.26.3] +Name = S9 +----- +Got request to http://localhost:8000/ +User-Agent header = [PostmanRuntime/7.26.3] +Name = Mozilla/5.0 (Linux; Android 7.0; SM-G930VC Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.83 Mobile Safari/537.36 +``` + +We see that we have received 6 HTTP requests. + +Two of them have a value from our values file for the `User-Agent` header, and 4 have the default header from the template. +Two of them have a value from our values file for the `fuzz` query parameter, and 4 have the default header from the template. +Two of them have a value from our values file for the `Name` body property, and 4 have the default header from the template. + +A slight improvement of the tool could be to make different permutations of these requests (for example, a request that has both `?fuzz=` and `User-Agent` as values from the values file). + +Notice how `httpfuzz` does not give us any information about the outcome of the requests. +To figure that out, we need to either set up some sort of monitoring for our server or write a `httpfuzz` plugin that will process the results in a meaningful for us way. +Let's do that. + +To write a custom plugin, we need to implement the [`Listener`](https://github.com/JonCooperWorks/httpfuzz/blob/master/plugin.go#L13) interface: + +```go +// Listener must be implemented by a plugin to users to hook the request - response transaction. +// The Listen method will be run in its own goroutine, so plugins cannot block the rest of the program, however panics can take down the entire process. +type Listener interface { + Listen(results <-chan *Result) +} +``` + +```go +package main + +import ( + "bytes" + "io/ioutil" + "log" + + "github.com/joncooperworks/httpfuzz" +) + +type logResponseCodePlugin struct { + logger *log.Logger +} + +func (b *logResponseCodePlugin) Listen(results <-chan *httpfuzz.Result) { + for result := range results { + b.logger.Printf("Got %d response from the server\n", result.Response.StatusCode) + } +} + +// New returns a logResponseCodePlugin plugin that simple logs the response code of the response. +func New(logger *log.Logger) (httpfuzz.Listener, error) { + return &logResponseCodePlugin{logger: logger}, nil +} +``` + +Now we need to build our plugin first: + +```shell +go build -buildmode=plugin -o log exampleplugins/log/log.go +``` + +and then we can plug it into `httpfuzz` via the `--post-request` flag: + +```shell +$ ./httpfuzz \ + --wordlist data.txt \ + --seed-request request.txt \ + --target-header User-Agent \ + --target-param fuzz \ + --delay-ms 50 \ + --skip-cert-verify \ + --proxy-url http://localhost:8080 \ + --post-request log + +httpfuzz: httpfuzz.go:164: Sending 6 requests +httpfuzz: log.go:15: Got 200 response from the server +httpfuzz: log.go:15: Got 200 response from the server +httpfuzz: log.go:15: Got 200 response from the server +httpfuzz: log.go:15: Got 200 response from the server +httpfuzz: log.go:15: Got 200 response from the server +httpfuzz: log.go:15: Got 200 response from the server +``` + +Voila! +Now we can at least see what the response code from the server was. + +Of course, we can write much more sophisticated plugins that output much more data, but for the purpose of this exercise, that is enough. + +## Summary + +Fuzzing is a really powerful testing technique that goes way beyond unit testing. + +Fuzzing can be extremely useful for testing HTTP servers by substituting parts of valid HTTP requests with data that could potentially expose vulnerabilities or deficiencies in our server. + +There are many tools that can help us in fuzzy testing our web applications, both free and paid ones. + +## Resources + +[OWASP: Fuzzing](https://owasp.org/www-community/Fuzzing) + +[OWASP: Fuzz Vectors](https://owasp.org/www-project-web-security-testing-guide/v41/6-Appendix/C-Fuzz_Vectors) + +[Hacking HTTP with HTTPfuzz](https://medium.com/swlh/hacking-http-with-httpfuzz-67cfd061b616) + +[Fuzzing the Stack for Fun and Profit at DefCamp 2019](https://www.youtube.com/watch?v=qCMfrbpuCBk&list=PLnwq8gv9MEKiUOgrM7wble1YRsrqRzHKq&index=33) + +[HTTP Fuzzing Scan with SmartBear](https://support.smartbear.com/readyapi/docs/security/scans/types/fuzzing-http.html) + +[Fuzzing Session: Finding Bugs and Vulnerabilities Automatically](https://youtu.be/DSJePjhBN5E) + +[Fuzzing the CNCF Landscape](https://youtu.be/zIyIZxAZLzo) From 39312678cacbd42657c914b72fe00c57b7686837 Mon Sep 17 00:00:00 2001 From: Anton Sankov Date: Tue, 17 Jan 2023 15:26:38 +0200 Subject: [PATCH 2/3] Remove trailing whitespaces --- 2023.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/2023.md b/2023.md index 9fcb9fe..6a0f3df 100644 --- a/2023.md +++ b/2023.md @@ -16,14 +16,14 @@ Or contact us via Twitter, my handle is [@MichaelCade1](https://twitter.com/Mich ## List of Topics -| Topic | Author | Date | Twitter Handle | +| Topic | Author | Date | Twitter Handle | | -------------------------------------- | ----------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------- | | DevSecOps | Michael Cade | 1st Jan - 6th Jan | [@MichaelCade1](https://twitter.com/MichaelCade1) | -| Secure Coding | Prateek Jain | 7th Jan - 13th Jan | [@PrateekJainDev](https://twitter.com/PrateekJainDev) | +| Secure Coding | Prateek Jain | 7th Jan - 13th Jan | [@PrateekJainDev](https://twitter.com/PrateekJainDev) | | Continuous Build, Integration, Testing | Anton Sankov and Svetlomir Balevski | 14th Jan - 20th Jan | [@a_sankov](https://twitter.com/a_sankov) | | Continuous Delivery & Deployment | Anton Sankov | 21st Jan - 27th Jan | [@a_sankov](https://twitter.com/a_sankov) | -| Runtime Defence & Monitoring | Ben Hirschberg | 28th Jan - 3rd Feb | [@slashben81](https://twitter.com/slashben81) | -| Secrets Management | Bryan Krausen | 4th Feb - 10th Feb | [@btkrausen](https://twitter.com/btkrausen) | +| Runtime Defence & Monitoring | Ben Hirschberg | 28th Jan - 3rd Feb | [@slashben81](https://twitter.com/slashben81) | +| Secrets Management | Bryan Krausen | 4th Feb - 10th Feb | [@btkrausen](https://twitter.com/btkrausen) | | Python | Rishab Kumar | 11th Feb - 17th Feb | [@rishabk7](https://twitter.com/rishabk7) | | AWS | Chris Williams | 18th Feb - 24th Feb | [@mistwire](https://twitter.com/mistwire) | | OpenShift | Dean Lewis | 25th Feb - 3rd Mar | [@saintdle](https://twitter.com/saintdle) | From 584ad7498ed5b56045e19e1b45d2483909d7860c Mon Sep 17 00:00:00 2001 From: Anton Sankov Date: Tue, 17 Jan 2023 15:27:31 +0200 Subject: [PATCH 3/3] Day 17: Fuzzing Advanced from @a_sankov --- 2023.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2023.md b/2023.md index 6a0f3df..41f8251 100644 --- a/2023.md +++ b/2023.md @@ -59,7 +59,7 @@ Or contact us via Twitter, my handle is [@MichaelCade1](https://twitter.com/Mich - [✔️] 🐧 14 > [Container Image Scanning](2023/day14.md) - [✔️] 🐧 15 > [Container Image Scanning Advanced](2023/day15.md) - [✔️] 🐧 16 > [Fuzzing](2023/day16.md) -- [] 🐧 17 > [](2023/day17.md) +- [✔️] 🐧 17 > [Fuzzing Advanced](2023/day17.md) - [] 🐧 18 > [](2023/day18.md) - [] 🐧 19 > [](2023/day19.md) - [] 🐧 20 > [](2023/day20.md)