Skip to content

Commit

Permalink
Merge pull request #85 from zema1/feat-filter-list
Browse files Browse the repository at this point in the history
feat: add product filter list
  • Loading branch information
zema1 authored Jun 4, 2024
2 parents 7cbc80a + e68dd1a commit 6d8ef94
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 4 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
## v1.9.0 (2025.06.04)

### 新增

- 支持白名单关键词过滤, 用于只推送包含白名单关键词的漏洞, 通过 `-wf` 或者环境变量 `WHITELIST_FILE`
指定 [#84](https://github.com/zema1/watchvuln/issues/84)
- 支持黑名单关键词过滤, 用于过滤包含黑名单关键词的漏洞, 通过 `-bf` 或者环境变量 `BLACKLIST_FILE` 指定

## v1.8.3 (2024.05.09)

### 新增

- 新增 diff 模式,跳过初始化,直接检查漏洞更新并推送,通过 `--diff` 或者环境变量 `DIFF` 指定 [#81](https://github.com/zema1/watchvuln/issues/81)
- 新增 diff 模式,跳过初始化,直接检查漏洞更新并推送,通过 `--diff` 或者环境变量 `DIFF`
指定 [#81](https://github.com/zema1/watchvuln/issues/81)

## v1.8.2 (2024.04.29)

Expand Down
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ Docker 方式推荐使用环境变量来配置服务参数
| `ENABLE_CVE_FILTER` | 启用 CVE 过滤,开启后多个数据源的统一 CVE 将只推送一次 | `true` |
| `NO_FILTER` | 禁用上述推送过滤策略,所有新发现的漏洞都会被推送 | `false` |
| `NO_START_MESSAGE` | 禁用服务启动的提示信息 | `false` |
| `WHITELIST_FILE` | 指定推送漏洞的白名单列表文件, 详情见 [推送内容筛选](#推送内容筛选) | |
| `BLACKLIST_FILE` | 指定推送漏洞的黑名单列表文件, 详情见 [推送内容筛选](#推送内容筛选) | |
| `DIFF` | 跳过初始化阶段,转而直接检查漏洞更新并推送 | |
| `HTTPS_PROXY` | 给所有请求配置代理, 支持 `socks5://xxxx` 或者 `http(s)://xxkx` | |
| `HTTPS_PROXY` | 给所有请求配置代理, 详情见 [配置代理](#配置代理) | |

比如使用钉钉机器人

Expand Down Expand Up @@ -350,6 +352,36 @@ watchvuln 支持配置上游代理来绕过网络限制,支持两种方式:
支持 `socks5://xxxx` 或者 `http(s)://xxkx` 两种代理形式。
## 推送内容筛选
如果你只想推送某些产品的漏洞,可以通过配置白名单或者黑名单来实现。这两个参数传入的都是一个文件,文件格式为每行一个产品名,比如:
```txt
Apache
泛微
```
温馨提示:如果你使用 `Docker` 来运行,可以通过挂载目录的方式将文件映射到容器内,比如:
```bash
echo "Apache" > whitelist.txt
docker run -v $(pwd):/config \
-e WHITELIST_FILE=/config/whitelist.txt \
-e xxxx=xxxxx
zemal/watchvuln:latest
```
### 白名单过滤
通过命令行参数 `-wf` 或者环境变量 `WHITELIST_FILE` 来指定白名单文件。在发现新漏洞时,将检查漏洞的 **标题** 和 **描述**
是否包含白名单的任意一行,全都不在的将不推送漏洞。
### 黑名单过滤
通过命令行参数 `-bf` 或者环境变量 `BLACKLIST_FILE` 来指定黑名单文件。在发现新漏洞时,将检查漏洞的 **标题** 是否包含黑名单的任意一行,
包含的将不推送漏洞。为了避免非预期的漏掉推送,黑名单**不会**检查漏洞的 **描述** 是否匹配。
## 常见问题
1. 服务重启后支持增量更新吗
Expand Down
4 changes: 3 additions & 1 deletion ctrl/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ type WatchVulnAppConfig struct {
NoGithubSearch bool `yaml:"no_github_search" json:"no_github_search"`
NoStartMessage bool `yaml:"no_start_message" json:"no_start_message"`
NoFilter bool `yaml:"no_filter" json:"no_filter"`
DiffMode bool `yaml:"diff_mode" json:"diff_mode`
DiffMode bool `yaml:"diff_mode" json:"diff_mode"`
Version string `yaml:"version" json:"version"`
WhiteKeywords []string `yaml:"white_keywords" json:"white_keywords"`
BlackKeywords []string `yaml:"black_keywords" json:"black_keywords"`
}

const dbExample = `
Expand Down
34 changes: 34 additions & 0 deletions ctrl/ctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,40 @@ func (w *WatchVulnApp) collectAndPush(ctx context.Context) {
}
}

// 如果配置了软件列表黑名单,不推送在黑名单内的漏洞
if len(w.config.BlackKeywords) != 0 {
for _, p := range w.config.BlackKeywords {
if strings.Contains(strings.ToLower(v.Title), strings.ToLower(p)) {
w.log.Infof("skipped %s as in product filter list", v)
continue
}
// 黑名单就不检查 description 里的内容了, 容易漏推送
// if strings.Contains(strings.ToLower(v.Description), strings.ToLower(p)) {
// w.log.Infof("skipped %s as in product filter list", v)
// continue
// }
}
}

// 如果配置了软件列表白名单,仅推送在白名单内的漏洞
if len(w.config.WhiteKeywords) != 0 {
found := false
for _, p := range w.config.WhiteKeywords {
if strings.Contains(strings.ToLower(v.Title), strings.ToLower(p)) {
found = true
break
}
if strings.Contains(strings.ToLower(v.Description), strings.ToLower(p)) {
found = true
break
}
}
if !found {
w.log.Infof("skipped %s as not in product filter list", v)
continue
}
}

// find cve pr in nuclei repo
if v.CVE != "" && !w.config.NoGithubSearch {
links, err := w.FindGithubPoc(ctx, v.CVE)
Expand Down
60 changes: 59 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
)

var log = golog.Child("[main]")
var Version = "v1.8.3"
var Version = "v1.9.0"

func main() {
golog.Default.SetLevel("info")
Expand Down Expand Up @@ -125,6 +125,18 @@ func main() {
Usage: "chat ids want to send on telegram, ex: 123456,4312341,123123",
Category: "[\x00Push Options]",
},
&cli.StringFlag{
Name: "whitelist-file",
Aliases: []string{"wf"},
Usage: "specify a file that contains some keywords, vulns with these keywords will be pushed",
Category: "[\x00Push Options]",
},
&cli.StringFlag{
Name: "blacklist-file",
Aliases: []string{"bf"},
Usage: "specify a file that contains some keywords, vulns with these products will NOT be pushed",
Category: "[\x00Push Options]",
},
&cli.StringFlag{
Name: "db-conn",
Aliases: []string{"db"},
Expand Down Expand Up @@ -231,6 +243,8 @@ func Action(c *cli.Context) error {
db := c.String("db")
proxy := c.String("proxy")
diff := c.Bool("diff")
whitelistFile := c.String("whitelist-file")
blacklistFile := c.String("blacklist-file")

if os.Getenv("INTERVAL") != "" {
iv = os.Getenv("INTERVAL")
Expand Down Expand Up @@ -271,6 +285,31 @@ func Action(c *cli.Context) error {
if interval.Minutes() < 1 && !debug {
return fmt.Errorf("interval is too small, at least 1m")
}

// 白名单关键字
if os.Getenv("WHITELIST_FILE") != "" {
whitelistFile = os.Getenv("WHITELIST_FILE")
}
whiteKeywords, err := splitLines(whitelistFile)
if err != nil {
return err
}
if len(whiteKeywords) != 0 {
log.Infof("using whitelist keywords: %v", whiteKeywords)
}

// 黑名单关键字
if os.Getenv("BLACKLIST_FILE") != "" {
blacklistFile = os.Getenv("BLACKLIST_FILE")
}
blackKeywords, err := splitLines(blacklistFile)
if err != nil {
return err
}
if len(blackKeywords) != 0 {
log.Infof("using blacklist keywords: %v", blackKeywords)
}

config := &ctrl.WatchVulnAppConfig{
DBConn: db,
Sources: sourcesParts,
Expand All @@ -281,6 +320,8 @@ func Action(c *cli.Context) error {
NoFilter: noFilter,
DiffMode: diff,
Version: Version,
WhiteKeywords: whiteKeywords,
BlackKeywords: blackKeywords,
}

app, err := ctrl.NewApp(config, textPusher, rawPusher)
Expand Down Expand Up @@ -416,3 +457,20 @@ func must(err error) {
panic(err)
}
}

func splitLines(path string) ([]string, error) {
var products []string
if path != "" {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
for _, p := range strings.Split(string(data), "\n") {
p = strings.TrimSpace(p)
if p != "" {
products = append(products, p)
}
}
}
return products, nil
}

0 comments on commit 6d8ef94

Please sign in to comment.