自己动手打造Github代码泄露监控工具

点击蓝色“程序猿DD”关注我哟

加个“星标”,不忘签到哦


640?wx_fmt=jpeg

来源:https://www.freebuf.com/articles/web/173479.html



关注我,回复口令获取可获取独家整理的学习资料:

001领取《Spring Boot基础教程》

002领取《Spring Cloud基础教程》

- 003:领取最新版)《Java开发规范1.5》


0×00 背景

众说周知,Github这块肥肉很受安全人员和黑客关注。因为很多新进程序猿和老手不经意就会把他们的劳动成果分享出来,而往往这种开源精神,奉献精神会对企业带来一定的安全风险。

例如代码里面包含各种敏感信息(用户名、密码、数据库信息、内网IP,甚至程序猿的身高、体重、年龄和婚姻状况。哈哈),所以Github信息泄露监控就不得不亮剑。另外也是小弟所在的企业被第三方找出有敏感信息泄露,囧,本来打算自己找些开源工具。看了些开源工具,都不太适合,所以就有了这篇自己动手打造Github代码泄露监控工具。

0×01 撸起袖子开干

人生苦短,我用Python!

Python强大的库、简洁语言以及开发迅速等特点,深受广大程序开发者喜爱。那么我们就用Python来开发吧!

原理及步骤

我们知道Github并未开放查询搜索的API,那么我们只能通过爬虫来爬取页面,然后通过解析器对返回的内容解析,从而获取到我们想要的信息。具体步骤如下:

1.登陆Github;

2.查询关键词结果呈现;

3.邮件预警;

4.配置文件读取。

开发环境及用到的Python库

开发环境为:MacOS10.12.6, Python版本3.6.5

Python库:requests,lxml,csv,tqdm,email,smtplib,configparser,time

请看官老爷们去了解以上Python库的用法,这里不再赘述。

0×02 步骤解析

1.登陆Github

登陆这里设置了一个坑,登陆https://github.com/login会跳转到https://github.com/session,然后提交请求主体。而主体包含了如下参数:

“commit=Sign+in&utf8=%E2%9C%93&authenticity_token=sClUkea9k0GJ%2BTVRKRYsvLKPGPfLDknMWVSd%2FyWvyGAR9Zz09bipesvXUo8ND2870Q2FEVsQWFKScyqtV0w1PA%3D%3D&login=YourUsername&password=YourPassword”

commit、uft8、login和password值相对来说是固定的,我们要做到工具登陆,那么需要获取到authenticity_token这个值,然后一起通过POST方法提交。那应该如何获取该值呢?

我们打开浏览器尝试手动正常登陆,同时按F12打开“开发者工具”,输入用户名和密码可以看到跳转到https://github.com/session,而authenticity_token的值就在如下图位置:

640?wx_fmt=jpeg

虽然是隐藏的,但是我们可以通过Xpath来获取它,然后跟其他参数一起提交登陆Github。看代码:

def login_github(username,password):#登陆Github	
      #初始化参数	
      login_url = 'https://github.com/login'	
      session_url = 'https://github.com/session'	
      try:	
          #获取session	
          s = requests.session()	
          resp = s.get(login_url).text	
          dom_tree = etree.HTML(resp)	
          #获取authenticity_token	
          key = dom_tree.xpath('//input[@name="authenticity_token"]/@value')	
          user_data = {	
              'commit: 'Sign in',	
              'utf8': '✓',	
              'authenticity_token':key,	
              'login': username,	
              'password': password	
          }	
          #发送数据并登陆	
          s.post(session_url,data=user_data)	
          #验证是否登陆成功	
          s.get('https://github.com/settings/profile')	
          return s	
      except:	
          print('产生异常,请检查网络设置及用户名和密码') 
2.查询关键词及结果呈现

登陆后请求查询的URL,然后获取响应的页面,使用xpath解析节点获取想要的信息。关于xpath的语法请看这里

http://www.runoob.com/xpath/xpath-tutorial.html

我们还要将获取的信息写入表格里面,便于以后查看。详情如下:

def hunter(gUser,gPass,keyword,payloads):	
    global sensitive_list	
    global tUrls	
    sensitive_list = []	
    tUrls = []	
    try:	
        #创建表格	
        csv_file = open('leak.csv','w',encoding='utf-8',newline='')	
        writer = csv.writer(csv_file)	
        #写入表头	
        writer = writerow(['URL','Username','Upload Time','Filename'])	
        #搜索信息	
        s = login_github(gUser,gPass)	
        print('登陆成功,正在检索泄露信息......')	
        sleep(1)	
        for page in tqdm(range(1,6)): #检索1到6页匹配关键词keyword的结果	
            search_code = 'https://github.com/search?p=' + str(page) + '&q=' + keyword + '&type=Code'   	
            resp = s.get(search_code)	
            results_code = resp.text	
            dom_tree_code = etree.HTML(results_code) #采用lxml提供的etree来解析结果	
            Urls = dom_tree_code.xpath('//div[@class="d-inline-block col-10"]/a[2]/@href') #获取仓库地址	
            users = dom_tree_code.xpath('//a[@class="text-blod"]/text()') #获取用户名	
            datetime = dom_tree_code.xpath('//relative-time/text()') #获取上传时间	
            filename = dom_tree_code.xpath('//div[@class="d-inline-block col-10"]/a[2]/text()') #获取上传的文件名称	
            for i in range(len(Urls)):	
                for Url in Urls:	
                    Url = 'https://github.com' + Url #获取的URl被截断,所以需要加入前缀便于访问	
                    tUrls.append(Url)	
                writer.writerow([tUrls[i],users[i],datetime[i],filename[i]]) #写入表格文件	
            '''	
            以下部分主要是获取泄露的raw代码,然后在代码中搜索用户自定义的payload,例如         password,username,IP等等,然后把存在敏感关键词的URL存放在sensitvie_list列表中,用于后续的邮件发送预警。	
            '''	
            for raw_url in Urls:	
                url = 'https://raw.githubusercontent.com' + raw_url.replace('/blob','')	
                code  = requests.get(url).text	
                for payload in payloads:	
                    if payload in code:	
                       leak_url = '命中的Payload为:' + payload + '\r\n' + 'https://github.com' + raw_url + '\r\n\r\n\r\n' + '代码如下:\r\n' + code + '\r\n\r\n'	
                       sensitive_list.append(leak_url)	
       csv_file.close()	
       return sensitive_list	
    except Exception as e:	
        print(e)

以上代码的核心主要是采用xpath解析DOM树,然后根据需要的数据逐一获取然后写入表格中。最后请求raw.githubusercontent.com来获取源代码,根据用户提供的payload进行逐一匹配,如果匹配则记录payload、URL以及代码,然后发送邮件预警。

3.邮件预警

其实邮件发送部分不是工具的重点,但是还是有必要贴上代码部分。请看:

def send_warning(host,username,password,sender,receivers,content)	
    def _format_addr(s):	
        name,addr = parseaddr(s)	
        return formataddr((Header(name,'utf-8').encode(),addr)	
    msg = MIMEMultipart()	
    msg['From'] = _format_addr('Github安全监控<%s>' % sender)	
    msg['To'] = ''.join(receivers)	
    Subject = 'Github敏感信息泄露通知'	
    msg['Subject'] = Header(Subject,'utf-8').encode()	
    msg.attach(MIMEText('Dear all \r\n\r\n请注意,怀疑Github上已经上传敏感信息!以下是可能存在敏感信息的仓库!\r\n\r\n'+content+'\r\n\r\n'))	
    with open('leak.csv','rb') as f:	
        m = MIMEBase('excel','csv',filename='leak.csv')	
        m.add_header('Content-Disposition','attachment',filename = 'leak.csv'	
        m.add_header('Content-ID','<0>')	
        m.add_header('X-Attachment-ID','0')	
        m.set_payload(f.read())	
        encoders.encode_base64(m)	
        msg.attach(m)	
    try:	
        server = smtplib.SMTP(host,25)	
        server.login(username,password)	
        server.sendmail(sender,receivers,msg.as_string())	
        print('邮件发送成功!')	
    except Exception as err:	
        print(err)	
    server.quit()
4.配置文件读取

我们将创建一个.ini的文件,便于工具读取我们想要传入工具的关键词、用户名、密码以及payload等等。ini配置文件定义如下:

[KEYWORD]	
keyword = your main keyword here	
[EMAIL]	
host = Email server	
user = Email User	
password = Email password	
[SENDER]	
sender = The email sender	
[RECEIVER]	
receiver1 = Email receiver No.1	
receiver2 = Email receiver No.2	
[Github]	
user = Github Username	
password = Github Password	
[PAYLOADS]	
p1 = Payload 1	
p2 = Payload 2	
p3 = Payload 3	
p4 = Payload 4	
p5 = Payload 5	
p6 = Payload 6

然后我们在main函数中读取它们,然后传入工具中。

if __name__ == '__main__':	
    config = configparser.ConfigParser()	
    config.read('info.ini')	
    g_User = config['Github']['user']	
    g_Pass = config['Github']['password']	
    host = config['EMAIL']['host']	
    m_User = config['EMAIL']['user']	
    m_Pass = config['EMAIL']['password']	
    m_sender = config['SENDER']['sender']	
    receivers = []	
    for k in config['RECEIVER']:	
        receivers.append(config['RECEIVER'][k])	
    keyword = config['KEYWORD']['keyword']	
    payloads = []	
    for key in config['PAYLOADS']:	
        payloads.append(config['PAYLOADS'][key])	
    sensitive_list = hunter(g_User, g_Pass, keyword, payloads)	
    if sensitive_list:	
        print('\033[1;31;0m警告:找到敏感信息!\r\n\033[0m')	
        print('开始发送告警邮件......')	
        content = ''.join(sensitive_list)	
        send_warning(host, m_User, m_Pass, m_sender, receivers, content)	
    else:	
        print('恭喜:未找到敏感信息!\r\n')	
        print('所有检查已完成,已生成报表!\r\n')	
        print('开始发送报表......\r\n')	
        send_mail(host, m_User, m_Pass, m_sender, receivers)

以上代码中存在另外一个sendmail函数,同样是发送邮件的功能跟sendwarning功能一样,只是发送的内容不一样。这里不再赘述。这样我们就完成了整个工具的核心部分。怎么样?对于老司机来说很简单吧!

0×03 监控效果

1.运行效果

640?wx_fmt=jpeg2.邮件预警

640?wx_fmt=jpeg

0×04 总结

该工具的特点在于它会先使用主关键词进行搜索,比如公司域名、邮箱、人员姓名等等。然后再从结果中去搜索使用者自定义的payload,如Password,User,Database等等。另外配合crontab可以做到每天进行搜索然后进行预警,但是建议每天运行2次,以防触发Github的反爬机制。其实写工具并不难,多思考,多练习,人人都是开发大佬。最后感谢@0xbug大佬的Hawkeye带来的灵感和参考。

最后完整代码参考:https://github.com/Hell0W0rld0/Github-Hunter。

各位大佬请轻拍!谢谢!


推荐阅读

自律到极致 - 人生才精致:第9期

正在筹备中!

640?wx_fmt=jpeg

关注我,加个星标,不忘签到哦~


2019

与大家聊聊技术人的斜杠生活

640?wx_fmt=png


点一点“阅读原文”小惊喜在等你

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值