github.com/chainreactors/fingers@v1.2.1/common/framework.go (about) 1 package common 2 3 import ( 4 "github.com/chainreactors/utils/iutils" 5 "strings" 6 ) 7 8 // 指纹类型定义 9 type FingerprintType int 10 11 const ( 12 WebFingerprint FingerprintType = iota // Web应用指纹 13 ServiceFingerprint // 服务指纹 14 ) 15 16 // 引擎能力定义 17 type EngineCapability struct { 18 SupportWeb bool // 支持Web指纹 19 SupportService bool // 支持Service指纹 20 } 21 22 // Service指纹检测结果 23 type ServiceResult struct { 24 Framework *Framework 25 Vuln *Vuln // 可选,只有部分引擎(如fingers)会返回漏洞信息 26 } 27 28 var NoGuess bool 29 30 type From int 31 32 const ( 33 FrameFromDefault From = iota 34 FrameFromACTIVE 35 FrameFromICO 36 FrameFromNOTFOUND 37 FrameFromGUESS 38 FrameFromRedirect 39 FrameFromFingers 40 FrameFromFingerprintHub 41 FrameFromWappalyzer 42 FrameFromEhole 43 FrameFromGoby 44 FrameFromNmap 45 ) 46 47 func (f From) String() string { 48 return FrameFromMap[f] 49 } 50 51 var FrameFromMap = map[From]string{ 52 FrameFromDefault: "default", 53 FrameFromACTIVE: "active", 54 FrameFromICO: "ico", 55 FrameFromNOTFOUND: "404", 56 FrameFromGUESS: "guess", 57 FrameFromRedirect: "redirect", 58 FrameFromFingers: "fingers", 59 FrameFromFingerprintHub: "fingerprinthub", 60 FrameFromWappalyzer: "wappalyzer", 61 FrameFromEhole: "ehole", 62 FrameFromGoby: "goby", 63 FrameFromNmap: "nmap", 64 } 65 66 func GetFrameFrom(s string) From { 67 switch s { 68 case "active": 69 return FrameFromACTIVE 70 case "404": 71 return FrameFromNOTFOUND 72 case "ico": 73 return FrameFromICO 74 case "guess": 75 return FrameFromGUESS 76 case "redirect": 77 return FrameFromRedirect 78 case "fingerprinthub", "fingerprinthub_v4": // fingerprinthub_v4 保留用于向后兼容 79 return FrameFromFingerprintHub 80 case "wappalyzer": 81 return FrameFromWappalyzer 82 case "ehole": 83 return FrameFromEhole 84 case "goby": 85 return FrameFromGoby 86 case "fingers": 87 return FrameFromFingers 88 case "nmap": 89 return FrameFromNmap 90 91 default: 92 return FrameFromDefault 93 } 94 } 95 96 func NewFramework(name string, from From) *Framework { 97 frame := &Framework{ 98 Name: name, 99 From: from, 100 Froms: map[From]bool{from: true}, 101 Tags: make([]string, 0), 102 Attributes: NewAttributesWithAny(), 103 } 104 frame.Attributes.Product = name 105 frame.Attributes.Part = "a" 106 if from >= FrameFromFingers { 107 frame.AddTag(from.String()) 108 } 109 return frame 110 } 111 112 func NewFrameworkWithVersion(name string, from From, version string) *Framework { 113 frame := NewFramework(name, from) 114 frame.Attributes.Version = version 115 //frame.Version = version 116 return frame 117 } 118 119 type Framework struct { 120 Name string `json:"name"` 121 From From `json:"-"` // 指纹可能会有多个来源, 指纹合并时会将多个来源记录到froms中 122 Froms map[From]bool `json:"froms,omitempty"` 123 Tags []string `json:"tags,omitempty"` 124 IsFocus bool `json:"is_focus,omitempty"` 125 MatchDetail *MatchDetail `json:"matcher,omitempty"` 126 *Attributes `json:"attributes,omitempty"` 127 } 128 129 // MatchDetail describes which rule and matcher produced a hit. 130 type MatchDetail struct { 131 RuleIndex int `json:"rule_index,omitempty"` 132 MatcherType string `json:"matcher_type,omitempty"` 133 MatcherIndex int `json:"matcher_index,omitempty"` 134 MatcherValue string `json:"matcher_value,omitempty"` 135 SendData string `json:"send_data,omitempty"` 136 } 137 138 func (f *Framework) String() string { 139 var s strings.Builder 140 if f.IsFocus { 141 s.WriteString("focus:") 142 } 143 s.WriteString(f.Name) 144 145 if f.Version != "" { 146 s.WriteString(":" + strings.Replace(f.Version, ":", "_", -1)) 147 } 148 149 if len(f.Froms) > 1 { 150 s.WriteString(":(") 151 var froms []string 152 for from, _ := range f.Froms { 153 froms = append(froms, FrameFromMap[from]) 154 } 155 s.WriteString(strings.Join(froms, " ")) 156 s.WriteString(")") 157 } else { 158 for from, _ := range f.Froms { 159 if from != FrameFromFingers { 160 s.WriteString(":") 161 s.WriteString(FrameFromMap[from]) 162 } 163 } 164 } 165 return strings.TrimSpace(s.String()) 166 } 167 168 func (f *Framework) UpdateAttributes(attrs *Attributes) { 169 if f.Version != "" { 170 attrs.Version = f.Version 171 } 172 f.Attributes = attrs 173 } 174 175 func (f *Framework) CPE() string { 176 return f.Attributes.String() 177 } 178 179 func (f *Framework) URI() string { 180 return f.Attributes.URI() 181 } 182 183 func (f *Framework) WFN() string { 184 return f.Attributes.WFNString() 185 } 186 187 func (f *Framework) IsGuess() bool { 188 var is bool 189 for from, _ := range f.Froms { 190 if from == FrameFromGUESS { 191 is = true 192 } else { 193 return false 194 } 195 } 196 return is 197 } 198 199 func (f *Framework) AddTag(tag string) { 200 if !f.HasTag(tag) { 201 f.Tags = append(f.Tags, tag) 202 } 203 } 204 205 func (f *Framework) HasTag(tag string) bool { 206 for _, t := range f.Tags { 207 if t == tag { 208 return true 209 } 210 } 211 return false 212 } 213 214 type Frameworks map[string]*Framework 215 216 func (fs Frameworks) One() *Framework { 217 for _, f := range fs { 218 return f 219 } 220 return nil 221 } 222 223 func (fs Frameworks) List() []*Framework { 224 var frameworks []*Framework 225 for _, f := range fs { 226 frameworks = append(frameworks, f) 227 } 228 return frameworks 229 } 230 231 func (fs Frameworks) Add(other *Framework) bool { 232 if other == nil { 233 return false 234 } 235 other.Name = strings.ToLower(other.Name) 236 if frame, ok := fs[other.Name]; ok { 237 for from, _ := range other.Froms { 238 frame.Froms[from] = true 239 } 240 frame.Tags = iutils.StringsUnique(append(frame.Tags, other.Tags...)) 241 frame.UpdateAttributes(other.Attributes) 242 return false 243 } else { 244 fs[other.Name] = other 245 return true 246 } 247 } 248 249 func (fs Frameworks) Merge(other Frameworks) int { 250 // name, tag 统一小写, 减少指纹库之间的差异 251 var n int 252 for _, f := range other { 253 f.Name = strings.ToLower(f.Name) 254 if fs.Add(f) { 255 n += 1 256 } 257 } 258 return n 259 } 260 261 func (fs Frameworks) String() string { 262 if fs == nil { 263 return "" 264 } 265 frameworkStrs := make([]string, len(fs)) 266 i := 0 267 for _, f := range fs { 268 if NoGuess && f.IsGuess() { 269 continue 270 } 271 frameworkStrs[i] = f.String() 272 i++ 273 } 274 return strings.Join(frameworkStrs, "||") 275 } 276 277 func (fs Frameworks) GetNames() []string { 278 if fs == nil { 279 return nil 280 } 281 var titles []string 282 for _, f := range fs { 283 if !f.IsGuess() { 284 titles = append(titles, f.Name) 285 } 286 } 287 return titles 288 } 289 290 func (fs Frameworks) URI() []string { 291 if fs == nil { 292 return nil 293 } 294 var uris []string 295 for _, f := range fs { 296 uris = append(uris, f.URI()) 297 } 298 return uris 299 } 300 301 func (fs Frameworks) CPE() []string { 302 if fs == nil { 303 return nil 304 } 305 var cpes []string 306 for _, f := range fs { 307 cpes = append(cpes, f.CPE()) 308 } 309 return cpes 310 } 311 312 func (fs Frameworks) WFN() []string { 313 if fs == nil { 314 return nil 315 } 316 var wfns []string 317 for _, f := range fs { 318 wfns = append(wfns, f.WFN()) 319 } 320 return wfns 321 } 322 323 func (fs Frameworks) IsFocus() bool { 324 if fs == nil { 325 return false 326 } 327 for _, f := range fs { 328 if f.IsFocus { 329 return true 330 } 331 } 332 return false 333 } 334 335 func (fs Frameworks) HasTag(tag string) bool { 336 for _, f := range fs { 337 if f.HasTag(tag) { 338 return true 339 } 340 } 341 return false 342 } 343 344 func (fs Frameworks) HasFrom(from string) bool { 345 for _, f := range fs { 346 if f.Froms[GetFrameFrom(from)] { 347 return true 348 } 349 } 350 return false 351 }