自己動手打造Github代碼泄露監控工具

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的值就在如下圖位置:

authenticity_token.jpg

雖然是隱藏的,但是我們可以通過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)

以上代碼中存在另外一個send_mail函數,同樣是發送郵件的功能跟send_warning功能一樣,只是發送的內容不一樣。這裏不再贅述。這樣我們就完成了整個工具的核心部分。怎麼樣?對於老司機來說很簡單吧!

0×03 監控效果

1.運行效果

result-1.jpg2.郵件預警

result-2.jpg

 

0×04 總結

該工具的特點在於它會先使用主關鍵詞進行搜索,比如公司域名、郵箱、人員姓名等等。然後再從結果中去搜索使用者自定義的payload,如Password,User,Database等等。另外配合crontab可以做到每天進行搜索然後進行預警,但是建議每天運行2次,以防觸發Github的反爬機制。其實寫工具並不難,多思考,多練習,人人都是開發大佬。最後感謝@0xbug大佬的Hawkeye帶來的靈感和參考。最後完整代碼參考https://github.com/Hell0W0rld0/Github-Hunter。各位大佬請輕拍!謝謝!

reference:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章