[
](#kiterunner)猎手(Kiterunner
[
](#introduction)简介
长期以来,内容发现一直专注于寻找文件和文件夹。虽然这种方法对承载静态文件的传统网络服务器是有效的,或者在部分路径上以3xx响应,但它对现代网络应用,特别是API不再有效。
随着时间的推移,我们已经看到在使内容发现工具变得更快方面投入了大量的时间,以便可以使用更大的词表,然而内容发现的艺术并没有得到创新。
Kiterunner是一个工具,它不仅能够以闪电般的速度进行传统的内容发现,而且还能够在现代应用中对路由/端点进行暴力破解。
现代应用框架,如Flask、Rails、Express、Django和其他框架,都遵循明确定义路由的范式,期望有特定的HTTP方法、标头、参数和值。
当使用传统的内容发现工具时,这样的路由往往被遗漏,而且不容易被发现。
通过整理Swagger规范的数据集,并将其浓缩到我们自己的模式中,Kiterunner可以使用这个数据集,通过为每个请求发送正确的HTTP方法、头信息、路径、参数和值,来破解API端点。
Swagger文件是从一些数据源收集的,包括在互联网上扫描40多个最常见的Swagger路径。其他数据源包括通过BigQuery的GitHub,以及APIs.guru。
[
](#contents)内容
[
](#installation)安装
[
](#downloading-a-release)下载一个版本
你可以从github.com/assetnote/k…,下载一个预构建的副本。
[
](#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
JSON数据集可以在下面找到。
- routes-large.json(118MB压缩,2.6GB解压)
- routes-small.json(14MB压缩,228MB解压)
另外,也可以从下面的链接中下载编译的.kite 文件。
- routes-large.kite(40MB压缩,183M解压)
- routes-small.kite(2MB压缩,35MB解压)
[
](#usage)使用方法
[
](#quick-start)快速入门
kr [scan|brute] <input> [flags]
<input>可以是一个文件,一个域,或URI。我们会帮你弄清楚。更多细节见输入/主机格式化
# 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)CLI帮助
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标志(以上所有标志+)
-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
[
](#inputhost-formatting)输入/主机格式化
当提供一个输入时,kiterunner将尝试按照以下顺序解析输入。
- 输入是否是一个文件。如果是,则将文件中的所有行作为独立的域来读取
- 输入被当作一个 "域 "来处理
如果你提供了一个 "域",但它作为一个文件存在,例如:google.com ,但google.com 在当前目录下也是一个txt文件,我们将加载google.com 这个文本文件,因为我们先找到它。
域名解析
我们希望你能提供一个完整的URI作为输入,但是你可以提供不完整的URI,我们会尝试猜测你的意思。你可以提供的域的一个例子是。
one.com
two.com:80
three.com:443
four.com:9447
https://five.com:9090
http://six.com:80/api
上述域的列表将扩展到随后的目标列表中。
(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)
我们应用的规则是。
- 如果你提供一个方案,我们就使用该方案。
- 我们只支持http & https
- 如果你不提供一个方案,我们会根据端口来猜测
- 如果你提供一个端口,我们将使用该端口
- 如果你的端口是443,或8443,我们会认为是tls
- 如果你没有提供端口,我们会猜测80和443两个端口。
- 如果你提供了一个路径,我们会在所有针对该主机的请求中添加该路径。
[
](#api-scanning)API扫描
当你有一个单一的目标时
# 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)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)Dirsearch Bruteforcing
当你有一个老式的单词表,其中仍然有%EXT%,你可以使用-D 。这将只替代路径中存在%EXT%的扩展。
kr brute https://target.com -w dirsearch.txt -x 10 -d=0 --ignore-length=34 -ejson,txt -D
[
](#technical-features)技术特点
[
](#depth-scanning)深度扫描
kiterunner的一个关键特征是基于深度的扫描。这试图处理检测基于虚拟应用程序路径的通配符。深度定义了在多少个目录下进行基线检查。
~/kiterunner $ cat wordlist.txt
/api/v1/user/create
/api/v1/user/delete
/api/v2/user/
/api/v2/admin/
/secrets/v1/
/secrets/v2/
- 在深度为0时,只有
/,为通配符检测执行基线检查。 - 在深度1,
/api和/secrets将被执行基线检查;这些检查将相应地用于/api和/secrets - 在深度2,
/api/v1,/api/v2,/secrets/v1和/secrets/v2都将被执行基线检查。
默认情况下,kr scan 的深度为1,因为从内部使用来看,我们经常看到这是发生虚拟路由的最常见的深度。kr brute 的默认深度为0,因为你通常不希望在静态词表下进行这种检查。
当然,增加深度会提高扫描的准确性,但这也会增加对目标的请求数量。(# of baseline checks * # of depth baseline directories)。因此,我们建议不要超过1,在极少数情况下,可以达到2的深度。
[
](#using-assetnote-wordlists)使用资产笔记词表
我们从assetnote.io提供内置的下载和缓存词表。你可以使用-A 标志,该标志接收以逗号分隔的别名或全名列表。
你可以通过kr wordlist list 获得所有Assetnote词表的完整列表。
这些词表在使用时,会被缓存在~/.cache/kiterunner/wordlists 。当使用时,这些都是由.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_filenames.txt | manual.json | 3191712 | 71.3mb | false |
| html | html.txt | manual.json | 4227526 | 107.7mb | false |
| apiroutes-201120 | httparchive_apiroutes_2020_11_20.txt | automated.json | 953011 | 45.3mb | false |
| apiroutes-210128 | httparchive_apiroutes_2021_01_28.txt | automated.json | 225456 | 6.6mb | false |
| apiroutes-210228 | httparchive_apiroutes_2021_02_28.txt | automated.json | 223544 | 6.5mb | true |
| apiroutes-210328 | httparchive_apiroutes_2021_03_28.txt | automated.json | 215114 | 6.3mb | false |
| aspx-201118 | httparchive_aspx_asp_cfm_svc_ashx_asmx_2020_11_18.txt | automated.json | 63200 | 1.7mb | false |
| aspx-210128 | httparchive_aspx_asp_cfm_svc_ashx_asmx_2021_01_28.txt | automated.json | 46286 | 928.7kb | false |
| aspx-210228 | httparchive_aspx_asp_cfm_svc_ashx_asmx_2021_02_28.txt | automated.json | 43958 | 883.3kb | false |
| aspx-210328 | httparchive_aspx_asp_cfm_svc_ashx_asmx_2021_03_28.txt | automated.json | 45928 | 926.8kb | false |
| cgi-201118 | httparchive_cgi_pl_2020_11_18.txt | automated.json | 2637 | 44.0kb | false |
<SNIP>
使用方法
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
[
](#head-syntax)头部语法
当使用assetnote提供的词表时,你可能不想使用整个词表,所以你可以选择使用某个词表的前N行,使用head syntax 。当指定一个词表时,其格式为<wordlist_name>:<N lines> 。
使用方法
# 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
[
](#concurrency-settingsgoing-fast)并发设置/快速运行
Kiterunner是为了在很多主机上快速运行。但是,仅仅因为你可以在20000 goroutines下运行kiterunner,并不意味着它是一个好主意。在高线程数下会出现瓶颈和性能下降,这是因为在调度等待网络IO和内核上下文切换的goroutines时花费了更多时间。
kiterunner有两个主要的并发性设置。
-x, --max-connection-per-host- 我们在一台主机上可以拥有的最大开放连接数。由1个goroutine来管理。为了避免DOS'ing主机,我们建议将其保持在5-10个的低水平。根据到目标的延迟,这将产生平均每秒钟1-5个连接的请求(200ms - 1000ms/req)到一个主机。-j, --max-parallel-hosts- 在任何给定时间内扫描的最大主机数。由每个人的1个goroutine监督器来管理
根据你扫描的硬件,你可以优化运行的goroutine的 "最大 "数量会有所不同。在AWS t3.medium上,我们看到超过2500个goroutines的性能下降。这意味着,500台主机x每台主机5个conn(2500)将产生峰值性能。
我们建议不要在你的Macbook上运行kiterunner。由于macOS上对高IO数和Epoll syscalls的内核优化较差,与在类似配置的linux实例上运行kiterunner相比,我们注意到性能大大降低(0.3-0.5倍)。
为了在扫描单个目标或大型攻击面时最大限度地提高性能,我们建议采用以下技巧。
- 在与你要扫描的目标相近的地理区域/数据中心中启动一个EC2实例。
- 用不同的
-x和-j选项对你的目标集进行一些初始基准测试。我们建议典型的起点是-x 5 -j 100,然后在你的CPU使用/网络性能允许的情况下向上移动-j。
[
](#converting-between-file-formats)文件格式之间的转换
Kiterunner还可以让你在模式JSON、Kite文件和标准txt字表之间进行转换。
使用方法
格式是由<input> 和<output> 字段提供的文件类型扩展决定的。我们支持txt 、json 和kite
kr kb convert wordlist.txt wordlist.kite
kr kb convert wordlist.kite wordlist.json
kr kb convert wordlist.kite wordlist.txt
❯ go run ./cmd/kiterunner kb convert -qh
convert an input file format into the specified output file format
this will determine the conversion based on the extensions of the input and the output
we support the following filetypes: txt, json, kite
You can convert any of the following into the corresponding types
-d Debug mode will attempt to convert the schema with error handling
-v=debug Debug verbosity will print out the errors for the schema
Usage:
kite kb convert <input> <output> [flags]
Flags:
-d, --debug debug the parsing
-h, --help help for convert
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")``bigquery
[
](#replaying-requests)重放请求
当你从kiterunner收到一堆输出时,你可能很难立即理解为什么一个请求会导致一个特定的响应代码/长度。Kiterunner提供了一种方法,从所使用的词表中重建请求,包括所有的头和主体参数。
- 你可以通过复制粘贴完整的响应输出到
kb replay命令来重放一个请求。 - 你可以指定一个
--proxy来转发你的请求,这样你就可以使用第三方工具修改/重复/拦截请求,如果你愿意的话。 - 由于默认的golang规范的实现方式(不幸的是),golang net/http客户端将对你的请求进行一些额外的修改。
❯ 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
[
](#technical-implementation)技术实现
[
](#intermediate-data-type-proutes)中间数据类型(PRoutes
我们在kiterunner中使用了wordlists和kitebuilder json schemas的中间表示。这是为了让我们能够动态地生成词表中的字段,并从给定的规范中重构请求体/头文件和查询参数。
PRoute类型是由头信息、正文、查询和Cookie参数组成的,这些参数被编码为pkg/proute.Crumb 。Crumb类型是一个接口,在UUIDs、Floats、Ints、随机字符串等类型上实现。
在进行txt、json和kite文件的转换时,所有的转换都是先进行到proute.API 中间类型。然后将相应的编码写出来
[
](#kite-file-format)Kite文件格式
我们使用一个超级秘密的kite文件格式来存储kitebuilder的json模式。这些是简单的protobuf编码的pkg/proute.APIS ,写到一个文件中。编译是用来让我们快速反序列化已经解析过的词表。这种文件格式并不稳定,只能使用kiterunner的内置转换工具进行交互。
当新版本的kite文件格式发布时,你可能需要重新编译你的kite文件
