github.com/chainreactors/fingers@v1.2.1/alias/alias.go (about)

     1  package alias
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/chainreactors/fingers/common"
     7  	"github.com/chainreactors/fingers/resources"
     8  	"github.com/chainreactors/utils/iutils"
     9  	"gopkg.in/yaml.v3"
    10  )
    11  
    12  func NewAliases(origin ...*Alias) (*Aliases, error) {
    13  	var aliases []*Alias
    14  	err := yaml.Unmarshal(resources.AliasesData, &aliases)
    15  	if err != nil {
    16  		return nil, err
    17  	}
    18  	aliasMap := &Aliases{
    19  		Aliases: make(map[string]*Alias, len(aliases)+len(origin)),
    20  		Map:     make(map[string]map[string]string),
    21  	}
    22  
    23  	err = aliasMap.Compile(append(origin, aliases...)) // yaml的优先级高于origin
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  	return aliasMap, nil
    28  }
    29  
    30  type Aliases struct {
    31  	Aliases map[string]*Alias
    32  	Map     map[string]map[string]string // 加速查询的映射表
    33  }
    34  
    35  func (as *Aliases) AppendAliases(other []*Alias) {
    36  	for _, alias := range other {
    37  		as.Append(alias)
    38  	}
    39  }
    40  
    41  func (as *Aliases) Compile(aliases []*Alias) error {
    42  	for _, alias := range aliases {
    43  		alias.Compile()
    44  		as.Append(alias)
    45  	}
    46  	return nil
    47  }
    48  
    49  func (as *Aliases) Append(alias *Alias) {
    50  	// 保留已存在 alias 的 Pocs
    51  	if original, exists := as.Aliases[alias.Name]; exists {
    52  		alias.Pocs = iutils.StringsUnique(append(original.Pocs, alias.Pocs...))
    53  	}
    54  
    55  	as.Aliases[alias.Name] = alias
    56  
    57  	// 生成映射表
    58  	for engine, engineMap := range alias.AliasMap {
    59  		if _, ok := as.Map[engine]; !ok {
    60  			as.Map[engine] = make(map[string]string)
    61  		}
    62  		for _, name := range engineMap {
    63  			as.Map[engine][resources.NormalizeString(name)] = alias.Name
    64  		}
    65  	}
    66  }
    67  
    68  func (as *Aliases) Find(engine, name string) (*Alias, bool) {
    69  	if engineMap, ok := as.Map[engine]; ok {
    70  		if aliasName, ok := engineMap[name]; ok {
    71  			if alias, ok := as.Aliases[aliasName]; ok {
    72  				if !alias.blocked[engine] {
    73  					return alias, true
    74  				}
    75  				return alias, false
    76  			}
    77  		}
    78  	}
    79  	return nil, false
    80  }
    81  
    82  func (as *Aliases) FindAny(name string) (string, *Alias, bool) {
    83  	name = resources.NormalizeString(name)
    84  	for engine, _ := range as.Map {
    85  		alias, ok := as.Find(engine, name)
    86  		if ok {
    87  			return engine, alias, ok
    88  		}
    89  	}
    90  	return "", nil, false
    91  }
    92  
    93  func (as *Aliases) FindFramework(frame *common.Framework) (*Alias, bool) {
    94  	return as.Find(frame.From.String(), resources.NormalizeString(frame.Name))
    95  }
    96  
    97  type Alias struct {
    98  	Name              string `json:"name" yaml:"name" jsonschema:"required,title=Alias Name,description=Unique identifier for the alias,example=nginx"`
    99  	normalizedName    string
   100  	common.Attributes `yaml:",inline" json:",inline"`
   101  	Tags              []string            `json:"tags,omitempty" yaml:"tags" jsonschema:"title=Tags,description=List of tags for categorization and search"`
   102  	Priority          int                 `json:"priority,omitempty" yaml:"priority" jsonschema:"title=Priority,description=Priority level (0-5),minimum=0,maximum=5,default=0,example=1"`
   103  	Link              []string            `json:"link,omitempty" yaml:"link" jsonschema:"title=Alias,description=Test target URLs or addresses for validation,example=https://example.com,example=192.168.1.1:8080"`
   104  	AliasMap          map[string][]string `json:"alias" yaml:"alias" jsonschema:"required,title=Alias Map,description=Mapping of engine names to their alias strings"`
   105  	Block             []string            `json:"block,omitempty" yaml:"block" jsonschema:"title=Block List,description=List of engines to block this alias from"`
   106  	blocked           map[string]bool
   107  	Pocs              []string               `json:"pocs,omitempty" yaml:"pocs,omitempty" jsonschema:"title=POCs,description=List of POC identifiers associated with this alias"`
   108  	Metadata          map[string]interface{} `json:"metadata,omitempty" yaml:"metadata,omitempty" jsonschema:"title=Metadata,description=Additional metadata as key-value pairs for flexible data storage"`
   109  	allTags           []string
   110  }
   111  
   112  func (a *Alias) Compile() {
   113  	a.Name = strings.ToLower(a.Name)
   114  	a.normalizedName = resources.NormalizeString(a.Name)
   115  	a.blocked = make(map[string]bool)
   116  	for _, block := range a.Block {
   117  		a.blocked[block] = true
   118  	}
   119  
   120  	var tags []string
   121  
   122  	if a.Vendor != "" {
   123  		tags = append(tags, strings.ToLower(a.Vendor))
   124  	}
   125  
   126  	if a.Product != "" {
   127  		tags = append(tags, strings.ToLower(a.Product))
   128  	}
   129  
   130  	// 从 metadata 中提取 category 和 type
   131  	if a.Metadata != nil {
   132  		if category, ok := a.Metadata["category"].(string); ok && category != "" {
   133  			tags = append(tags, strings.ToLower(category))
   134  		}
   135  		if typ, ok := a.Metadata["type"].(string); ok && typ != "" {
   136  			tags = append(tags, strings.ToLower(typ))
   137  		}
   138  	}
   139  
   140  	for _, tag := range a.Tags {
   141  		if tag != "" {
   142  			tags = append(tags, strings.ToLower(tag))
   143  		}
   144  	}
   145  
   146  	a.allTags = iutils.StringsUnique(tags)
   147  }
   148  
   149  func (a *Alias) AllTags() []string {
   150  	return a.allTags
   151  }
   152  
   153  func (a *Alias) IsBlocked(key string) bool {
   154  	return a.blocked[key]
   155  }
   156  
   157  func (a *Alias) FuzzyMatch(s string) bool {
   158  	return a.normalizedName == resources.NormalizeString(s)
   159  }
   160  
   161  func (a *Alias) ToWFN() *common.Attributes {
   162  	a.Part = "a"
   163  	return &a.Attributes
   164  }