MCPcopy
hub / github.com/assetnote/kiterunner

github.com/assetnote/kiterunner @v1.0.2 sqlite

repository ↗ · DeepWiki ↗ · release v1.0.2 ↗
1,070 symbols 2,681 edges 89 files 167 documented · 16%
README

Kiterunner

GoDoc GitHub release Go Report Card

Introduction

For the longest of times, content discovery has been focused on finding files and folders. While this approach is effective for legacy web servers that host static files or respond with 3xx’s upon a partial path, it is no longer effective for modern web applications, specifically APIs.

Over time, we have seen a lot of time invested in making content discovery tools faster so that larger wordlists can be used, however the art of content discovery has not been innovated upon.

Kiterunner is a tool that is capable of not only performing traditional content discovery at lightning fast speeds, but also bruteforcing routes/endpoints in modern applications.

Modern application frameworks such as Flask, Rails, Express, Django and others follow the paradigm of explicitly defining routes which expect certain HTTP methods, headers, parameters and values.

When using traditional content discovery tooling, such routes are often missed and cannot easily be discovered.

By collating a dataset of Swagger specifications and condensing it into our own schema, Kiterunner can use this dataset to bruteforce API endpoints by sending the correct HTTP method, headers, path, parameters and values for each request it sends.

Swagger files were collected from a number of datasources, including an internet wide scan for the 40+ most common swagger paths. Other datasources included GitHub via BigQuery, and APIs.guru.

Contents

Installation

Downloading a release

You can download a pre-built copy from https://github.com/assetnote/kiterunner/releases.

Building from source

# build the binary
make build

# symlink your binary
ln -s $(pwd)/dist/kr /usr/local/bin/kr

# compile the wordlist
# kr kb compile <input.json> <output.kite>
kr kb compile routes.json routes.kite

# scan away
kr scan hosts.txt -w routes.kite -x 20 -j 100 --ignore-length=1053

The JSON datasets can be found below:

Alternatively, it is possible to download the compile .kite files from the links below:

Usage

Quick Start

kr [scan|brute] <input> [flags]
  • <input> can be a file, a domain, or URI. we'll figure it out for you. See Input/Host Formatting for more details
# Just have a list of hosts and no wordlist
kr scan hosts.txt -A=apiroutes-210328:20000 -x 5 -j 100 --fail-status-codes 400,401,404,403,501,502,426,411

# You have your own wordlist but you want assetnote wordlists too
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

# Bruteforce like normal but with the first 20000 words
kr brute https://target.com/subapp/ -A=aspx-210328:20000 -x 20 -j 1

# Use a dirsearch style wordlist with %EXT%
kr brute https://target.com/subapp/ -w dirsearch.txt -x 20 -j 1 -exml,asp,aspx,ashx -D

CLI Help

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")

bruteforce flags (all the flags above +)

  -D, --dirsearch-compat              this will replace %EXT% with the extensions provided. backwards compat with dirsearch because shubs loves him some dirsearch
  -e, --extensions strings            extensions to append while scanning
  -w, --wordlist strings              normal wordlist to use for scanning

Input/Host Formatting

When supplied with an input, kiterunner will attempt to resolve the input in the following order: 1. Is the input a file. If so read all the lines in the file as separate domains 2. The input is treated as a "domain"

If you supply a "domain", but it exists as a file, e.g. google.com but google.com is also a txt file in the current directory, we'll load google.com the text file, because we found it first.

Domain Parsing

Its preferred that you provide a full URI as the input, however you can provide incomplete URIs and we'll try and guess what you mean. An example list of domains you can supply are:

one.com
two.com:80
three.com:443
four.com:9447
https://five.com:9090
http://six.com:80/api

The above list of domains will expand into the subsequent list of targets

(two targets are created for one.com, since neither port nor protocol was specified)
http://one.com (port 80 implied)
https://one.com (port 443 implied)

http://two.com (port 80 implied)
https://three.com (port 443 implied)
http://four.com:9447 (non-tls port guessed)
https://five.com:9090
http://six.com/api (port 80 implied; basepath API appended)

the rules we apply are: - if you supply a scheme, we use the scheme. - We only support http & https - if you don't supply a scheme, we'll guess based on the port - if you supply a port, we'll use the port - If your port is 443, or 8443, we'll assume its tls - if you don't supply a port, we'll guess both port 80, 443 - if you supply a path, we'll prepend that path to all requests against that host

API Scanning

When you have a single target

# single target
kr scan https://target.com:8443/ -w routes.kite -A=apiroutes-210228:20000 -x 10 --ignore-length=34

# single target, but you want to try http and https
kr scan target.com -w routes.kite -A=apiroutes-210228:20000 -x 10 --ignore-length=34

# a list of targets
kr scan targets.txt -w routes.kite -A=apiroutes-210228:20000 -x 10 --ignore-length=34

Vanilla Bruteforcing

kr brute https://target.com -A=raft-large-words -A=apiroutes-210228:20000 -x 10 -d=0 --ignore-length=34 -ejson,txt

Dirsearch Bruteforcing

For when you have an old-school wordlist that still has %EXT% in the wordlist, you can use -D. this will only substitute the extension where %EXT% is present in the path

kr brute https://target.com -w dirsearch.txt -x 10 -d=0 --ignore-length=34 -ejson,txt -D

Technical Features

Depth Scanning

A key feature of kiterunner is depth based scanning. This attempts to handle detecting wildcards given virtual application path based routing. The depth defines how many directories deep the baseline checks are performed E.g.

~/kiterunner $ cat wordlist.txt

/api/v1/user/create
/api/v1/user/delete
/api/v2/user/
/api/v2/admin/
/secrets/v1/
/secrets/v2/
  • At depth 0, only / would have the baseline checks performed for wildcard detection
  • At depth 1, /api and /secrets would have baseline checks performed; and these checks would be used against /api and /secrets correspondingly
  • At depth 2, /api/v1, /api/v2, /secrets/v1 and /secrets/v2 would all have baseline checks performed.

By default, kr scan has a depth of 1, since from internal usage, we've often seen this as the most common depth where virtual routing has occured. kr brute has a default depth of 0, as you typically don't want this check to be performed with a static wordlist.

Naturally, increasing the depth will increase the accuracy of your scans, however this also increases the number of requests to the target. (# of baseline checks * # of depth baseline directories). Hence, we recommend against going above 1, and in rare cases going to depth 2.

Using Assetnote Wordlists

We provide inbuilt downloading and caching of wordlists from assetnote.io. You can use these with the -A flag which receives a comma delimited list of aliases, or fullnames.

You can get a full list of all the Assetnote wordlists with kr wordlist list.

The wordlists when used, are cached in ~/.cache/kiterunner/wordlists. When used, these are compiled from .txt -> .kite

``` +-----------------------------------+-------------------------------------------------------+----------------+---------+----------+--------+ | ALIAS | FILENAME | SOURCE | COUNT | FILESIZE | CACHED | +-----------------------------------+-------------------------------------------------------+----------------+---------+----------+--------+ | 2m-subdomains | 2m-subdomains.txt | manual.json | 2167059 | 28.0mb | false | | asp_lowercase | asp_lowercase.txt | manual.json | 24074 | 1.1mb | false | | aspx_lowercase | aspx_lowercase.txt | manual.json | 80293 | 4.4mb | false | | bak | bak.txt | manual.json | 31725 | 634.8kb | false | | best-dns-wordlist | best-dns-wordlist.txt | manual.json | 9996122 | 139.0mb | false | | cfm | cfm.txt | manual.json | 12100 | 260.3kb | true | | do | do.txt | manual.json | 173152 | 4.8mb | false | | dot_filenames | dot_

Extension points exported contracts — how you extend this code

RequestValidator (Interface)
RequestValidator is an interface that lets you add custom validators for what are good and bad responses [8 implementers]
pkg/kiterunner/validator.go
Crumb (Interface)
Crumb is a piece of a route, can be dynamically rendered or not [11 implementers]
pkg/proute/crumb.go
Typer (Interface)
Typer provides an interface that makes parameter and schema generic. It provides a list of fields that allow both to be [2 …
pkg/kitebuilder/schema.go
ListOption (FuncType)
(no doc)
internal/wordlist/list.go
ScanOption (FuncType)
(no doc)
internal/scan/options.go
ScanOption (FuncType)
(no doc)
internal/kitebuilder/parse.go
ProgressBar (Interface)
(no doc) [2 implementers]
pkg/kiterunner/config.go
UnwrapCrumber (Interface)
(no doc) [11 implementers]
pkg/proute/proute.pbext.go

Core symbols most depended-on inside this repo

Run
called by 46
pkg/kiterunner/kiterunner_wrappers.go
String
called by 39
pkg/http/range.go
Fatal
called by 33
pkg/http/client_benchmark_test.go
Bytes
called by 32
pkg/http/field.go
Value
called by 22
pkg/proute/crumb.go
Key
called by 20
pkg/proute/crumb.go
ParseHostHeader
called by 18
pkg/http/target.go
Write
called by 17
pkg/http/target.go

Shape

Method 627
Function 317
Struct 92
TypeAlias 20
Interface 8
FuncType 6

Languages

Go100%

Modules by API surface

pkg/proute/proute.pb.go412 symbols
pkg/proute/crumb.go73 symbols
pkg/kitebuilder/schema.go53 symbols
internal/scan/options.go34 symbols
pkg/kiterunner/config.go27 symbols
pkg/proute/proute.pbext.go26 symbols
pkg/http/target.go26 symbols
benchmark/concurrency_test.go21 symbols
pkg/kiterunner/result.go20 symbols
pkg/kiterunner/validator.go18 symbols
pkg/kiterunner/preflight.go18 symbols
pkg/http/target_test.go15 symbols

Dependencies from manifests, versioned

github.com/beevik/etreev1.1.0 · 1×
github.com/davecgh/go-spewv1.1.1 · 1×
github.com/dustin/go-humanizev1.0.0 · 1×
github.com/fasthttp/routerv1.3.6 · 1×
github.com/francoispqt/gojayv1.2.13 · 1×
github.com/hashicorp/go-multierrorv1.0.0 · 1×
github.com/lucasjones/reggenv0.0.0-2020090414413 · 1×
github.com/manifoldco/promptuiv0.8.0 · 1×
github.com/mattn/go-colorablev0.1.2 · 1×
github.com/mitchellh/go-homedirv1.1.0 · 1×

For agents

$ claude mcp add kiterunner \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact