很久之前看到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一份到自己这里



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



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



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

  1. # name属性用来指定这个工作流的名字
  2. name: CI
  3. # 这个部分用来指定能够触发工作流执行的事件
  4. on:
  5. # 当对分支master进行push操作的时候,这个工作流就被触发了
  6. push:
  7. branches: [ "master" ]
  8. # 当对分支master进行pull request操作的时候,同样也会触发这个工作流
  9. pull_request:
  10. branches: [ "master" ]
  11. # 允许你手动在Github网页上执行该workflow
  12. workflow_dispatch:
  13. # 一个workflow可以由多个job组成,可以并行或者分离运行,在jobs里面来说明要交给Github action执行的任务
  14. jobs:
  15. # 这个jobs中的一个任务,名字叫做build(任务的名字是自己取的)
  16. build:
  17. # 用来指定这个任务在什么操作系统上面跑,此处运行在最新版本的ubuntu镜像上(服务器是Github免费提供的)
  18. runs-on: ubuntu-latest
  19. # 指出这个build任务的步骤
  20. steps:
  21. # 将你的job指向你的文件目录$GITHUB_WORKSPACE,用来运行你的脚本
  22. - uses: actions/checkout@v3
  23. # 步骤 运行单行命令 输出Hello, world!
  24. - name: Run a one-line script
  25. run: echo Hello, world!
  26. # 步骤 运行一组命令
  27. - name: Run a multi-line script
  28. run: |
  29. echo Add other actions to build,
  30. echo test, and deploy your project.

点击Start commit,这样一个最基本的Github action工作流就写好了,当进行push或者pull request时会触发脚本执行

为了检测是否成功,push一个test.txt上去,可以看到



点击可以查看运行详情

测试定时任务

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

  1. on:
  2. schedule:
  3. - 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可以在网站上编写规则之后查看



这里可以看到执行时间之间相差了5分钟

修改github main.yml文件为5分钟后发现



任务执行时间相差挺大的 orz

官方对此有一个非常确定的说法如下

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

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

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

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

魔改main.yaml

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

  1. on:
  2. schedule:
  3. - cron: '0 4 * * *'

因为时区的问题所以我们用北京时间减 8 小时

接着修改main.yml

环境变量

使用本地时间

  1. env:
  2. TZ: Asia/Shanghai

工作指令

这里我们只需要执行python文件,所以运行单任务就行

先设置虚拟的运行环境

  1. runs-on: ubuntu-latest

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

  1. steps:
  2. - name: checkout
  3. - uses: actions/checkout@v3

安装运行代码需要的依赖

  1. - name: Set up Python3
  2. uses: actions/setup-python@v2
  3. with:
  4. python-version: '3.6'
  5. - name: Install requirements
  6. run: |
  7. python3 -m pip install --upgrade pip
  8. pip3 install -r ./requirements.txt

最后是运行这个脚本

  1. - name: Run YunP4n_Sec
  2. env:
  3. github_token: ${{ secrets.GITHUB_TOKEN }}
  4. 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设置

  1. - name: Run YunP4n_Sec
  2. env:
  3. keywords: '漏洞扫描'

python中通过下面的方式加载

  1. import os
  2. keywords=os.environ["keywords"]

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

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

  1. - name: Run YunP4n_Sec
  2. env:
  3. keywords: '漏洞扫描 应急响应'

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

  1. import os
  2. keywords=os.environ["keywords"]
  3. def splitKeywordList():
  4. return keywords.split()

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

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

内容清洗

对我来说,如果给我推送过一次的内容,我就不想再获取到了,一天我想要获取最多10条github关键字内容监控信息,所以需要有一个集合来专门存储已经爬取的内容

这里需要提到Github的一个机制,即不能创建同名的仓库,我们可以通过仓库的名字来判断是否已经被推送过了。

此外还有一个问题是Github给我们提供的运行容器在下一次加载的时候又是全新的,所以我们不能把我们在VPS上存储到数据库中的方法套用在这里(会造成数据的丢失)。对于Github用户来说,最安全的位置莫过于仓库了,所以我们可以将数据存储到开源仓库一个叫做clean.txt的文件夹内

每次加载的时候

读取txt -> 加载到环境变量 -> python更新环境变量 -> 检查是否已推送 -> 存储到txt里面 -> 将环境变量中已推送的工具覆盖掉原有文件 -> 更新仓库

这样就不用担心数据丢失的问题了

具体的操作如下

  • 读取txt并加载到环境变量
  1. - name: clean data
  2. run: echo "CleanKeywords=$(cat ./clean.txt)" >> $GITHUB_ENV
  • python更新环境变量
  1. CleanKeywords=os.environ.get("CleanKeywords")
  • 检查是否已推送
  1. cleanKeywords=set(splitCleanKeywords())
  2. for tempdata in templist:
  3. if tempdata.get("keyword_name") in cleanKeywords:
  4. pass
  5. else:
  6. //如果未推送的逻辑
  • 更新环境变量
  1. def flashCleanData(cleanKeywords):
  2. text=""
  3. for key in cleanKeywords:
  4. text+="{} ".format(key)
  5. env_file = os.getenv('GITHUB_ENV')
  6. with open(env_file, "a") as myfile:
  7. myfile.write("CleanKeywords={}".format(text))
  8. logging.info("环境变量刷新成功")
  • 更新仓库原文件
  1. - name: push clean data
  2. run: echo ${{ env.CleanKeywords }} > ./clean.txt
  • 更新仓库
  1. - name: push clean data
  2. run: |
  3. echo ${{ env.CleanKeywords }} > ./clean.txt
  4. REMOTE=https://${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
  5. git config user.email "${{ github.actor }}@users.noreply.github.com"
  6. git config user.name "${{ github.actor }}"
  7. git add .
  8. git commit -m "Add new comment"
  9. git push ${REMOTE} main

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

推送钉钉

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

  1. def dingding(text, msg,webhook,secretKey):
  2. ding = cb.DingtalkChatbot(webhook, secret=secretKey)
  3. ding.send_text(msg='{}\r\n{}'.format(text, msg), is_at_all=False)
  4. logging.info("发送消息 title:{} msg:{}".format(text,msg))
  5. def sendmsg(pushdata):
  6. text=""
  7. for data in pushdata:
  8. text+="工具名称:{}\n工具网址:{}\n详情:{}\n\n\n ".format(data.get("keyword_name"),data.get("keyword_url"),data.get("description"))
  9. dingding("新推送",text,webhook,secretKey)
  10. logging.info("消息发送完成")

测试

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

  1. name: YunP4n_Sec
  2. on:
  3. schedule:
  4. - cron: '*/5 * * * *'
  5. env:
  6. TZ: Asia/Shanghai
  7. jobs:
  8. github_monitor:
  9. runs-on: ubuntu-latest
  10. steps:
  11. - name: checkout
  12. uses: actions/checkout@v3
  13. - name: Set up Python3
  14. uses: actions/setup-python@v2
  15. with:
  16. python-version: '3.6'
  17. - name: clean data
  18. run: echo "CleanKeywords=$(cat ./clean.txt)" >> $GITHUB_ENV
  19. - name: Install requirements
  20. run: |
  21. python3 -m pip install --upgrade pip
  22. pip3 install -r ./requirements.txt
  23. - name: Run YunP4n_Sec
  24. env:
  25. keywords: '漏洞扫描 内网渗透 代码审计 SQL注入 XSS 漏洞挖掘'
  26. github_token: ${{ secrets.GITHUB_TOKEN }}
  27. secretKey: "SEC33f24a184e46aecd0b2e2cad1df0457d6820cc1d75430880420aca97d54c24f6"
  28. webhook: "https://oapi.dingtalk.com/robot/send?access_token=d8c16a1142ae1e3077d05234b73826b1b65ec56c38b9ff83564e8b317f372d04"
  29. run: python3 ./main.py
  30. - name: test run
  31. run: echo ${{ env.CleanKeywords }}
  32. - name: push clean data
  33. run: |
  34. echo ${{ env.CleanKeywords }} > ./clean.txt
  35. REMOTE=https://${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
  36. git config user.email "${{ github.actor }}@users.noreply.github.com"
  37. git config user.name "${{ github.actor }}"
  38. git add .
  39. git commit -m "Add new comment"
  40. git push ${REMOTE} main

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

使用

fork仓库 https://github.com/Cl0udG0d/YunP4n_Monitor 之后

只需要修改main.yml文件中的这几个参数就行

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

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

  1. on:
  2. schedule:
  3. - cron: '*/5 * * * *'

然后就能愉快使用了

参考链接

END

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


对Github指定类目的内容进行监控和推送的更多相关文章

  1. 两种github action 打包.Net Core 项目docker镜像推送到阿里云镜像仓库

    两种github action 打包.Net Core 项目docker镜像推送到阿里云镜像仓库 1.GitHub Actions 是什么? 大家知道,持续集成由很多操作组成,比如抓取代码.运行测试. ...

  2. 基于SolrCloud的内容搜索和热点推送

    ➠更多技术干货请戳:听云博客 什么是热点 我认为热点有时效性和受众面 用户关注从低到高再到低的内容 .有公共热点和分类热点.例如医辽养老全民关注,科技汽车等只有特定的人群关注. 推送的条件 搜索频次达 ...

  3. 天兔(Lepus)监控邮件推送安装配置

    好吧,我承认官网的邮件配置教程我又没看懂,这里记录下我的配置方法 [root@HE3]# vi /usr/local/lepus/test_send_mail.py #!/usr/bin/envpyt ...

  4. 如何将本地的项目推送到github

    一.创建密钥 1.本地终端命令行生成密钥 访问密钥创建的帮助文档:https://help.github.com/en/github/authenticating-to-github/generati ...

  5. Ionic下的Jpush消息推送与内容显示

    本文测试Jpush将消息推送给手机端,手机端点击通知栏,即可看到具体的推送内容. 1.极光推送消息设置 设置附加字段: 点击发送,手机端收到消息通知. 2.手机接收到的消息通知 点击之后进入具体的页面 ...

  6. git之github推送篇

    1.创建项目  2.生成ssh密钥并设置到github 在文件夹里面右键打开git命令行,输入下面命令,然后一直回车. ssh-keygen -t rsa 生成位置在当前用户的.ssh文件夹里,带pu ...

  7. __str__被print函数调用,目的是打印类的内容到屏幕上

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #__str__被print函数调用,目的是打印类的内容到屏幕上 class APIError(): def ...

  8. 利用RandomAccessFile类在指定文件指定位置插入内容

    package File; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; ...

  9. Android初级教程反射+AIDL+内容观察者监控黑名单号码代码模板

    对于想要拦截一些莫名的陌生号码,就需要电话拦截功能与删除其电话记录功能.拦截的主要业务逻辑,分别是在一个服务里面进行:1.注册电话监听:2.取消注册电话监听(当然注册于取消是在服务里面建立一个广播接收 ...

随机推荐

  1. es6.4.2api

    这是讲数据库的数据导入到es里  所有用到了mysql! 1.依赖 <?xml version="1.0" encoding="UTF-8"?> & ...

  2. Docker容器编译安装Redis

    Docker容器编译安装Redis 1.创建容器 -i 交互模式 -d 后端运行 -h 容器的hostname --name 容器名 --network 网卡 --ip IP地址 -p 端口映射 -- ...

  3. C# List转String的办法

    2022年5月28日 初始记录 代码: String.Join(",", List.ToArray());

  4. 2.1 动为进程,静为程序 -进程概论 -《zobolの操作系统学习札记》

    2.1 动为进程,静为程序 -进程概论 目录 2.1 动为进程,静为程序 -进程概论 问1:发明进程的原因? 问2:现在计算机中的进程的定义是什么? 问3:为什么进程跟处理器的联系更密切? 问4:进程 ...

  5. java 改变图片的DPI

    代码如下: public class test01 { private static int DPI = 300; public static void main(String[] args) { S ...

  6. java包机制

  7. 5-9 Leaf 分布式ID

    Leaf 什么Leaf leaf是叶子的意思 我们使用的Leaf是美团公司开源的一个分布式序列号(id)生成系统 我们可以在Github网站上下载项目直接使用 为什么需要Leaf 上面的图片中 是一个 ...

  8. 01. MySQL__数据库分类和介绍

    数据库的分类 1. 关系型数据库 以表为数据库存储数据的单位,关系型数据库是经过数学理论验证可以保存现实生活中任何关系型的数据 2. 非关系型数据库 主要应用在一些特定场景,解决某些具体问题比如解决高 ...

  9. MYSQL--安装2(命令行连接到数据库)

    使用命令行窗口连接 MYSQL 数据库[操作示意图]

  10. Template -「网络流 & 二分图」

    EK. 很少用到,知道思想即可. 懒得写封装的屑. queue<int> q; int Cap[MAXN][MAXN], Flow[MAXN][MAXN], Aug[MAXN], fa[M ...