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 }