### Kiterunner Quick Start Scan (Bash)
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
This example demonstrates a quick start for Kiterunner, performing a scan with a list of hosts and Assetnote's API route wordlists, specifying concurrency and failing status codes.
```bash
kr scan hosts.txt -A=apiroutes-210328:20000 -x 5 -j 100 --fail-status-codes 400,401,404,403,501,502,426,411
```
--------------------------------
### Install Kiterunner via AUR Helper (Bash)
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
This snippet shows how to install the Kiterunner binary on Arch-based Linux distributions using an AUR helper like 'yay'.
```bash
yay -S kiterunner-bin
```
--------------------------------
### Install Kiterunner via AUR (Bash)
Source: https://context7.com/assetnote/kiterunner/llms.txt
Provides commands to install the Kiterunner binary from the Arch User Repository using popular AUR helpers like yay and paru.
```bash
yay -S kiterunner-bin
paru -S kiterunner-bin
```
--------------------------------
### GET /thisshouldnotexist
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/tornado.md
Demonstrates the 404 Not Found error handling behavior of the Tornado server.
```APIDOC
## GET /thisshouldnotexist
### Description
Requests a non-existent resource to trigger the standard 404 error response.
### Method
GET
### Endpoint
/thisshouldnotexist
### Response
#### Error Response (404)
- **body** (html) - Standard 404 Not Found HTML page.
#### Response Example
404: Not Found404: Not Found
```
--------------------------------
### Kiterunner Depth Scanning Wordlist Example
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
Provides an example of a wordlist used for depth scanning in Kiterunner. The paths in the wordlist illustrate different levels of directory depth, which Kiterunner uses to detect wildcards.
```plaintext
/api/v1/user/create
/api/v1/user/delete
/api/v2/user/
/api/v2/admin/
/secrets/v1/
/secrets/v2/
```
--------------------------------
### Kiterunner Input and Domain Parsing Examples
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
Demonstrates how Kiterunner parses different input formats for domains, including full URIs, incomplete URIs, and hostnames with specified ports. It shows the expansion of these inputs into usable targets for scanning.
```bash
one.com
two.com:80
three.com:443
four.com:9447
https://five.com:9090
http://six.com:80/api
```
--------------------------------
### GET /
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/kestrel.md
This endpoint is the root path for the Kestrel service, typically used for basic access or redirection.
```APIDOC
## GET /
### Description
Provides access to the root of the Kestrel service.
### Method
GET
### Endpoint
/
### Response
#### Success Response (200)
- **message** (string) - A welcome message or service information.
#### Response Example
```json
{
"message": "Welcome to Kestrel"
}
```
#### Error Response (404)
- **error** (string) - Indicates the resource was not found.
#### Response Example
```json
{
"error": "Not Found"
}
```
```
--------------------------------
### GET /
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/nest.md
Attempts to retrieve the root resource. Typically returns a 404 Not Found error for Nest applications.
```APIDOC
## GET /
### Description
Attempts to retrieve the root resource. This endpoint is expected to return a 404 Not Found error in a Nest.js application.
### Method
GET
### Endpoint
/
### Parameters
None
### Request Example
None
### Response
#### Error Response (404)
- **statusCode** (integer) - The HTTP status code, expected to be 404.
- **message** (string) - A message indicating the resource was not found.
- **error** (string) - The type of error, expected to be "Not Found".
#### Response Example
```json
{
"statusCode": 404,
"message": "Cannot GET /",
"error": "Not Found"
}
```
```
--------------------------------
### GET /
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/tornado.md
Retrieves the root endpoint of the Tornado server to identify the server signature.
```APIDOC
## GET /
### Description
Fetches the root path of the server to verify the TornadoServer signature.
### Method
GET
### Endpoint
/
### Response
#### Success Response (200)
- **Server** (string) - The server header identifying the software as TornadoServer.
#### Response Example
{
"Server": "TornadoServer"
}
```
--------------------------------
### Execute Kiterunner Scans with Assetnote Wordlists
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
Examples of using the -A flag to specify Assetnote wordlist aliases for scanning and brute-forcing targets.
```bash
kr scan targets.txt -A=apiroutes-210228 -x 10 --ignore-length=34
kr brute targets.txt -A=aspx-210228 -x 10 --ignore-length=34 -easp,aspx
```
--------------------------------
### Kiterunner Scan with Custom and Assetnote Wordlists (Bash)
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
This example shows how to use Kiterunner to scan a target domain, combining a custom wordlist with Assetnote's wordlists, and configuring concurrency and ignored status codes.
```bash
kr scan target.com -w routes.kite -A=apiroutes-210328:20000 -x 20 -j 1 --fail-status-codes 400,401,404,403,501,502,426,411
```
--------------------------------
### GET / - Not Found Error
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/loopback.md
This endpoint is expected to return a 'NotFoundError' when accessed.
```APIDOC
## GET /
### Description
This endpoint is expected to return a 'NotFoundError'.
### Method
GET
### Endpoint
/
### Parameters
None
### Request Example
None
### Response
#### Success Response (200)
- **name** (string) - Indicates the type of error, 'NotFoundError'.
#### Response Example
```json
{
"name": "NotFoundError"
}
```
```
--------------------------------
### GET /thisshouldnotexist - Not Found Error
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/loopback.md
This endpoint is designed to return a 'NotFoundError'.
```APIDOC
## GET /thisshouldnotexist
### Description
This endpoint is designed to return a 'NotFoundError'.
### Method
GET
### Endpoint
/thisshouldnotexist
### Parameters
None
### Request Example
None
### Response
#### Success Response (200)
- **name** (string) - Indicates the type of error, 'NotFoundError'.
#### Response Example
```json
{
"name": "NotFoundError"
}
```
```
--------------------------------
### GET /api-auth/login/
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/django.md
Retrieves the Django REST framework login interface for user authentication.
```APIDOC
## GET /api-auth/login/
### Description
Accesses the login page provided by the Django REST framework to authenticate users.
### Method
GET
### Endpoint
/api-auth/login/
### Parameters
#### Query Parameters
- **next** (string) - Optional - The URL to redirect to after successful authentication.
### Request Example
GET /api-auth/login/?next=/
### Response
#### Success Response (200)
- **Content-Type** (text/html) - Returns the HTML login form for the Django REST framework.
```
--------------------------------
### GET / (Root and Non-existent Paths)
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/dropwizard.md
Describes the behavior of the Dropwizard API when accessing the root path or undefined routes.
```APIDOC
## GET /
### Description
Returns a 404 Not Found error when accessing the root or any undefined path on the Dropwizard server.
### Method
GET
### Endpoint
/
### Parameters
None
### Request Example
GET /
### Response
#### Success Response (404)
- **message** (string) - The error message indicating the resource was not found.
#### Response Example
{
"message": "HTTP 404 Not Found"
}
```
--------------------------------
### GET /
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/jetty.md
Attempts to access the root path of the Jetty server. It may return a problem message or server information.
```APIDOC
## GET /
### Description
Attempts to access the root path of the Jetty server. This endpoint can reveal if the server is running and potentially expose error messages or server details.
### Method
GET
### Endpoint
/
### Parameters
None
### Request Example
None
### Response
#### Success Response (200)
- **Server** (string) - The server software, e.g., "Jetty"
#### Error Response (e.g., 404)
- **message** (string) - A message indicating a problem accessing the resource, e.g., "Problem accessing /. Reason:"
### Response Example
```
Server: Jetty
```
OR
```
Problem accessing /. Reason:
```
```
--------------------------------
### Kiterunner Vanilla Bruteforcing
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
Example of performing a vanilla brute-force scan using Kiterunner. It utilizes a specified wordlist and options for concurrency, default depth, ignored lengths, and output formats.
```bash
kr brute https://target.com -A=raft-large-words -A=apiroutes-210228:20000 -x 10 -d=0 --ignore-length=34 -ejson,txt
```
--------------------------------
### Kiterunner Traditional Bruteforce Scanning (Bash)
Source: https://context7.com/assetnote/kiterunner/llms.txt
Illustrates how to use Kiterunner's `kr brute` command for traditional directory and file bruteforcing. Examples include using text wordlists, file extensions, Assetnote wordlists, and compatibility modes.
```bash
# Basic bruteforce with a text wordlist
kr brute https://target.com -w wordlist.txt -x 10 --ignore-length=34
# Bruteforce with file extensions
kr brute https://target.com -w wordlist.txt -x 10 -d=0 --ignore-length=34 -ejson,txt,xml,html
# Use Assetnote wordlists for bruteforcing
kr brute https://target.com -A=raft-large-words -A=apiroutes-210228:20000 -x 10 -d=0 --ignore-length=34 -ejson,txt
# Dirsearch compatibility mode (replaces %EXT% in wordlist)
kr brute https://target.com -w dirsearch.txt -x 10 -d=0 --ignore-length=34 -ejson,asp,aspx,ashx -D
# Bruteforce a specific subpath
kr brute https://target.com/subapp/ -A=aspx-210328:20000 -x 20 -j 1
# Read targets from stdin with extensions
cat hosts | kr brute - -w wordlist.txt -easpx,asmx,ashx,asp --dirsearch-compat
# Bruteforce with custom status code filtering
kr brute https://target.com -w wordlist.txt --success-status-codes 200,301,302,403 -x 10
```
--------------------------------
### Laravel Signature Detection
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/laravel.md
Endpoints and patterns used to identify Laravel framework installations.
```APIDOC
## GET /
### Description
Detects Laravel installations via default headers and error page content.
### Method
GET
### Endpoint
/
### Parameters
None
### Request Example
GET / HTTP/1.1
### Response
#### Success Response (200)
- **content** (string) - Contains "Environment & details:" or "Whoops, looks like something went wrong."
#### Response Example
{ "message": "Whoops, looks like something went wrong." }
## GET /thisshouldnotexist
### Description
Triggers a 404 Not Found page to identify Laravel specific error templates.
### Method
GET
### Endpoint
/thisshouldnotexist
### Response
#### Success Response (404)
- **content** (string) - Contains "Not Found" and references to "Nunito" font.
#### Response Example
{ "error": "Not Found" }
```
--------------------------------
### GET /
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/fastapi.md
Retrieves a 'Not Found' message, indicating the root endpoint is not a valid resource.
```APIDOC
## GET /
### Description
This endpoint is not a valid resource and will return a 'Not Found' error.
### Method
GET
### Endpoint
/
### Response
#### Success Response (404)
- **detail** (string) - Indicates that the requested resource was not found.
### Response Example
```json
{
"detail": "Not Found"
}
```
```
--------------------------------
### GET /thisshouldntexist
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/jetty.md
Attempts to access a non-existent path on the Jetty server, typically resulting in an error.
```APIDOC
## GET /thisshouldntexist
### Description
Attempts to access a non-existent path on the Jetty server. This endpoint is expected to return an error message indicating the resource could not be found.
### Method
GET
### Endpoint
/thisshouldntexist
### Parameters
None
### Request Example
None
### Response
#### Error Response (e.g., 404)
- **message** (string) - A message indicating a problem accessing the resource, e.g., "Problem accessing /thisshouldntexist. Reason:"
### Response Example
```
Problem accessing /thisshouldntexist. Reason:
```
```
--------------------------------
### GET /thisshouldntexist
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/fastapi.md
Attempts to access a non-existent endpoint, resulting in a 'Not Found' error.
```APIDOC
## GET /thisshouldntexist
### Description
This endpoint does not exist and will return a 'Not Found' error.
### Method
GET
### Endpoint
/thisshouldntexist
### Response
#### Success Response (404)
- **detail** (string) - Indicates that the requested resource was not found.
### Response Example
```json
{
"detail": "Not Found"
}
```
```
--------------------------------
### GET /
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/tomcat.md
Attempts to access the root path of a Tomcat server. Typically returns a 404 Not Found error if the root path is not explicitly handled.
```APIDOC
## GET /
### Description
Attempts to access the root path of a Tomcat server. This endpoint is often used to check if a server is running, though it may return a 404.
### Method
GET
### Endpoint
/
### Parameters
None
### Request Example
None
### Response
#### Success Response (200)
None
#### Error Response (404)
- **title** (string) - "HTTP Status 404 – Not Found"
#### Response Example
```html
HTTP Status 404 – Not Found
```
```
--------------------------------
### GET / - Powered By Loopback
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/loopback.md
This endpoint returns an image indicating the service is powered by Loopback.
```APIDOC
## GET /
### Description
This endpoint returns an image indicating the service is powered by Loopback.
### Method
GET
### Endpoint
/
### Parameters
None
### Request Example
None
### Response
#### Success Response (200)
- **image** (string) - The filename of the 'powered-by-loopback-sm.png' image.
#### Response Example
```
powered-by-loopback-sm.png
```
```
--------------------------------
### GET /thisshouldnotexist
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/nest.md
Attempts to access a non-existent endpoint. This request is expected to result in a 404 Not Found error.
```APIDOC
## GET /thisshouldnotexist
### Description
Attempts to access a non-existent endpoint. This request is expected to return a 404 Not Found error.
### Method
GET
### Endpoint
/thisshouldnotexist
### Parameters
None
### Request Example
None
### Response
#### Error Response (404)
- **statusCode** (integer) - The HTTP status code, expected to be 404.
- **message** (string) - A message indicating the resource was not found.
- **error** (string) - The type of error, expected to be "Not Found".
#### Response Example
```json
{
"statusCode": 404,
"message": "Cannot GET /thisshouldnotexist",
"error": "Not Found"
}
```
```
--------------------------------
### http.Target - Target Configuration
Source: https://context7.com/assetnote/kiterunner/llms.txt
The Target type encapsulates connection details for a scan target including hostname, port, TLS settings, and custom headers. This example shows how to create, configure, and use a Target for making HTTP requests.
```APIDOC
## http.Target - Target Configuration
### Description
The Target type encapsulates connection details for a scan target including hostname, port, TLS settings, and custom headers.
### Method
N/A (This is a type definition and usage example)
### Endpoint
N/A
### Parameters
N/A
### Request Example
```go
package main
import (
"context"
"fmt"
"time"
"github.com/assetnote/kiterunner/pkg/http"
)
func main() {
// Create target using pool (recommended for high-volume scanning)
target := http.AcquireTarget()
defer http.ReleaseTarget(target)
// Configure target properties
target.Hostname = "api.example.com"
target.Port = 443
target.IsTLS = true
target.BasePath = "/v2" // Prepended to all request paths
// Add custom headers
target.Headers = []http.Header{
{Key: []byte("Authorization"), Value: []byte("Bearer eyJhbGciOiJIUzI1NiIs...")},
{Key: []byte("X-API-Key"), Value: []byte("abc123")},
{Key: []byte("Accept"), Value: []byte("application/json")},
}
// Set context for cancellation support
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
target.SetContext(ctx)
// Parse host header (required before using target)
target.ParseHostHeader()
// Get HTTP client configured for this target
client := target.HTTPClient(5, 3*time.Second) // maxConns, timeout
// Create and execute a request
route := &http.Route{
Path: []byte("/users"),
Method: http.GET,
Query: []byte("limit=100&offset=0"),
}
req := http.Request{
Target: target,
Route: route,
}
config := &http.Config{
Timeout: 3 * time.Second,
MaxRedirects: 3,
ReadBody: true,
ReadHeaders: true,
}
resp, err := http.DoClient(client, req, config)
if err != nil {
fmt.Printf("Request failed: %v\n", err)
return
}
fmt.Printf("Response: %d - %d bytes\n", resp.StatusCode, resp.BodyLength)
fmt.Printf("Target URL: %s\n", target.String()) // https://api.example.com:443/v2
// Check quarantine status (for wildcard detection)
if target.Quarantined() {
fmt.Println("Target was quarantined due to excessive matches")
}
}
```
### Response
N/A (This is a usage example)
```
--------------------------------
### kiterunner.Engine - Core Scanning Engine
Source: https://context7.com/assetnote/kiterunner/llms.txt
The Engine type provides the primary interface for programmatic scanning, supporting both synchronous and asynchronous operation modes. This example demonstrates setting up routes, configuring the engine, and running an asynchronous scan.
```APIDOC
## kiterunner.Engine - Core Scanning Engine
### Description
The Engine type provides the primary interface for programmatic scanning, supporting both synchronous and asynchronous operation modes.
### Method
N/A (This is a type definition and usage example)
### Endpoint
N/A
### Parameters
N/A
### Request Example
```go
package main
import (
"context"
"fmt"
"time"
"github.com/assetnote/kiterunner/pkg/http"
"github.com/assetnote/kiterunner/pkg/kiterunner"
"github.com/assetnote/kiterunner/pkg/proute"
)
func main() {
// Define routes to scan
routes := http.RouteMap{
"/api": []*http.Route{
{Path: []byte("/api/v1/users"), Method: http.GET},
{Path: []byte("/api/v1/items"), Method: http.GET},
{Path: []byte("/api/v1/orders"), Method: http.POST},
},
"/admin": []*http.Route{
{Path: []byte("/admin/config"), Method: http.GET},
{Path: []byte("/admin/users"), Method: http.GET},
},
}
// Create engine with configuration options
engine := kiterunner.NewEngine(routes,
kiterunner.MaxParallelHosts(50),
kiterunner.MaxConnPerHost(5),
kiterunner.MaxTimeout(3*time.Second),
kiterunner.MaxRedirects(3),
kiterunner.TargetQuarantineThreshold(10),
kiterunner.WildcardDetection(true),
)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
// Start async scanning - returns input and output channels
tx, rx, err := engine.RunAsync(ctx)
if err != nil {
panic(fmt.Sprintf("failed to start engine: %v", err))
}
// Send targets to scan
go func() {
targets := []struct {
hostname string
port int
tls bool
}{
{"api.target.com", 443, true},
{"internal.target.com", 8080, false},
}
for _, t := range targets {
target := http.AcquireTarget()
target.Hostname = t.hostname
target.Port = t.port
target.IsTLS = t.tls
target.SetContext(ctx)
tx <- target
}
close(tx) // Signal no more targets
}()
// Process results
for result := range rx {
fmt.Printf("Found: %s %s - Status: %d, Length: %d\n",
result.Route.Method,
result.Route.Path,
result.Response.StatusCode,
result.Response.BodyLength,
)
result.Release() // Return to pool
}
}
```
### Response
N/A (This is a usage example)
```
--------------------------------
### GET / (404 Not Found)
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/nginx.md
This endpoint represents a 404 Not Found response when accessing the root path of the Nginx server.
```APIDOC
## GET /
### Description
Returns a 404 Not Found error when accessing the root path.
### Method
GET
### Endpoint
/
### Response
#### Success Response (404)
- **body** (string) - HTML content indicating a 404 Not Found error.
### Response Example
```html
404 Not Found
```
```
--------------------------------
### GET /thisdoesntexist
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/tomcat.md
Attempts to access a non-existent path on a Tomcat server. This is expected to return a 404 Not Found error.
```APIDOC
## GET /thisdoesntexist
### Description
Attempts to access a path that does not exist on the Tomcat server. This is a common test to verify the server's error handling for invalid routes.
### Method
GET
### Endpoint
/thisdoesntexist
### Parameters
None
### Request Example
None
### Response
#### Success Response (200)
None
#### Error Response (404)
- **title** (string) - "HTTP Status 404 – Not Found"
#### Response Example
```html
HTTP Status 404 – Not Found
```
```
--------------------------------
### GET /
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/spring-boot.md
Retrieves the root endpoint of the Spring Boot application, often returning a default error message or Whitelabel Error Page.
```APIDOC
## GET /
### Description
Accesses the root path of the application to check for default Spring Boot error handling or index responses.
### Method
GET
### Endpoint
/
### Response
#### Success Response (200)
- **message** (string) - The error message returned by the server.
- **path** (string) - The path requested.
#### Response Example
{
"message": "No message available",
"path": "/"
}
```
--------------------------------
### GET /profile
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/spring-boot.md
Attempts to access the profile endpoint, which is often used in Spring Boot applications to expose configuration or link information.
```APIDOC
## GET /profile
### Description
Checks for the existence of the profile endpoint, which may return HATEOAS links or configuration metadata.
### Method
GET
### Endpoint
/profile
### Response
#### Success Response (200)
- **_links** (object) - A collection of HATEOAS links associated with the profile.
#### Response Example
{
"_links": {
"self": {
"href": "http://example.com/profile"
}
}
}
```
--------------------------------
### Run Async Scan with Kiterunner Engine
Source: https://context7.com/assetnote/kiterunner/llms.txt
Demonstrates how to initialize and run the Kiterunner Engine in asynchronous mode. It shows setting up routes, configuring engine options, sending targets via a channel, and processing scan results. Dependencies include the kiterunner and http packages.
```go
package main
import (
"context"
"fmt"
"time"
"github.com/assetnote/kiterunner/pkg/http"
"github.com/assetnote/kiterunner/pkg/kiterunner"
"github.com/assetnote/kiterunner/pkg/proute"
)
func main() {
// Define routes to scan
routes := http.RouteMap{
"/api": []*http.Route{
{Path: []byte("/api/v1/users"), Method: http.GET},
{Path: []byte("/api/v1/items"), Method: http.GET},
{Path: []byte("/api/v1/orders"), Method: http.POST},
},
"/admin": []*http.Route{
{Path: []byte("/admin/config"), Method: http.GET},
{Path: []byte("/admin/users"), Method: http.GET},
},
}
// Create engine with configuration options
engine := kiterunner.NewEngine(routes,
kiterunner.MaxParallelHosts(50),
kiterunner.MaxConnPerHost(5),
kiterunner.MaxTimeout(3*time.Second),
kiterunner.MaxRedirects(3),
kiterunner.TargetQuarantineThreshold(10),
kiterunner.WildcardDetection(true),
)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
// Start async scanning - returns input and output channels
tx, rx, err := engine.RunAsync(ctx)
if err != nil {
panic(fmt.Sprintf("failed to start engine: %v", err))
}
// Send targets to scan
go func() {
targets := []struct {
hostname string
port int
tls bool
}{
{"api.target.com", 443, true},
{"internal.target.com", 8080, false},
}
for _, t := range targets {
target := http.AcquireTarget()
target.Hostname = t.hostname
target.Port = t.port
target.IsTLS = t.tls
target.SetContext(ctx)
tx <- target
}
close(tx) // Signal no more targets
}()
// Process results
for result := range rx {
fmt.Printf("Found: %s %s - Status: %d, Length: %d\n",
result.Route.Method,
result.Route.Path,
result.Response.StatusCode,
result.Response.BodyLength,
)
result.Release() // Return to pool
}
}
```
--------------------------------
### Build Kiterunner from Source and Compile Wordlists (Bash)
Source: https://context7.com/assetnote/kiterunner/llms.txt
Instructions for cloning the Kiterunner repository, building the binary, and compiling wordlists from JSON to the .kite format for API scanning. It also shows how to download pre-compiled .kite files.
```bash
git clone https://github.com/assetnote/kiterunner.git
cd kiterunner
make build
ln -s $(pwd)/dist/kr /usr/local/bin/kr
wget https://wordlists-cdn.assetnote.io/rawdata/kiterunner/routes-small.json.tar.gz
tar -xzf routes-small.json.tar.gz
kr kb compile routes-small.json routes.kite
wget https://wordlists-cdn.assetnote.io/data/kiterunner/routes-small.kite.tar.gz
tar -xzf routes-small.kite.tar.gz
```
--------------------------------
### Define Parameterized API Routes in Go
Source: https://context7.com/assetnote/kiterunner/llms.txt
This snippet demonstrates how to initialize an API definition using proute, configure global headers and query parameters, and define specific routes with dynamic path, query, and body crumbs. It concludes by converting the definition into executable HTTP routes and performing a debug print.
```go
package main
import (
"fmt"
"github.com/assetnote/kiterunner/pkg/http"
"github.com/assetnote/kiterunner/pkg/proute"
)
func main() {
api := proute.NewAPI("", "https://api.example.com")
api.HeaderCrumbs = []proute.Crumb{
&proute.StaticCrumb{K: "Content-Type", V: "application/json"},
&proute.StaticCrumb{K: "Accept", V: "application/json"},
}
api.QueryCrumbs = []proute.Crumb{
&proute.StaticCrumb{K: "api_version", V: "v2"},
}
api.Routes = []proute.Route{
{
Method: http.GET,
PathCrumbs: []proute.Crumb{
&proute.StaticCrumb{V: "/users"},
},
QueryCrumbs: []proute.Crumb{
&proute.IntCrumb{K: "limit"},
&proute.IntCrumb{K: "offset"},
&proute.StaticCrumb{K: "sort", V: "created_at"},
},
},
{
Method: http.POST,
PathCrumbs: []proute.Crumb{
&proute.StaticCrumb{V: "/users"},
},
BodyCrumbs: []proute.Crumb{
&proute.StringCrumb{K: "name"},
&proute.StringCrumb{K: "email"},
&proute.UUIDCrumb{K: "tenant_id"},
},
HeaderCrumbs: []proute.Crumb{
&proute.StaticCrumb{K: "X-Request-ID", V: ""},
},
},
{
Method: http.GET,
PathCrumbs: []proute.Crumb{
&proute.StaticCrumb{V: "/users/"},
&proute.UUIDCrumb{},
},
},
}
httpRoutes := api.ToHTTPRoutes()
for _, route := range httpRoutes {
fmt.Printf("%s %s?%s\n", route.Method, route.Path, route.Query)
}
apis := proute.APIS{api}
limited := apis.First(100)
fmt.Printf("Limited to %d APIs\n", len(limited))
api.DebugPrint()
}
```
--------------------------------
### Build and Compile Kiterunner Wordlists (Bash)
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
This snippet demonstrates how to build the Kiterunner binary from source, compile JSON wordlists into the Kiterunner's native '.kite' format, and then use the compiled wordlist for scanning hosts.
```bash
make build
ln -s $(pwd)/dist/kr /usr/local/bin/kr
kr kb compile routes.json routes.kite
kr scan hosts.txt -w routes.kite -x 20 -j 100 --ignore-length=1053
```
--------------------------------
### Configure Kiterunner Engine Programmatically in Go
Source: https://context7.com/assetnote/kiterunner/llms.txt
Demonstrates how to initialize and customize the Kiterunner engine using both direct struct configuration and functional options. It includes setting concurrency limits, HTTP timeouts, and implementing custom request validators.
```go
package main
import (
"fmt"
"time"
"github.com/assetnote/kiterunner/pkg/http"
"github.com/assetnote/kiterunner/pkg/kiterunner"
)
type CustomValidator struct {
blockedPaths []string
}
func (v *CustomValidator) Validate(resp http.Response, wcr kiterunner.WildcardResponses, config *kiterunner.Config) error {
if resp.StatusCode == 500 {
return fmt.Errorf("server error responses blocked")
}
return nil
}
func main() {
config := kiterunner.NewDefaultConfig()
config.MaxParallelHosts = 100
config.MaxConnPerHost = 10
config.QuarantineThreshold = 15
config.WildcardDetection = true
config.Delay = 100 * time.Millisecond
config.HTTP.Timeout = 5 * time.Second
config.RequestValidators = append(config.RequestValidators, &CustomValidator{blockedPaths: []string{"/health", "/status"}})
routes := http.RouteMap{}
engine := kiterunner.NewEngine(routes,
kiterunner.MaxParallelHosts(100),
kiterunner.MaxConnPerHost(10),
kiterunner.MaxTimeout(5*time.Second),
)
}
```
--------------------------------
### GET /api/v2.0/pinga
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/kestrel.md
This endpoint is used to check the status or health of the Kestrel service.
```APIDOC
## GET /api/v2.0/pinga
### Description
Checks the health status of the Kestrel service.
### Method
GET
### Endpoint
/api/v2.0/pinga
### Response
#### Success Response (200)
- **message** (string) - Indicates the service is operational.
#### Response Example
```json
{
"message": "pong"
}
```
#### Error Response (404)
- **error** (string) - Indicates the resource was not found.
#### Response Example
```json
{
"error": "Not Found"
}
```
```
--------------------------------
### Configure and Use http.Target for Scans
Source: https://context7.com/assetnote/kiterunner/llms.txt
Illustrates how to configure a scan target using the http.Target type, including setting hostname, port, TLS, base path, and custom headers. It also shows how to create an HTTP client, make a request, and check target quarantine status. This utilizes the http package.
```go
package main
import (
"context"
"fmt"
"time"
"github.com/assetnote/kiterunner/pkg/http"
)
func main() {
// Create target using pool (recommended for high-volume scanning)
target := http.AcquireTarget()
defer http.ReleaseTarget(target)
// Configure target properties
target.Hostname = "api.example.com"
target.Port = 443
target.IsTLS = true
target.BasePath = "/v2" // Prepended to all request paths
// Add custom headers
target.Headers = []http.Header{
{Key: []byte("Authorization"), Value: []byte("Bearer eyJhbGciOiJIUzI1NiIs...")},
{Key: []byte("X-API-Key"), Value: []byte("abc123")},
{Key: []byte("Accept"), Value: []byte("application/json")},
}
// Set context for cancellation support
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
target.SetContext(ctx)
// Parse host header (required before using target)
target.ParseHostHeader()
// Get HTTP client configured for this target
client := target.HTTPClient(5, 3*time.Second) // maxConns, timeout
// Create and execute a request
route := &http.Route{
Path: []byte("/users"),
Method: http.GET,
Query: []byte("limit=100&offset=0"),
}
req := http.Request{
Target: target,
Route: route,
}
config := &http.Config{
Timeout: 3 * time.Second,
MaxRedirects: 3,
ReadBody: true,
ReadHeaders: true,
}
resp, err := http.DoClient(client, req, config)
if err != nil {
fmt.Printf("Request failed: %v\n", err)
return
}
fmt.Printf("Response: %d - %d bytes\n", resp.StatusCode, resp.BodyLength)
fmt.Printf("Target URL: %s\n", target.String()) // https://api.example.com:443/v2
// Check quarantine status (for wildcard detection)
if target.Quarantined() {
fmt.Println("Target was quarantined due to excessive matches")
}
}
```
--------------------------------
### Kiterunner API Scanning with Target List File
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
Demonstrates how to initiate an API scan using a file containing a list of targets. Kiterunner reads each line from the specified file as a target for the scan.
```bash
kr scan targets.txt -w routes.kite -A=apiroutes-210228:20000 -x 10 --ignore-length=34
```
--------------------------------
### List Available Assetnote Wordlists
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
Command to display all available Assetnote wordlists, including their aliases, filenames, source, count, and cache status.
```bash
kr wordlist list
```
--------------------------------
### Kiterunner CLI Help - Scan Command
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
Displays the help information for the 'kite scan' command, outlining its usage, available flags, and global options. This includes parameters for assetnote wordlists, blacklisted domains, request delays, and more.
```bash
Usage:
kite scan [flags]
Flags:
-A, --assetnote-wordlist strings use the wordlists from wordlist.assetnote.io. specify the type/name to use, e.g. apiroutes-210228. You can specify an additional maxlength to use only the first N values in the wordlist, e.g. apiroutes-210228;20000 will only use the first 20000 lines in that wordlist
--blacklist-domain strings domains that are blacklisted for redirects. We will not follow redirects to these domains
--delay duration delay to place inbetween requests to a single host
--disable-precheck whether to skip host discovery
--fail-status-codes ints which status codes blacklist as fail. if this is set, this will override success-status-codes
--filter-api strings only scan apis matching this ksuid
--force-method string whether to ignore the methods specified in the ogl file and force this method
-H, --header strings headers to add to requests (default [x-forwarded-for: 127.0.0.1])
-h, --help help for scan
--ignore-length strings a range of content length bytes to ignore. you can have multiple. e.g. 100-105 or 1234 or 123,34-53. This is inclusive on both ends
--kitebuilder-full-scan perform a full scan without first performing a phase scan.
-w, --kitebuilder-list strings ogl wordlist to use for scanning
-x, --max-connection-per-host int max connections to a single host (default 3)
-j, --max-parallel-hosts int max number of concurrent hosts to scan at once (default 50)
--max-redirects int maximum number of redirects to follow (default 3)
-d, --preflight-depth int when performing preflight checks, what directory depth do we attempt to check. 0 means that only the docroot is checked (default 1)
--profile-name string name for profile output file
--progress a progress bar while scanning. by default enabled only on Stderr (default true)
--quarantine-threshold int if the host return N consecutive hits, we quarantine the host as wildcard. Set to 0 to disable (default 10)
--success-status-codes ints which status codes whitelist as success. this is the default mode
-t, --timeout duration timeout to use on all requests (default 3s)
--user-agent string user agent to use for requests (default "Chrome. Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36")
--wildcard-detection can be set to false to disable wildcard redirect detection (default true)
Global Flags:
--config string config file (default is $HOME/.kiterunner.yaml)
-o, --output string output format. can be json,text,pretty (default "pretty")
-q, --quiet quiet mode. will mute unecessarry pretty text
-v, --verbose string level of logging verbosity. can be error,info,debug,trace (default "info")
```
--------------------------------
### Kiterunner Dirsearch Bruteforcing with Extension Substitution
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
Shows how to use Kiterunner for Dirsearch-style bruteforcing, specifically when the wordlist contains '%EXT%' placeholders for file extensions. The '-D' flag enables this substitution.
```bash
kr brute https://target.com -w dirsearch.txt -x 10 -d=0 --ignore-length=34 -ejson,txt -D
```
--------------------------------
### Apply Head Syntax to Limit Wordlist Lines
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
Demonstrates how to use the : syntax to restrict the number of lines processed from a specific wordlist.
```bash
# this will use the first 20000 lines in the api routes wordlist
kr scan targets.txt -A=apiroutes-210228:20000 -x 10 --ignore-length=34
# this will use the first 10 lines in the aspx wordlist
kr brute targets.txt -A=aspx-210228:10 -x 10 --ignore-length=34 -easp,aspx
```
--------------------------------
### GET / (403 Forbidden)
Source: https://github.com/assetnote/kiterunner/blob/main/api-signatures/nginx.md
This endpoint represents a 403 Forbidden response when accessing the root path of the Nginx server.
```APIDOC
## GET /
### Description
Returns a 403 Forbidden error when accessing the root path.
### Method
GET
### Endpoint
/
### Response
#### Success Response (403)
- **body** (string) - HTML content indicating a 403 Forbidden error.
### Response Example
```html
403 Forbidden
```
```
--------------------------------
### Kiterunner API Scanning with HTTP and HTTPS
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
Illustrates scanning a single target domain, attempting both HTTP and HTTPS protocols. This is useful when the protocol is not explicitly known or needs to be tested for both cases.
```bash
kr scan target.com -w routes.kite -A=apiroutes-210228:20000 -x 10 --ignore-length=34
```
--------------------------------
### Replay Request with Kiterunner CLI
Source: https://github.com/assetnote/kiterunner/blob/main/readme.md
Replays a captured HTTP request using the `kb replay` command. This command reconstructs the request from wordlists and can forward it through a specified proxy for inspection. The Go net/http client may alter the request slightly.
```bash
❯ go run ./cmd/kiterunner kb replay -q --proxy=http://localhost:8080 -w routes.kite "POST 403 [ 287, 10, 1] https://target.com/dedalo/lib/dedalo/publication/server_api/v1/json/thesaurus_parents 0cc39f76702ea287ec3e93f4b4710db9c8a86251"
11:25AM INF Raw reconstructed request
POST /dedalo/lib/dedalo/publication/server_api/v1/json/thesaurus_parents?ar_fields=48637466&code=66132381&db_name=08791392&lang=lg-eng&recursive=false&term_id=72336471 HTTP/1.1
Content-Type: any
11:25AM INF Outbound request
POST /dedalo/lib/dedalo/publication/server_api/v1/json/thesaurus_parents?ar_fields=48637466&code=66132381&db_name=08791392&lang=lg-eng&recursive=false&term_id=72336471 HTTP/1.1
Host: target.com
User-Agent: Go-http-client/1.1
Content-Length: 0
Content-Type: any
Accept-Encoding: gzip
11:25AM INF Response After Redirects
HTTP/1.1 403 Forbidden
Connection: close
Content-Length: 45
Content-Type: application/json
Date: Wed, 07 Apr 2021 01:25:28 GMT
X-Amzn-Requestid: 7e6b2ea1-c662-4671-9eaa-e8cd31b463f2
User is not authorized to perform this action
```
--------------------------------
### Kiterunner API Endpoint Scanning (Bash)
Source: https://context7.com/assetnote/kiterunner/llms.txt
Demonstrates various ways to perform API endpoint scanning using Kiterunner's `kr scan` command. It covers scanning single targets, multiple targets from a file, using Assetnote wordlists, combining local and Assetnote wordlists, custom headers, timeouts, and different scanning modes.
```bash
# Scan a single target with a compiled kite wordlist
kr scan https://target.com:8443/ -w routes.kite -x 10 --ignore-length=34
# Scan multiple targets from a file
kr scan hosts.txt -w routes.kite -x 10 -j 100 --ignore-length=34
# Scan using Assetnote wordlists (auto-downloaded and cached)
kr scan hosts.txt -A=apiroutes-210328:20000 -x 5 -j 100 --fail-status-codes 400,401,404,403,501,502,426,411
# Combine local wordlist with Assetnote wordlists
kr scan target.com -w routes.kite -A=apiroutes-210328:20000 -x 20 -j 1 --fail-status-codes 400,401,404,403,501,502,426,411
# Scan with custom headers and timeout
kr scan https://api.target.com -w routes.kite -x 5 -t 5s -H "Authorization: Bearer token123" -H "X-Custom-Header: value"
# Full scan without phase optimization (more thorough but slower)
kr scan target.com -w routes.kite --kitebuilder-full-scan -x 10
# Disable wildcard detection for specific cases
kr scan target.com -w routes.kite --wildcard-detection=false -x 10
# Scan with depth-based preflight checks (for virtual path routing)
kr scan target.com -w routes.kite -d 2 -x 10
# Read targets from stdin
cat hosts.txt | kr scan - -w routes.kite -x 5 -j 50
```