diff --git a/README.md b/README.md
index 04cf2b9..44931a4 100644
--- a/README.md
+++ b/README.md
@@ -103,6 +103,33 @@ rules:
The above rule will inject `">
asd
` and `test` in query string values, and check for `asd
` OR `test` in the response contents.
In order to be successful, one of the 2 `responseContents` must be matched, as well as the `Content-Type` response header including `html` within it.
+### Templating
+There is rudimentary templating functionality within the rule's injection points, which can be done by inserting the supported variable in square brackets `[[var]]`.
+This is to allow for some dynamic payloads where you need them. Here are the following fields supported within the templating (these are all related to the URL that is
+being assessed at that point in time):
+- fullurl
+- domain
+- path
+
+An example on using these are:
+
+```
+rules:
+ CallbackFuzz:
+ description: Test for open redirects and potential SSRFs by checking for certain responses or callbacks to your server
+ injections:
+ - "http://[[domain]].example.net/"
+ - "//example.net?targetUrl=[[fullurl]]"
+ - "https://example.net?target=[[domain]][[path]]"
+ - "@example.net"
+ expectation:
+ responseContents:
+ - Example Domain
+```
+
+This is particularly valuable in blind attacks, such as blind SSRF, where `qsfuzz` won't necessarily know whether it's successful, but your callback server receives a hit.
+You can add some data, such as the above supported parameters, within the injection to also send the vulnerable, injected URL within the request.
+
## Help
```
$ qsfuzz -h
diff --git a/utils.go b/utils.go
index 402d4b8..b56c0c2 100644
--- a/utils.go
+++ b/utils.go
@@ -133,11 +133,8 @@ func getInjectedUrls(fullUrl string, ruleInjections []string) ([]string, error)
for qs, values := range queryStrings {
for index, val := range values {
// Check if templating is used in the injection, if so substitute it
- templatedValue := checkTemplate(injection, u)
- if templatedValue != "" {
- injection = templatedValue
- }
- queryStrings[qs][index] = injection
+ expandedInjection := expandTemplatedValues(injection, u)
+ queryStrings[qs][index] = expandedInjection
// TODO: Find a better solution to turn the qs map into a decoded string
decodedQs, err := url.QueryUnescape(queryStrings.Encode())
@@ -163,9 +160,9 @@ func getInjectedUrls(fullUrl string, ruleInjections []string) ([]string, error)
}
// Makeshift templating check within the YAML files to allow for more dynamic config files
-func checkTemplate(ruleInjection string, u *url.URL) string {
+func expandTemplatedValues(ruleInjection string, u *url.URL) string {
if !strings.Contains(ruleInjection, "[[") || !strings.Contains(ruleInjection, "]]") {
- return ""
+ return ruleInjection
}
re := regexp.MustCompile(`\[\[([^\[\]]*)\]\]`)