Skip to content

Commit

Permalink
Merge pull request #4 from zema1/feat-wechat-work
Browse files Browse the repository at this point in the history
支持微信企业版机器人,增加测试信息
  • Loading branch information
zema1 authored Mar 27, 2023
2 parents bb248b4 + 15d9b76 commit 29941e2
Show file tree
Hide file tree
Showing 14 changed files with 332 additions and 83 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## v0.2.0 (2023.03.27)

### 新增

- 增加启动和退出消息,可以测试机器人是否正常运行
- 增加微信企业版机器人支持

## v0.1.0 (2023.03.25)

### 新增

- 支持阿里云漏洞库的抓取 https://avd.aliyun.com/high-risk/list
- 支持奇安信漏洞库的抓取 https://ti.qianxin.com/vulnerability
- 支持OSCS开源安全情报预警 https://www.oscs1024.com/cm
- 支持钉钉推送
- 支持指定检查间隔
- 支持增量更新
- 支持 Docker 运行
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ WORKDIR /app

COPY --from=builder /app/main /app/main

ENV DINGDING_ACCESS_TOKEN="" DINGDING_SECRET="" INTERVAL=30m
ENV DINGDING_ACCESS_TOKEN="" DINGDING_SECRET="" WECHATWORK_KEY="" INTERVAL=30m
ENTRYPOINT ["/app/main"]
62 changes: 45 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# WatchVuln 高价值漏洞采集与推送

众所周知,CVE 漏洞库中 99% 以上的漏洞只是无现实意义的编号。我想集中精力看下当下需要关注的高价值漏洞有哪些,而不是被各类 RSS
和公众号的 ~~威胁情报~~ 淹没。 于是写了这个小项目来抓取部分高质量的漏洞信息源然后做推送。 `WatchVuln`意为**监测**漏洞更新,同时也表示这些漏洞需要**注意**
一下。
和公众号的 ~~威胁情报~~ 淹没。 于是写了这个小项目来抓取部分高质量的漏洞信息源然后做推送。 `WatchVuln`意为**监测**
漏洞更新,同时也表示这些漏洞需要**注意**
漏洞更新,同时也表示这些漏洞需要**注意**一下。

当前抓取了这几个站点的数据:

Expand All @@ -13,49 +14,62 @@
| 奇安信威胁情报中心 | https://ti.qianxin.com/vulnerability | 等级为高危严重**并且**包含 `奇安信CERT验证` `POC公开` `技术细节公布`标签之一 |

> 所有站点采用的都是公开接口,且抓取策略很柔和,无恶意。如果有侵权,请提交 issue, 我会删除相关源。
>
> 如果有更好的信息源也可以反馈给我,需要能够响应及时 & 漏洞有价值
>
> 如果有更好的信息源也可以反馈给我,需要能够响应及时 & 漏洞有价值
当有漏洞更新时,会受到一条推送消息:

![dingding](./.github/assets/dingding.png)

## 快速使用

当前仅支持钉钉机器人推送,使用之前需要有一个钉钉机器人,安全设置使用加签模式,获得这两个密钥一会要用
### 使用 Docker

- `DINGDING_ACCESS_TOKEN`: 取钉钉 webhook 的 `access_token` 部分, 形如 `260cdz724fay862bce8d3ea71762cxxxxxxxxx`
- `DINGDING_SECRET`: 加签的那个值, 形如 `SECxxxxxxxxxxxxxxxxxx`
使用之前需要先添加机器人,获取相关的密钥,当前支持钉钉和企业微信 (飞书在路上了) 几个相关的环境变量:

### 使用 Docker
- `DINGDING_ACCESS_TOKEN` 钉钉 webhook 的 `access_token` 部分, 形如 `260cdz724fay862bce8d3ea71762cxxxxxxxxx`
- `DINGDING_SECRET` 钉钉加签的那个值, 形如 `SECxxxxxxxxxxxxxxxxxx`
- `WECHATWORK_KEY` 企业微信 webhook 的 key , 形如 `260cdz724fay862bce8d3ea71762cxxxxxxxxx`

使用钉钉机器人

```bash
docker pull zemal/watchvuln:latest

docker run --restart always -d \
-e DINGDING_ACCESS_TOKEN=xxxx \
-e DINGDING_SECRET=xxxx \
-e INTERVAL=30m \
zemal/watchvuln:latest
```

初次运行会在本地建立全量数据库,大概需要 1~5 分钟,可以使用 `docker logs -f [containerId]` 来查看进度。
完成后将每 30分钟 (30m) 检查一次数据源。这个频率可以通过 `INTERVAL` 这个环境变量来设置,支持的形式如
`120s` `30m` `1h`,最低 1 分钟 (`60s``1m`)
使用企业微信机器人

> 特别注意: 为了减少内卷,该工具在凌晨 12:00 到 7:00 间会去 sleep 不会运行!
```bash
docker pull zemal/watchvuln:latest

docker run --restart always -d \
-e WECHATWORK_KEY=xxxx \
-e INTERVAL=30m \
zemal/watchvuln:latest
```

如果配置了多种机器人的密钥,都会生效,也就是说可以在一个服务推送到多种服务。 初次运行会在本地建立全量数据库,大概需要 1~5
分钟,可以使用 `docker logs -f [containerId]` 来查看进度。
完成后会在群内收到一个提示消息,表示已成功跑起来。 后续将每 30分钟 (30m) 检查一次。这个频率可以通过 `INTERVAL`
这个环境变量来设置,支持的形式如
`120s` `30m` `1h`,最低 1 分钟 (`60s``1m`)

### 使用二进制

前往 Release 下载对应平台的二进制,然后在命令行执行。

```bash
NAME:
watchvuln - A high valuable vulnerability watcher and pusher

USAGE:
watchvuln [global options] command [command options] [arguments...]

VERSION:
v0.1.0
v0.2.0

COMMANDS:
help, h Shows a list of commands or help for one command
Expand All @@ -65,14 +79,24 @@ GLOBAL OPTIONS:
--interval value, -i value checking every [interval], supported format like 30s, 30m, 1h (default: "30m")
--dingding-access-token value, --dt value access token of dingding bot
--dingding-sign-secret value, --ds value sign secret of dingding bot
--wechatwork-key value, --wk value wechat work webhook key
--no-start-message, -n disable the hello message when server starts (default: false)
--help, -h show help
--version, -v print the version
```

在参数中指定相关 Token 即可

钉钉

```
$ ./watchvuln --dt DINGDING_ACCESS_TOKEN --ds DINGDING_SECRET -i 30m
```

企业微信

```
$ ./watchvuln --dt DINGDING_ACCESS_TOKEN --ds DINGDING_SECRET
$ ./watchvuln --wk WECHATWORK_KEY -i 30m
```

## 常见问题
Expand All @@ -84,3 +108,7 @@ $ ./watchvuln --dt DINGDING_ACCESS_TOKEN --ds DINGDING_SECRET
2. 如何强制重新创建本地数据库

删除运行目录的 `vuln_vx.sqlite3` 文件再重新运行即可

## 其他

为了减少内卷,该工具在 00:00 到 07:00 间会去 sleep 不会运行, 请确保你的服务器是正确的时间!
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/kataras/golog v0.1.8
github.com/pkg/errors v0.9.1
github.com/urfave/cli/v2 v2.25.0
github.com/vimsucks/wxwork-bot-go v0.0.0-20221213061339-fcbcd88ede1c
golang.org/x/net v0.7.0
golang.org/x/sync v0.1.0
modernc.org/sqlite v1.21.0
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,13 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/urfave/cli/v2 v2.25.0 h1:ykdZKuQey2zq0yin/l7JOm9Mh+pg72ngYMeB0ABn6q8=
github.com/urfave/cli/v2 v2.25.0/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/vimsucks/wxwork-bot-go v0.0.0-20221213061339-fcbcd88ede1c h1:gyl9LgDfFBpVSbAY816tU/nhDuSHMa0tXoleQrIJyE8=
github.com/vimsucks/wxwork-bot-go v0.0.0-20221213061339-fcbcd88ede1c/go.mod h1:brn5UkCRa+oqXYsvyO0Mz5JsfU2vlOWUndlvYILUacw=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
Expand Down
4 changes: 2 additions & 2 deletions grab/avd.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ func NewAVDCrawler() Grabber {
log: golog.Child("[aliyun-avd]"),
}
}
func (a *AVDCrawler) SourceInfo() *SourceInfo {
return &SourceInfo{
func (a *AVDCrawler) ProviderInfo() *Provider {
return &Provider{
Name: "aliyun-avd",
DisplayName: "阿里云漏洞库",
Link: "https://avd.aliyun.com/high-risk/list",
Expand Down
4 changes: 2 additions & 2 deletions grab/grab.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ func (v *VulnInfo) String() string {
return fmt.Sprintf("%s (%s)", v.Title, v.From)
}

type SourceInfo struct {
type Provider struct {
Name string
DisplayName string
Link string
}

type Grabber interface {
SourceInfo() *SourceInfo
ProviderInfo() *Provider
GetPageCount(ctx context.Context, size int) (int, error)
ParsePage(ctx context.Context, page int, size int) (chan *VulnInfo, error)
IsValuable(info *VulnInfo) bool
Expand Down
6 changes: 3 additions & 3 deletions grab/oscs.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ func NewOSCSCrawler() Grabber {
return c
}

func (t *OSCSCrawler) SourceInfo() *SourceInfo {
return &SourceInfo{
func (t *OSCSCrawler) ProviderInfo() *Provider {
return &Provider{
Name: "oscs",
DisplayName: "OSCS开源安全情报预警",
Link: "https://www.oscs1024.com/cm",
Expand Down Expand Up @@ -163,7 +163,7 @@ func (t *OSCSCrawler) parseSingeVuln(ctx context.Context, mps string) (*VulnInfo
References: refs,
Tags: nil,
Solutions: "",
From: t.SourceInfo().Link,
From: t.ProviderInfo().Link,
Creator: t,
}
return info, nil
Expand Down
6 changes: 3 additions & 3 deletions grab/ti.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ func NewTiCrawler() Grabber {
return c
}

func (t *TiCrawler) SourceInfo() *SourceInfo {
return &SourceInfo{
func (t *TiCrawler) ProviderInfo() *Provider {
return &Provider{
Name: "qianxin-ti",
DisplayName: "奇安信威胁情报中心",
Link: "https://ti.qianxin.com/vulnerability",
Expand Down Expand Up @@ -105,7 +105,7 @@ func (t *TiCrawler) ParsePage(ctx context.Context, page, size int) (chan *VulnIn
References: []string{},
Tags: tags,
Solutions: "",
From: t.SourceInfo().Link,
From: t.ProviderInfo().Link,
Creator: t,
}
result <- info
Expand Down
Loading

0 comments on commit 29941e2

Please sign in to comment.