/
threatbook.go
136 lines (123 loc) · 3.28 KB
/
threatbook.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package grab
import (
"context"
"time"
"github.com/imroc/req/v3"
"github.com/kataras/golog"
"github.com/pkg/errors"
)
type ThreatBookCrawler struct {
client *req.Client
log *golog.Logger
}
func NewThreatBookCrawler() Grabber {
client := NewHttpClient()
client.SetCommonHeader("Referer", "https://x.threatbook.com/v5/vulIntelligence")
client.SetCommonHeader("Origin", "https://mp.weixin.qq.com/")
client.SetCommonHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
return &ThreatBookCrawler{
log: golog.Child("[threatbook]"),
client: client,
}
}
func (t *ThreatBookCrawler) ProviderInfo() *Provider {
return &Provider{
Name: "threatbook",
DisplayName: "微步在线研究响应中心-漏洞通告",
Link: "https://x.threatbook.com/v5/vulIntelligence",
}
}
func (t *ThreatBookCrawler) GetUpdate(ctx context.Context, pageLimit int) ([]*VulnInfo, error) {
ctx, cancel := context.WithTimeout(ctx, 10*time.Second) // 增加超时
defer cancel()
var results []*VulnInfo
resp, err := t.client.R().Get("https://x.threatbook.com/v5/node/vul_module/homePage")
if err != nil {
return nil, err
}
var body threatBookHomepage
err = resp.UnmarshalJson(&body)
if err != nil {
return nil, err
}
t.log.Infof("got %d vulns", len(body.Data.HighRisk))
for _, v := range body.Data.HighRisk {
disclosure := v.VulnPublishTime
if disclosure == "" {
disclosure = v.VulnUpdateTime
}
var tags []string
if v.Is0Day {
tags = append(tags, "0day")
}
if v.PocExist {
tags = append(tags, "有Poc")
}
if v.Premium {
tags = append(tags, "有漏洞分析")
}
if v.Solution {
tags = append(tags, "有修复方案")
}
vuln := &VulnInfo{
UniqueKey: v.Id,
Title: v.VulnNameZh,
Severity: Critical,
Disclosure: disclosure,
Solutions: "",
References: nil,
Tags: tags,
From: t.ProviderInfo().Link,
Creator: t,
}
results = append(results, vuln)
}
t.log.Infof("got %d vulns", len(results))
return results, nil
}
func (t *ThreatBookCrawler) IsValuable(info *VulnInfo) bool {
// 漏洞太多了,规则严格一些
var hasPoc, hasAnalysis bool
for _, tag := range info.Tags {
if tag == "有Poc" {
hasPoc = true
}
if tag == "有漏洞分析" {
hasAnalysis = true
}
}
if !hasPoc || !hasAnalysis {
return false
}
if info.Disclosure == "" {
return false
}
// 2024-04-29 format
dis, err := time.Parse("2006-01-02", info.Disclosure)
if err != nil {
t.log.Error(errors.Wrap(err, "parse disclosure time"))
return false
}
// 只看两周内的,古董漏洞就别推了
if time.Since(dis) > 14*24*time.Hour {
return false
}
return true
}
type threatBookHomepage struct {
Data struct {
HighRisk []struct {
Id string `json:"id"`
VulnNameZh string `json:"vuln_name_zh"`
VulnUpdateTime string `json:"vuln_update_time"`
Affects []string `json:"affects"`
VulnPublishTime string `json:"vuln_publish_time,omitempty"`
PocExist bool `json:"pocExist"`
Solution bool `json:"solution"`
Premium bool `json:"premium"`
RiskLevel string `json:"riskLevel"`
Is0Day bool `json:"is0day,omitempty"`
} `json:"highrisk"`
} `json:"data"`
ResponseCode int `json:"response_code"`
}