整体功能
从 github 的相关 API 接口搜索关键字 CVE-{YEAR},并且按照 best-match
进行排序,获取每年的 CVE 中前 1000 个,再进行判活,去重等等筛选,最终存入数据库。
代码实现
getGithubHeader()
func getGithubHeader() map[string]string{
token := cfg.Github.GithubToken
header := map[string]string{
"Authorization":"token "+ token,
}
return header
}
该函数用于从 config 文件中获取 github token,如果不加上 token 访问,1h 只能访问 50 次:
加上 token 后尝试:
请求次数变成 6000. 更多详细配置参考官方文档:
url: https://docs.github.com/v3/search/
title:"Search - GitHub Docs"
description:"Use the REST API to search for specific items on GitHub."
host: docs.github.com
favicon:/assets/cb-345/images/site/favicon.png
image: https://github.githubassets.com/images/modules/open_graph/github-logo.png
getCVEInfo(cve string)
func getCVEInfo(cve string)(exists bool, desc, cvss2, cvss3, cna string, err error){
url := nvdURL + cve
res, err := http.Get(url)
if err !=nil{
fmt.Println("Error establishing connect:", err)
returnfalse,"","","","", err
}
defer res.Body.Close()
doc, err := goquery.NewDocumentFromReader(res.Body)
if err !=nil{
fmt.Println("Error parsing html:", err)
returnfalse,"","","","", err
}
//exists
//cvss3
//cna
//cvss2
//desc
return exists, desc, cvss2, cvss3, cna,nil
}
该函数用来判断 CVE 是否存在,如果存在,从返回值取出漏洞描述以及评分信息。
fetchGithub(year, page int, wg *sync.WaitGroup, countchan chan struct{})
func fetchGithub(year, page int, wg *sync.WaitGroup, countchan chan struct{}) {
defer wg.Done()
/*
...
data handle
...
*/
err = database.InsertGithubDB(cve, desc, date_published, cvss2, cvss3, cna, poc_url)
if err != nil {
fmt.Println("Error insert vul:", cve)
continue
}
countchan <- struct{}{} //记录插入条数
}
}
该函数用来完成对 github 数据的一次完整的爬取及处理。
ConcurrentGitHubCrawler()
func ConcurrentGitHubCrawler() {
var wg, mainWG sync.WaitGroup
var totalCount int
for year := startYear; year <= endYear; year++ {
mainWG.Add(1)
yearCount := 0
countChan := make(chan struct{})
for page := 1; page <= 10; page++ {
wg.Add(1)
go fetchGithub(year, page, &wg, countChan)
}
go func() {
wg.Wait()
close(countChan)
mainWG.Done()
}()
for range countChan {
yearCount++
}
totalCount += yearCount
}
mainWG.Wait()
fmt.Printf("Github: Successfully insert %d vul info", totalCount)
}
该函数实现了 fetchGithub 函数的并发操作。在外层循环中,依次遍历 year,并且在 mainwg 中加 1,到内层循环里,wg 加 1,并且执行爬取处理的函数,起一个协程来等待当前 year 下所有 page 的数据爬取完成,并且关闭 countChan,当前 year 完成后,通过 for range 来统计插入数据库的条数,当所有 year 的数据爬取完成后,主协程停止等待,并打印结果。
运行结果
原文始发于微信公众号(Crush Sec):golang 实现漏洞监控02——github 历史漏洞信息爬取
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论