標題:發現一個隱藏在我的追蹤者中的協同GitHub關注殭屍網路?

已發布:是

標籤:安全、GitHub、Python、開源

封面圖片:

描述:八個帳戶,建立日期跨越六年,追蹤者數量在 25 以內。以下是關注清單重疊分析如何揭露一個協同運作的虛假網絡,而交叉關注檢測卻完全沒有發現它。


我一直在為我的 GitHub 和 DEV.to 帳號建立個人分析工具——流量報告、機器人審計等等。今天在審計我的 97 位 GitHub 粉絲時,我注意到一些啟發式評分不太對勁。有八個帳號,建立於不同年份,都被標記為大量關注。表面上看沒什麼異常。

然後我查看了以下統計資料。

canestein   → 29,835 following  (created 2015)
hazexone    → 29,857 following  (created 2017)
domcomit    → 29,833 following  (created 2018)
kylehyne    → 29,837 following  (created 2018)
jaderytm    → 29,832 following  (created 2018)
vierystein  → 29,833 following  (created 2019)
hanyvert    → 29,839 following  (created 2020)
mariwatts   → 29,832 following  (created 2021)

八個帳號。建立時間跨越六年。關注人數在25以內。

這種模式很難用自然的方式來解釋。 GitHub 的 API 和 UI 都大規模地暴露了用戶的關注行為,而達到關注上限的帳號往往會止步於此——無論是出於設計考慮,還是因為自動化流程從未被指示繼續關注更多帳號。值得注意的是:這些帳號也可能各自獨立地達到了平台層面的關注上限。真正有趣的地方不僅在於這個上限本身,還在於關注清單重疊所揭示的隱藏訊息。

這些都是公開的 GitHub 帳號。我公佈它們的名稱是因為只有資料可複現,方法論才能得到驗證。


樸素測試失敗了——這是有意為之。

我做的第一件事就是檢查它們是否互相關注。這是典型的殭屍網路偵測方法-如果帳號來自同一操控者,它們通常會互相關注以建立相互認同。

Cross-follow matrix:
              canestein  hazexone  domcomit  kylehyne  jaderytm  vierystein  hanyvert  mariwatts
canestein         -         no        no        no        no        no          no        no
hazexone         no          -        no        no        no        no          no        no
domcomit         no         no         -        no        no        no          no        no
kylehyne         no         no        no         -        no        no          no        no
jaderytm         no         no        no        no         -        no          no        no
vierystein       no         no        no        no        no         -          no        no
hanyvert         no         no        no        no        no        no           -        no
mariwatts        no         no        no        no        no        no          no         -

全零。乾淨的矩陣。一個簡單的檢測器會在這裡停止並清除它們。

它們之間不會相互跟隨——這正是淺層探測器無法探測到它們的原因。這就是規避機制。缺乏交叉跟隨並非無辜的訊號;這是一種設計選擇。


重要訊號並非交叉跟踪

重要的訊號並非這些帳戶彼此關注,它們並沒有。重要的訊號是它們關注的外部群體幾乎完全相同。交叉關注分析完全忽略了這個聚集現象,而關注清單重疊則揭示了它的存在。

我提取了所有 8 個帳戶的完整關注清單——每個帳戶約 29,800 條記錄,總共約 238,000 條關注記錄,需要約 2,400 個分頁 API 請求——併計算了成對 Jaccard 相似度得分。

account_a       account_b         shared    jaccard    a_overlap  b_overlap
jaderytm        mariwatts          29,829    0.9998     0.9999     0.9999
kylehyne        mariwatts          29,831    0.9998     0.9998     1.0000
kylehyne        jaderytm           29,831    0.9998     0.9998     1.0000
domcomit        hanyvert           29,831    0.9997     0.9999     0.9997
canestein       jaderytm           29,828    0.9996     0.9998     0.9999
canestein       mariwatts          29,827    0.9996     0.9997     0.9998
canestein       kylehyne           29,829    0.9995     0.9998     0.9997
jaderytm        vierystein         29,810    0.9985     0.9993     0.9992
vierystein      mariwatts          29,810    0.9985     0.9992     0.9993
kylehyne        vierystein         29,812    0.9985     0.9992     0.9993
canestein       hanyvert           29,813    0.9984     0.9993     0.9991
domcomit        jaderytm           29,808    0.9984     0.9992     0.9992
domcomit        mariwatts          29,807    0.9983     0.9991     0.9992
domcomit        kylehyne           29,809    0.9983     0.9992     0.9991
canestein       vierystein         29,808    0.9983     0.9991     0.9992
canestein       domcomit           29,807    0.9982     0.9991     0.9991
jaderytm        hanyvert           29,807    0.9981     0.9992     0.9989
hanyvert        mariwatts          29,807    0.9981     0.9989     0.9992
kylehyne        hanyvert           29,809    0.9981     0.9991     0.9990
domcomit        vierystein         29,789    0.9971     0.9985     0.9985
vierystein      hanyvert           29,788    0.9968     0.9985     0.9983
hazexone        domcomit           29,732    0.9925     0.9958     0.9966
hazexone        hanyvert           29,730    0.9921     0.9957     0.9963
hazexone        vierystein         29,708    0.9909     0.9950     0.9958
hazexone        jaderytm           29,707    0.9908     0.9950     0.9958
hazexone        mariwatts          29,706    0.9908     0.9949     0.9958
hazexone        kylehyne           29,708    0.9907     0.9950     0.9957
canestein       hazexone           29,706    0.9907     0.9957     0.9949

Jaccard相似度達到0.99以上代表兩組資料幾乎完全相同。該聚類中的每一對資料的Jaccard相似度都高於0.99

聚類層面的結果:

8 位成員同時關注了 29,682 個帳號。

六年間建立了八個帳戶,這些帳戶都基於幾乎相同的約 29,800 個 GitHub 使用者清單。這種模式符合由相同操作員、相同自動化流程或相同種子清單來源所建立的情況。我將其視為協調行為的證據,而非帳戶控制者的證據。


閱讀證據

這些是建立於 2015 年至 2021 年的舊帳戶,並非新建立的一次性帳戶。舊帳戶之所以能通過基本的信任驗證,是因為它們似乎有歷史記錄。至於這些帳戶是故意建立的,還是已被盜用或重新利用,目前尚無定論。但從偵測的角度來看,這正是淺層啟發式演算法無法辨識它們的主要原因。

不存在交叉關注-它們之間不會互相關注。無論是有意為之或自動化程式編寫方式的必然結果,其效果都是一樣的:它繞過了最常用的網路偵測方法。

相同的種子清單——約 29,682 個共同關注者是經營者的目標清單。我在其中。其他約 29,681 位 GitHub 用戶也在其中。維護關注約 30,000 位開發者的舊帳戶的實際用途包括:洗白互動(增加用於網路釣魚或垃圾郵件活動的帳戶的追蹤者數量)、為植入惡意軟體的倉庫提供社會認同,或作為「知名」GitHub 帳戶轉售。此處的具體發現是共享的種子清單本身。其下游用途為推斷。

他們忽略的關鍵訊息——專注於清單重疊。當你避免交叉關注但仍然使用相同的種子清單時,重疊部分就成了辨識特徵。集群中的帳戶越多,訊號就越強——也就越難在不破壞產品的情況下進行追溯性隨機化。


其他解釋和誤報

在將某種現象稱為協調現象之前,值得探討還有什麼其他因素會導致這種模式。

這些帳號有可能各自獨立關注同一份熱門名單嗎?對於一兩對帳號,如果重疊度適中,則有可能。但考慮到八個帳號建立時間相隔數年,且涉及 29,800 個帳號,Jaccard 係數為 0.9998,這種可能性不大。

是否有可能使用了共享導入工具或瀏覽器擴充功能?理論上是這樣。但這仍然意味著有共享的自動化流程——換個說法就是協調。

這些帳號中會不會有某個合法帳號剛好導入了大量追蹤者?個別帳戶有可能。但集群層面的結果——所有八個帳戶都共享 29,682 個共同帳戶——排除了這只是群體層面的巧合。

我並非在證明惡意意圖或所有權。我只是在記錄一種統計上異常的模式,這種模式與有組織的虛假行為相符,而與自然獨立的活動不符。


檢測方法

簡單的殭屍網路偵測方法會檢查哪些帳號互相關注。老練的攻擊者可以繞過這種方法,但他們很難繞過關注清單——因為種子清單本身就是最終目標。更改種子清單就失去了意義。

方法:

  1. 透過共享的行為特徵辨識候選集群—遵循計數上限和帳戶年齡分佈。

  2. 獲取所有候選人的完整下標列表

  3. 計算成對 Jaccard 相似度

  4. 利用聚類級交集找到共同種子

信號解讀:

傑卡德區間 | 解讀 |

|---|---|

| < 0.50 | 無顯著重疊 — 可能獨立 |

| 0.50 – 0.80 | 可能存在共享訊號源,訊號較弱 |

| 0.80 – 0.95 | 可疑-需深入分析 |

| 0.95 – 0.99 | 可能需要協調 — 共享自動化或種子清單 |

| > 0.99 | 強協調訊號-近乎相同的跟隨行為 |

這適用於任何透過 API 公開追蹤清單的平台。


程式碼

執行此腳本前請注意速率限制:每個帳戶取得約 29,800 筆關注記錄大約需要 300 次 API 呼叫。 GitHub 的認證使用者每小時呼叫次數上限為 5,000 次。 8 個帳戶以這種規模執行,呼叫次數將接近上限——如果您的叢集規模更大,請將呼叫分散到不同的速率限制視窗內。 GitHub 也會對快速連續的請求實施二級速率限制,獨立於每小時的上限。如果遇到403429錯誤,請在重試之前遵循Retry-After標頭。對於大型集群,將頁面之間的time.sleep()值從0.1增加到0.5會更安全。

完整的審計腳本位於BANANA_TREE目錄中。核心邏輯:

import urllib.request, json, os, time
from itertools import combinations

token = os.environ.get("GH_TOKEN")
headers = {
    "Authorization": f"token {token}",
    "Accept": "application/vnd.github.v3+json",
    "User-Agent": "gh-botnet-audit"
}

def get_following(login):
    following = set()
    page = 1
    while True:
        url = f"https://api.github.com/users/{login}/following?per_page=100&page={page}"
        req = urllib.request.Request(url, headers=headers)
        with urllib.request.urlopen(req, timeout=20) as r:
            data = json.loads(r.read())
        if not data:
            break
        following.update(u['login'] for u in data)
        if len(data) < 100:
            break
        page += 1
        time.sleep(0.1)
    return following

def jaccard(a, b):
    intersection = len(a & b)
    union = len(a | b)
    return intersection / union if union else 0

following_sets = {}
for login in cluster:
    following_sets[login] = get_following(login)

for a, b in combinations(cluster, 2):
    shared = len(following_sets[a] & following_sets[b])
    j = jaccard(following_sets[a], following_sets[b])
    print(f"{a:<20} {b:<20} shared={shared} jaccard={j:.4f}")

common = set.intersection(*following_sets.values())
print(f"Followed by ALL accounts: {len(common)}")

執行命令: python3 gh_botnet_audit.py GnomeMan4201


報告

我已經透過 GitHub 的濫用舉報系統向其舉報了這個集群,並提供了帳戶名稱、Jaccard 分數和 29,682 個共同追蹤者數量作為佐證。

在您自己的追蹤者中尋找候選集群:

  • 多個帳號的粉絲數量異常相似

  • 追蹤者數量超過 500,但沒有相應的追蹤者比例。

  • 帳戶年齡跨越數年(可作為規避訊號,但僅憑這一點尚不足以得出結論)

重疊分析將啟發式方法轉化為可辯護的結論。啟發式方法告訴你該從哪裡開始。而杰卡德矩陣則是你最終呈現在報告中的內容。


工具

本研究中所使用的所有工具均位於BANANA_TREE

  • gh_botnet_audit.py — GitHub 追蹤者評分 + 重疊分析

  • traffic_report.py — GitHub + DEV.to 分析,只需一次終端執行即可完成

  • 僅使用 Python 標準函式庫—無外部依賴


這最初源自於一次奇怪的追蹤者審核結果。但真正的啟示遠不止於此:當協同運作的帳號刻意避免彼此間明顯的關聯時,共同的目標群體就成了它們的指紋。交叉關注可以告訴你哪些帳號之間有連結。關注清單的重疊部分可以告訴你哪些帳號是源自同一張地圖。

文中提到的帳號均為公開的 GitHub 個人資料。如果您也對自己的追蹤者進行過類似的分析,並發現與此種子清單中的帳號有重疊,請留言——我很想知道這個網路的實際覆蓋範圍有多廣。


第二部分現已發布:我發現了一個 GitHub 關注殭屍網絡,然後我找到了幕後操縱者。


原文出處:https://dev.to/gnomeman4201/i-found-a-coordinated-github-follow-botnet-hiding-in-my-followers-kgl


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝17   💬11   ❤️1
585
🥈
alicec
📝1   ❤️2
81
🥉
我愛JS
💬2  
7
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登