yarx

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 27, 2021 License: MIT Imports: 36 Imported by: 0

README

Logo

在线体验    漏洞报告

Yarx 是什么

Yarx 来自于 x-r-a-y 的反向拼写,它能够根据 xray 的 yaml poc 规则全自动的生成一个满足规则要求的 Server,使用 xray 扫描该 Server 将会扫描出对应的漏洞。它的核心工作原理如下:

yarx-core

它的主要特性有:

  • 支持 status、header、body 等位置的响应变换
  • 支持 == contains submatch 等各种匹配模式
  • 支持动态变量的渲染和捕获以及多级规则的变量追踪
  • 支持绝大部分内置函数的解析和调用
  • 通过路由合并和智能排序等策略有效减少路由冲突
  • 平铺式规则处理逻辑,支持并发扫描
  • 支持捕获扫描事件做进一步分析联动

立即尝试

./xray webscan --plugins phantasm --html-output yarx.html --url https://yarx.koalr.me

running

几秒钟后你就会得到一个类似的漏洞报告: report.html

安装

  • Github Release

    https://github.com/zema1/yarx/releases 下载合适的版本然后从命令行运行即可

  • 源码安装

    git clone https://github.com/zema1/yarx
    cd yarx
    go build -o yarx ./cmd/yarx
    

用法

USAGE:
   yarx [global options] [arguments...]

GLOBAL OPTIONS:
   --pocs value, -p value    load pocs from this dir
   --listen value, -l value  the http server listen address (default: "127.0.0.1:7788")
   --root value, -r value    load files form this directory if the requested path is not found

   --verbose, -V             verbose mode, which is  equivalent to --log-level debug (default: false)
   --help, -h                show help (default: false)

使用示例:

# 在8080端口创建一个 http 服务,这个服务将模拟 pocs 文件夹下的所有漏洞
./yarx -p ./pocs -l 0.0.0.0:8080

# 和上面类似,但当路径不存在时,会从 `./www/html` 加载文件
./yarx -p ./pocs -l 0.0.0.0:8080 -r ./www/html

running

你可以使用本仓库的 pocs 文件夹,也可以直接使用 xray 官方仓库的 https://github.com/chaitin/xray/tree/master/pocs 文件夹。本仓库仅仅是去掉了暂时不支持的 poc,后者除了在运行时会打印一点错误信息之外没有任何区别,我会定期同步数据来增加更多 poc。当然,你也可以指定自己编写的 poc。

开发

Yarx 也可以作为 go 的 package 来使用

yr := &yarx.Yarx{}
// err := yr.Parse([]byte("poc-data"))
err := yr.ParseFile("/path/to/a/yaml/poc")
if err != nil {
    panic(err)
}

// 每个成功加载的 poc 对应一个 MutationChain
// poc 中的 rule 则对应于 MutationRule
chains := yr.Chains()
rules := yr.Rules()
...

// 一键生成上述规则的 http handler
handler := yr.HTTPHandler()

// 事件处理
handler.OnRuleMatch(func(e *yarx.ScanEvent) {
})
handler.OnPocMatch(func(e *yarx.ScanEvent) {
    fmt.Println(e.RemoteAddr)
    fmt.Println(e.Request)
    fmt.Println(e.Response)
    fmt.Println(e.PocMatched)
    fmt.Println(e.RuleMatched)
})

// 启动服务
http.ListenAndServe(handler, "127.0.0.1:7788")

错误说明

Yarx 在解析 poc 的过程中可能会出现错误,这些 poc 不会被加载到最终的 http 服务中,遇到错误时不要惊慌,基本都是这几类问题:

  • 不支持路径本身太灵活的

    主要是 {{name}}.php/ 之类的路径,这些路径作为路由时无法与其他类似的规则区分开,目测无解(相信我,Yarx 已经尽了最大努力避免路有冲突)

  • 不支持 set 定义中存在复杂转换的情况,如:

    set:
      r0: randLowercase(8)
      r1: base64(r0) # 追踪这个变量太复杂,不打算支持
    
  • 不支持使用反连平台的,即 yaml 中有 newReverse() 调用的,后续有计划支持

如果你遇到其他类型的报错,可以提交一个 issue,带上报错的 yaml poc 即可,我会尽快处理。

规划

  • 支持 Docker 一键部署
  • 支持依赖反连平台的 POC
  • 支持依赖 request 的 POC

Documentation

Index

Constants

View Source
const (
	PositionBody   = "body"
	PositionHeader = "header"
	PositionStatus = "status"
)

Variables

View Source
var (
	ErrReverseNotSupported = errors.New("reverse type is not supported yet")
	ErrRequestNotSupported = errors.New("request variable is not supported yet")
)

Functions

func Generate

func Generate(regex string, limit int) (string, error)

func NewCELEnv

func NewCELEnv() *cel.Env

func RandLowerLetter

func RandLowerLetter(n int) string

func SortedQuery

func SortedQuery(query string) string

func SortedQueryKey

func SortedQueryKey(query string) string

func SortedURI

func SortedURI(u *url.URL) string

Types

type Generator

type Generator struct {
	// contains filtered or unexported fields
}

func NewGenerator

func NewGenerator(regex string) (*Generator, error)

create a new generator

func (*Generator) Generate

func (g *Generator) Generate(limit int) string

limit is the maximum number of times star, range or plus should repeat i.e. [0-9]+ will generate at most 10 characters if this is set to 10

func (*Generator) SetSeed

func (gen *Generator) SetSeed(seed int64)

type MutationChain

type MutationChain struct {
	sync.Mutex
	Name string
	// contains filtered or unexported fields
}

func (*MutationChain) IsFirst

func (g *MutationChain) IsFirst(rule *MutationRule) bool

func (*MutationChain) IsLast

func (g *MutationChain) IsLast(rule *MutationRule) bool

type MutationRule

type MutationRule struct {
	Name        string // eg: poc-yaml-yapi-rce
	Method      string
	ReplacedURI string
	URI         *regexp.Regexp
	Body        *regexp.Regexp
	Header      map[string]*regexp.Regexp

	Status      int
	MutateFuncs []func(resp http.ResponseWriter, ctx *celContext) error

	ExprInfo *expr.SourceInfo
	YamlRule *YamlRule

	Chain *MutationChain
	// contains filtered or unexported fields
}

func NewMutationRule

func NewMutationRule(celCtx *celContext) *MutationRule

func (*MutationRule) HTTPHandler

func (m *MutationRule) HTTPHandler() http.HandlerFunc

func (*MutationRule) Match

func (m *MutationRule) Match(req *http.Request, celCtx *celContext) error

func (*MutationRule) String

func (m *MutationRule) String() string

type RegexpHandler

type RegexpHandler struct {
	// contains filtered or unexported fields
}

func (*RegexpHandler) HandleRule

func (h *RegexpHandler) HandleRule(rule *MutationRule)

func (*RegexpHandler) OnPocMatch

func (h *RegexpHandler) OnPocMatch(fn ScanEventHandleFunc)

OnPocMatch will be called only if the last rule of poc get matched see details at OnRuleMatch

func (*RegexpHandler) OnRuleMatch

func (h *RegexpHandler) OnRuleMatch(fn ScanEventHandleFunc)

OnRuleMatch will be called if there is a poc rule matched for example, if a poc has there rules, OnRuleMatch will be called there times, meanwhile OnPocMatch will only be called once.

func (*RegexpHandler) Routes

func (h *RegexpHandler) Routes() []string

func (*RegexpHandler) ServeHTTP

func (h *RegexpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*RegexpHandler) SetStaticDir

func (h *RegexpHandler) SetStaticDir(path string)

type RespMetrics

type RespMetrics struct {
	// contains filtered or unexported fields
}

func (*RespMetrics) Header

func (f *RespMetrics) Header() http.Header

func (*RespMetrics) HeaderMap

func (f *RespMetrics) HeaderMap() map[string]string

func (*RespMetrics) Write

func (f *RespMetrics) Write(bytes []byte) (int, error)

func (*RespMetrics) WriteHeader

func (f *RespMetrics) WriteHeader(statusCode int)

type ScanEvent

type ScanEvent struct {
	Request     *http.Request
	Response    *RespMetrics
	PocMatched  string
	RuleMatched string
}

func (*ScanEvent) String

func (s *ScanEvent) String() string

type ScanEventHandleFunc

type ScanEventHandleFunc func(e *ScanEvent)

type YamlPoc

type YamlPoc struct {
	Name      string               `yaml:"name"`
	ID        string               `yaml:"id"`
	Tags      []string             `yaml:"tags"`
	ApplyTo   string               `yaml:"apply_to"`
	Transport string               `yaml:"transport"`
	Set       yaml.Node            `yaml:"set"`
	Rules     map[string]*YamlRule `yaml:"rules"`
	Pattern   string               `yaml:"expression"`
}

type YamlRule

type YamlRule struct {
	Name    string `yaml:"-"`
	Request struct {
		Method          string            `yaml:"method"`
		Path            string            `yaml:"path"`
		Headers         map[string]string `yaml:"headers"`
		Body            string            `yaml:"body"`
		FollowRedirects *bool             `yaml:"follow_redirects"`
	} `yaml:"request"`
	Expression string    `yaml:"expression"`
	Output     yaml.Node `yaml:"output"`
}

type Yarx

type Yarx struct {
	// contains filtered or unexported fields
}

func (*Yarx) Chains

func (y *Yarx) Chains() []*MutationChain

func (*Yarx) HTTPHandler

func (y *Yarx) HTTPHandler() *RegexpHandler

func (*Yarx) Parse

func (y *Yarx) Parse(pocData []byte) error

func (*Yarx) ParseFile

func (y *Yarx) ParseFile(path string) error

func (*Yarx) Rules

func (y *Yarx) Rules() []*MutationRule

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL