1

对Github指定类目的内容进行监控和推送 - 春告鳥

 1 year ago
source link: https://www.cnblogs.com/Cl0ud/p/16631445.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

对Github指定类目的内容进行监控和推送 - 春告鳥 - 博客园

很久之前看到HACK学习呀有一个Github 安全搬运工的系列文章,个人觉得很不错,想要在自己的公众号上也做这方面的内容,内容的编辑排版相对来说比较容易,这样问题就回归到Github安全内容的获取上

这篇文章整体比较长,如果想直接使用的话可以跳转去仓库 https://github.com/Cl0udG0d/YunP4n_Monitor/

实际上这部分在Github上也已经有人做过了,不过大部分安全人员实现的项目是代码监控、信息泄露相关的,例如

我们可以基于他们来进行魔改,直到看到了...
https://github.com/yhy0/github-cve-monitor

实时监控github上新增的cve、自定义关键字和安全工具更新,并多渠道推送通知

其中就有自定义关键字这个功能,我们可以借此来实现我们想要的功能

本来现在可以开始部署了,但是基础条件就是需要一个VPS,然后通过screen之类的后台运行命令把python脚本运行在后台,定时对内容进行爬取和监控
这样还是比较麻烦(我看起来像缺VPS的人吗
所以我们可以考虑用之前github开放的action来实现这个功能

Github Action

Github Action官方文档中对自身的定义

在Github Actions的仓库中自动化、自定义和执行软件开发工作流程。您可以发现、创建和共享操作以执行您喜欢的任何作业(包括CI/CD),并将操作合并到完全自定义的工作流程中。

也就是说我们可以给自己的代码仓库部署一系列自动化脚本,在我们进行了提交、合并分支等操作后,自动执行脚本。
阮一峰Github Action指南中的介绍:

大家知道,持续集成由很多操作组成,比如抓取代码、运行测试、登录远程服务器,发布到第三方服务等等。GitHub 把这些操作就称为 actions。

很多操作在不同项目里面是类似的,完全可以共享。GitHub 注意到了这一点,想出了一个很妙的点子,允许开发者把每个操作写成独立的脚本文件,存放到代码仓库,使得其他开发者可以引用。

如果你需要某个 action,不必自己写复杂的脚本,直接引用他人写好的 action 即可,整个持续集成过程,就变成了一个 actions 的组合。这就是 GitHub Actions 最特别的地方。

也就是说当我们编写好项目对应的脚本并上传到Github上后,Github会运行脚本帮我们做一系列动作,而做这些动作所需要消耗的计算资源Github会慷慨地提供给我们(当然也有防止滥用的机制)。如果我们计算资源消耗不是很大,用Github Action就绰绰有余了
所以这里我们可以通过Github Action编写定时任务来运行python脚本,从而达成白嫖
官方文档在此
其中Github Actions的一些术语:

  • workflow 工作流程:持续集成一次运行的过程,就是一个workflow
  • job 任务:一个workflow由一个或多个jobs构成,一次持续集成的运行,可以完成多个任务
  • step 步骤:每个job由多个step构成,一步步完成
  • action 动作:每个step可以依次执行一个或多个命令action

感觉是在一直套娃 😃

先把原来的仓库fork一份到自己这里

20220821212908.png


第一次操作直接在web界面上进行吧

20220821213249.png#crop=0&crop=0&crop=1&crop=1&id=pTSxj&originHeight=675&originWidth=1548&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=


接下来GitHub自动给我们生成了一个小型的main.yml文件,其中填充了运行一个工作流所必须的基本要素

20220821213459.png#crop=0&crop=0&crop=1&crop=1&id=ipEwc&originHeight=733&originWidth=1459&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=


Github Actions默认的位置是.github/workflows/目录中,下面对main.yml进行解释



# name属性用来指定这个工作流的名字

name: CI

# 这个部分用来指定能够触发工作流执行的事件 on: # 当对分支master进行push操作的时候,这个工作流就被触发了 push: branches: [ "master" ] # 当对分支master进行pull request操作的时候,同样也会触发这个工作流 pull_request: branches: [ "master" ]

# 允许你手动在Github网页上执行该workflow workflow_dispatch:

# 一个workflow可以由多个job组成,可以并行或者分离运行,在jobs里面来说明要交给Github action执行的任务 jobs: # 这个jobs中的一个任务,名字叫做build(任务的名字是自己取的) build: # 用来指定这个任务在什么操作系统上面跑,此处运行在最新版本的ubuntu镜像上(服务器是Github免费提供的) runs-on: ubuntu-latest

# 指出这个build任务的步骤 steps: # 将你的job指向你的文件目录$GITHUB_WORKSPACE,用来运行你的脚本 - uses: actions/checkout@v3

# 步骤 运行单行命令 输出Hello, world! - name: Run a one-line script run: echo Hello, world!

# 步骤 运行一组命令 - name: Run a multi-line script run: | echo Add other actions to build, echo test, and deploy your project.

点击Start commit,这样一个最基本的Github action工作流就写好了,当进行push或者pull request时会触发脚本执行
为了检测是否成功,push一个test.txt上去,可以看到

20220821224109.png#crop=0&crop=0&crop=1&crop=1&id=CHope&originHeight=754&originWidth=1817&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=


点击可以查看运行详情

20220821224216.png#crop=0&crop=0&crop=1&crop=1&id=zjhZw&originHeight=730&originWidth=1426&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=

测试定时任务

我们先测试一下Github Actions的定时任务功能



on: schedule: - cron: '*/5 * * * *'

上面表示每五分钟执行一次任务,Crontab的设置规则可以查看
有关cron语法的五个字段的说明
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of the month (1 - 31)
│ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
│ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │


注:这里的定时任务指定的时间和中国的时区有时差,北京时间比Github所使用的时区快8个小时
比如7月1号23点,github时间是7月1号15点。所以我们可以配置成15点或16点执行(对应北京时间的夜里11点、12点)

Github Actions定时任务最短的时间间隔也是5分钟
如果不是很熟悉crontab可以在网站上编写规则之后查看

20220822223254.png#crop=0&crop=0&crop=1&crop=1&id=XhWj9&originHeight=791&originWidth=1326&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=


这里可以看到执行时间之间相差了5分钟
修改github main.yml文件为5分钟后发现

20220822223353.png#crop=0&crop=0&crop=1&crop=1&id=PBpFU&originHeight=553&originWidth=1445&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=


任务执行时间相差挺大的 orz
官方对此有一个非常确定的说法如下

注意: schedule 事件在Github Actions 工作流程运行期间负载过高时可能会延迟。高负载时间包括每小时的开始时间。为了降低延迟的可能性,将您的工作流程安排在不同时间运行

原因在于Github为了控制成本,在云上的成本是固定的,这时如果对于用户的任务完全都实时,会有一个非常高的瞬间峰值,对于资源的使用非常不合理,对于这个问题有两个办法解决:

  • 让我们的定时任务对时间的要求不精确
  • 使用自己的云资源 (又回到了原点)

所以我们不会选择第二种方法,而我们的任务恰好对时间不精确,只需要一天给我们推送一次或者两次就可以了,继而我们自然要薅这个羊毛了

魔改main.yaml

修改main.yml文件中定时为每天12点一次



on: schedule: - cron: '0 4 * * *'

因为时区的问题所以我们用北京时间减 8 小时
接着修改main.yml

使用本地时间



env: TZ: Asia/Shanghai

这里我们只需要执行python文件,所以运行单任务就行
先设置虚拟的运行环境



runs-on: ubuntu-latest

设置每个step,首先要 checkout the repository under $GITHUB_WORKSPACE



steps: - name: checkout - uses: actions/checkout@v3

安装运行代码需要的依赖



- name: Set up Python3 uses: actions/setup-python@v2 with: python-version: '3.6' - name: Install requirements run: | python3 -m pip install --upgrade pip pip3 install -r ./requirements.txt

最后是运行这个脚本



- name: Run YunP4n_Sec env: github_token: ${{ secrets.GITHUB_TOKEN }} run: python3 ./github_sec_monitor.py

魔改github_sec_monitor.py

虽然现在能够运行python文件了,但是里面还有一些东西是需要我们自己配置的

orz,写到这一步的时候发现要改的东西还挺多的,草,直接新建一个仓库吧

创建仓库YunP4n_Monitor

仓库地址 https://github.com/Cl0udG0d/YunP4n_Monitor
创建main.py执行我们的主要逻辑,整体的逻辑为
加载关键字列表 -> 遍历关键字并获取最新结果 -> 内容清洗 -> 推送钉钉

加载关键字列表

使用Github Actions来实现的话,我们把关键字作为一个字符串存储到main.yml的环境变量里面,并在python文件里通过环境变量的方式加载出来就行
main.yml设置



- name: Run YunP4n_Sec env: keywords: '漏洞扫描'

python中通过下面的方式加载



import os

keywords=os.environ["keywords"]

遍历关键字并获取最新结果

首先是遍历关键字,我们通过空格来区分关键字,即



- name: Run YunP4n_Sec env: keywords: '漏洞扫描 应急响应'

python中通过空格的切割来处理关键字



import os

keywords=os.environ["keywords"]

def splitKeywordList(): return keywords.split()

获取Github上的搜索结果通过接口来实现,记得带上github token,同样从环境变量中取得



github_token = os.environ.get("github_token") def getKeywordNews(keyword): today_keyword_info_tmp=[] try: # 抓取本年的 api = "https://api.github.com/search/repositories?q={}&sort=updated".format(keyword) json_str = requests.get(api, headers=github_headers, timeout=10).json() today_date = datetime.date.today() n=20 if len(json_str['items'])>20 else len(json_str['items']) for i in range(0, n): keyword_url = json_str['items'][i]['html_url'] try: keyword_name = json_str['items'][i]['name'] description=json_str['items'][i]['description'] pushed_at_tmp = json_str['items'][i]['pushed_at'] pushed_at = re.findall('\d{4}-\d{2}-\d{2}', pushed_at_tmp)[0] if pushed_at == str(today_date): today_keyword_info_tmp.append({"keyword_name": keyword_name, "keyword_url": keyword_url, "pushed_at": pushed_at,"description":description}) print("[+] keyword: {} ,{} ,{} ,{} ,{}".format(keyword, keyword_name,keyword_url,pushed_at,description)) else: print("[-] keyword: {} ,{}的更新时间为{}, 不属于今天".format(keyword, keyword_name, pushed_at)) except Exception as e: pass except Exception as e: logging.error(e, "github链接不通") return today_keyword_info_tmp

对我来说,如果给我推送过一次的内容,我就不想再获取到了,一天我想要获取最多10条github关键字内容监控信息,所以需要有一个集合来专门存储已经爬取的内容
这里需要提到Github的一个机制,即不能创建同名的仓库,我们可以通过仓库的名字来判断是否已经被推送过了。
此外还有一个问题是Github给我们提供的运行容器在下一次加载的时候又是全新的,所以我们不能把我们在VPS上存储到数据库中的方法套用在这里(会造成数据的丢失)。对于Github用户来说,最安全的位置莫过于仓库了,所以我们可以将数据存储到开源仓库一个叫做clean.txt的文件夹内
每次加载的时候
读取txt -> 加载到环境变量 -> python更新环境变量 -> 检查是否已推送 -> 存储到txt里面 -> 将环境变量中已推送的工具覆盖掉原有文件 -> 更新仓库
这样就不用担心数据丢失的问题了
具体的操作如下

  • 读取txt并加载到环境变量


- name: clean data run: echo "CleanKeywords=$(cat ./clean.txt)" >> $GITHUB_ENV
  • python更新环境变量


CleanKeywords=os.environ.get("CleanKeywords")
  • 检查是否已推送


cleanKeywords=set(splitCleanKeywords()) for tempdata in templist: if tempdata.get("keyword_name") in cleanKeywords: pass else: //如果未推送的逻辑
  • 更新环境变量


def flashCleanData(cleanKeywords): text="" for key in cleanKeywords: text+="{} ".format(key) env_file = os.getenv('GITHUB_ENV') with open(env_file, "a") as myfile: myfile.write("CleanKeywords={}".format(text)) logging.info("环境变量刷新成功")
  • 更新仓库原文件


- name: push clean data run: echo ${{ env.CleanKeywords }} > ./clean.txt


- name: push clean data run: | echo ${{ env.CleanKeywords }} > ./clean.txt REMOTE=https://${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} git config user.email "${{ github.actor }}@users.noreply.github.com" git config user.name "${{ github.actor }}" git add . git commit -m "Add new comment" git push ${REMOTE} main

这样就不会推送重复的内容了

这部分已经有很多师傅实现了,我们只需要修改为我们的格式即可,看代码就明白了



def dingding(text, msg,webhook,secretKey): ding = cb.DingtalkChatbot(webhook, secret=secretKey) ding.send_text(msg='{}\r\n{}'.format(text, msg), is_at_all=False) logging.info("发送消息 title:{} msg:{}".format(text,msg))

def sendmsg(pushdata): text="" for data in pushdata: text+="工具名称:{}\n工具网址:{}\n详情:{}\n\n\n ".format(data.get("keyword_name"),data.get("keyword_url"),data.get("description")) dingding("新推送",text,webhook,secretKey) logging.info("消息发送完成")

用钉钉账号创建一个群聊,设置自定义机器人,获取到webhooksecretKey填充到main.yml里,目前main.yml文件内容如下,因为是测试所以时间设置的5分钟执行一次,在实际执行过程中是大于五分钟的,前面已经说过理由了。另外webhooksecretKey是明文存放在main.yml文件中的,存在信息泄露的风险,目前没有找到比较好的替代方法,如果有师傅知道的话麻烦带带



name: YunP4n_Sec

on: schedule: - cron: '*/5 * * * *'

env: TZ: Asia/Shanghai

jobs: github_monitor: runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v3

- name: Set up Python3 uses: actions/setup-python@v2 with: python-version: '3.6'

- name: clean data run: echo "CleanKeywords=$(cat ./clean.txt)" >> $GITHUB_ENV

- name: Install requirements run: | python3 -m pip install --upgrade pip pip3 install -r ./requirements.txt - name: Run YunP4n_Sec env: keywords: '漏洞扫描 内网渗透 代码审计 SQL注入 XSS 漏洞挖掘' github_token: ${{ secrets.GITHUB_TOKEN }} secretKey: "SEC33f24a184e46aecd0b2e2cad1df0457d6820cc1d75430880420aca97d54c24f6" webhook: "https://oapi.dingtalk.com/robot/send?access_token=d8c16a1142ae1e3077d05234b73826b1b65ec56c38b9ff83564e8b317f372d04" run: python3 ./main.py

- name: test run run: echo ${{ env.CleanKeywords }}

- name: push clean data run: | echo ${{ env.CleanKeywords }} > ./clean.txt REMOTE=https://${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} git config user.email "${{ github.actor }}@users.noreply.github.com" git config user.name "${{ github.actor }}" git add . git commit -m "Add new comment" git push ${REMOTE} main

等待一段时间后成功推送消息

20220827171458.png#crop=0&crop=0&crop=1&crop=1&id=lUXNO&originHeight=558&originWidth=1081&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=

fork仓库 https://github.com/Cl0udG0d/YunP4n_Monitor 之后
只需要修改main.yml文件中的这几个参数就行

  • keywords 你需要监控的关键字们,空格隔开就行
  • secretKey 钉钉推送的参数
  • webhook 钉钉推送的参数

如果想要修改推送的时间,修改这部分就行



on: schedule: - cron: '*/5 * * * *'

然后就能愉快使用了

建了一个微信的安全交流群,欢迎添加我微信备注进群,一起来聊天吹水哇,以及一个会发布安全相关内容的公众号,欢迎关注 😃

GIF
GIF

__EOF__


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK