tips

Code bẩn #1

Tl;dr: viết một (quick, dirty and easy) script để tìm kiếm/theo dõi keywords trên GitHub.


Câu chuyện bắt đầu khi mình vô tình tìm được một vài “lỗi” dạng information disclosure trên GitHub của một công ty ở VN. Information disclosure thì cũng có this có that, dăm ba cái full path, version,… thì thôi bỏ đi, chứ những thứ sensitive như là hardcode secret, API keys, authorization token,… thì đáng được đưa vào report. Developers của công ty này, uhm, thường xuyên push code lên GitHub và sẵn tiện thì hay kèm thêm username/password/URL/token… trong repository luôn. Ờ thì, thấy lỗi, tìm cách report, may mắn thì có bounty, không may thì nhận lời cám ơn, không may nữa thì bị bơ luôn, chuyện bình thường. Chuyện sẽ không có gì để nói nếu developers của bên công ty đó không chơi trò mèo vờn chuột với mình: mình phát hiện lỗi, report cho công ty, họ gỡ xuống, vài hôm sau lại thấy ông khác đẩy code khác lên, vẫn có “hàng nóng” kèm theo, lại report. Ban đầu mình tìm thủ công, sau đó thấy bên này lặp đi lặp lại khoảng gần chục lần, nên mình nảy ra ý tưởng là đi tìm tool hoặc viết tool tìm tự động cho nhanh.

Thực ra ý tưởng này hoàn toàn không mới, bằng chứng là khi đi dạo một vòng trên GitHub bạn có thể dễ dàng tìm được những tool/script với công dụng tương tự và hoạt động rất hiệu quả, đã được dùng từ rất lâu rồi, ví dụ như gitleaks, gitGraber,… Chính GitHub cũng đề cập cũng như cảnh báo việc developer ném sensitive information lên GitHub, và cho phép secret scanning đối với cả public lẫn private repository để hạn chế tình trạng trên. Nhưng kết quả thì cũng không khá hơn là bao, đơn giản thôi, vì ai cũng có lúc mắc sai lầm.

Tuy nhiên, có vài điểm trong các tool public này hơi không đúng ý mình lắm, sửa lại thì cũng được nhưng khá mất công, mình thì lười, nên thôi, viết script tìm luôn cho nhanh. Như đã đề cập ở trên, developers có thói quen vứt sensitive information lên GitHub, và trong code push lên thường có mention đến domain, nên mình sẽ thực hiện tìm kiếm chủ động, và theo dõi (monitor) các keyword liên quan đến domain của công ty (target) mình nhắm đến. Không phải lúc nào mình cũng rảnh để vào GitHub search rồi sort theo recently indexed, nên mình code một (quick and dirty) script để làm hộ. Ý tưởng của mình rất đơn giản: tìm kiếm thông tin về domain (keyword) của target bằng cách search trên GitHub, đếm số lần xuất hiện của keyword, lưu vào một database, cho chạy cronjob. Nếu số lần xuất hiện của keyword thay đổi nghĩa là vừa có code mới được push lên, lúc này database sẽ được update số lần xuất hiện của keyword, đồng thời sẽ có thông báo qua Slack/Telegram/Discord,… mình chỉ việc vào check repository mới nhất có chứa keyword bằng link Slack/Telegram/Discord vừa send.

Trong các quảng cáo thường có câu: “Đọc kỹ hướng dẫn sử dụng trước khi dùng”, cá nhân mình thấy câu này xứng đáng 10 điểm. RTFM, ta biết được GitHub có cung cấp Search API đầy đủ và rõ ràng cho chúng ta sử dụng, chỉ cần vào Developer settings tạo cho mình một Personal access token với permission phù hợp. Trường hợp này mình chỉ muốn search theo keyword thì đơn giản chỉ cần dùng:

import requests

url = 'https://api.github.com/search/code?q="%s"'
header = {'Authorization': 'token github-personal-access-token'}
r = requests.get(url % keyword, headers=header)

Ở response sẽ có rất nhiều thông tin, tuy nhiên mình chỉ cần đếm số lần xuất hiện của keyword, nên chỉ cần quan tâm field total_count.

print(r.json()['total_count'])

Phần database mình dùng thư viện mysql.connector, code kiểu như:

mydb = mysql.connector.connect(
  host='localhost',
  user='',
  password='',
  database='githubmonitor'
)

Phần send notification mình chọn Telegram, tham khảo thêm cách tạo bot tại đây. Code khá đơn giản, à mà lấy trên Google thì lại chả dễ =]]

def telegram_bot_sendtext(bot_message):
    bot_token = ''
    bot_chatID = ''
    send_text = 'https://api.telegram.org/bot' + bot_token + '/sendMessage?chat_id=' + bot_chatID + '&parse_mode=Markdown&text=' + bot_message
    response = requests.get(send_text)

    return response.json()

Đến đây thì phần cắt ghép cũng coi như xong rồi, chỉ cần thêm một chút magic nữa để script hoạt động trơn tru. Tận dụng con VPS $5/tháng sống bằng tiền donate của các bạn để chạy cron, thời gian thì tuỳ các bạn, mình thì chọn 5 phút, máy chạy chứ mình có chạy đâu mà lo. Kết quả sẽ là dạng như thế này:

Script này hoạt động tốt nhất với các trường hợp monitor một hoặc nhiều keyword/domain của một công ty cùng lúc (dạng internal hunting), nếu keyword hoặc domain đó unique nữa thì càng tốt. Ưu điểm (và cũng là nhược điểm) của phương pháp này là bạn chỉ biết được có keyword xuất hiện, còn ở đâu thì bạn phải tự check repository thủ công, do đó rất dễ gặp trường hợp false positive. Với mình thì không vấn đề gì, vì mục đích mình muốn như vậy, còn với các bạn thì tuỳ nhu cầu sử dụng thực tế mà các bạn hoàn toàn có thể phát triển thêm.

Spoiler: Bài này chỉ là bài chia sẻ, không phải bài hướng dẫn. Mình cũng không phải developer cao siêu gì, code nhanh code vội, quan trọng dùng được, nên các siêu nhân nhìn vô code sẽ rất ngứa mắt. Code này có lẽ còn chứa nhiều potential critical security issues. Code bẩn, code bẩn, code bẩn, cái gì quan trọng nhắc ba lần, nên mong các chuyên gia nếu có vô tình ghé mắt qua đây thì bỏ qua cho em, góp ý hoặc donate thì em xin nhận, còn gạch đá thì thôi, em cám ơn nhiều.

Full script: here. Good luck =]]]]


Như thường lệ, nếu bạn cảm thấy bài viết có ích thì có thể giúp mình duy trì VPS thông qua PayPal hoặc MoMo, cám ơn các bạn rất nhiều!

Happy hacking!